导言
服务端请求伪造(SSRF),简单来说就是服务器以其身份替攻击者发生任意请求,因为服务器所处的特殊网络位置,很可能有机会访问内部资源,在元环境中,可能会存在包含敏感凭证的元数据断点,造成很严重的危害
比如一个在线翻译服务,服务器需要请求用户给定的url并且翻译后将内容回显,这时服务器就需要通过自己特殊的网络位置发生请求,造成漏洞
例如刚刚在线翻译服务的那个场景,攻击者唯一可控的只有url,那么怎么利用url达成攻击呢
答案是协议,Web攻击可以达到的效果,取决于可控参数传入的函数,支持的功能,除了http,https协议,还有很多其他的协议可以利用
上图是curl支持的协议
我们可以这里理解ssrf攻击
curl类似一个函数,会把我们传入的url转成对应的tcp或udp报文,发送到对应的host和端口,
我们要利用可控的url操作curl生成的报文,然后对内网的服务进行攻击
我们容易想到我们可以操控得到的流量会有三者情况
可交互的tcp流
这种应该只会在极其特殊的情况下才会出现
完全可控的一次tcp流
只可以发送一次,但是内容完全可控,这种会在c协议出现,或者在对ftp服务器的进一步利用出现
受限的部分可控的一次tcp流
dict协议,http,https协议都有可能出现这种情况
##可利用的协议
file协议
file协议可以直接读取文件
1 | % curl file:///etc/passwd |
gopher
Gopher协议是internet的一个信息查找系统,他出现在www之前,现在支持gopher协议的客户端已经越来越少了
但是他是可以达到完全可控的一次tcp流,这个效果的,可以说是攻击面最广的一个协议了,http的post请求,redis的设置请求,都可以伪造
1 | gopher://127.0.0.1:4002/_%65%76%61%6c%5f%64%61%74%61 |
格式为gopher://127.0.0.1:4002/_后面是要传输内容的url编码

1 | import socket |
可以使用这个脚本,转发并且记录流量,转成gopher的形式
dict协议
dict协议是词典网络协议,url-path部分的字符会直接发送,达到受限的部分可控的一次tcp流攻击效果,但是无法加入一些特殊字符,无法换行,攻击效果受限,常用来攻击redis
CRLF攻击
CVE-2019-9740urllib2 in Python 2.x through 2.7.16 and urllib in Python 3.x through 3.7.3都曾出过CRLF漏洞
CVE-2016-5699Python 2.7.10之前的版本和3.4.4之前的3.x 版本中的 urllib2和urllib中的‘HTTPConnection.putheader’函数存在CRLF注入漏洞
http协议
因为http应用很光,单纯http协议,也可以攻击部分web内网应用,如果docker开启了tcp监听,也可以进行攻击
ftp协议
- 利用被动模式
在hxp-2020resonator/
1 | <?php |
出现的这样一个利用姿势,利用一个恶意的ftp服务器,当php使用file_put_contents向ftp服务器上传数据时,服务器开启被动模式,返回127.0.0.1:9000 这个地址,内容就被发往本地的fpm服务器,造成rce
利用ftp主动模式
在starctf2021/web-oh-my-bet,出现了这样一个姿势
在python的pyftpdlib启动的ftp服务器中,如果配置
1
handler.permit_foreign_addresses = True
既ftp服务器在主动模式中,对用户来源ip地址和用户主动模式给出ip地址不做校验
则可以恶意用户则可以连接ftp服务器,上传恶意文件后,使用主动模式下载,这是给服务器恶意内网地址,造成攻击,
如果内网有ftp服务器,利用ftp服务器对tcp流的容错,则可以,受限的部分可控的一次tcp流,转成把完全可控的一次tcp流
TLS协议
https://i.blackhat.com/USA-20/Wednesday/us-20-Maddux-When-TLS-Hacks-You.pdf
利用tls的会话复用机制,可以实现ssrf只要支持https协议,就可以造成受限的部分可控的一次tcp流攻击
可攻击的应用
本质上来说,只要在内网监听了端口,都有可能被攻击,但是因为协议中可控内容有限,还是有一些限制 的,
redis
1 | docker run -d -p 6379:6379 ju5ton1y/redis |
redis使用的是RESP (REdis Serialization Protocol),本质上只是规定了将命令行命令转为tcp传输的封装方式
1 | auth 123123 |
并且redis是支持管道操作的,也就是说可以一次发生多次操作,而不需要等待服务器回复
而且redis认证的本质也是请求前,发送了上述auth命令,也就是说,如果你通过其他途径得到了redis密码,或者进行爆破,有认证的redis也是可以被攻击的
在我实验的redis_version:3.2.11中,redis对
1 | POST, |
做了检测,如果匹配到会直接结束连接,应该是为了防止http POST或者crlf攻击redis,但是redis没有banGET
在python的CVE-2016-5699CRLF注入中,因为payload是注入在Host之后,所以无法攻击,虽然它可以通过SNI注入,去掉GET,但是因为有特殊字符的问题,redis也无法攻击.
python的 CVE-2019-9740,CRLF注入,因为是url处,所以可以攻击redis
攻击姿势
参考
https://paper.seebug.org/1169/#_1
https://www.anquanke.com/post/id/214108#h3-12
比较常见的利用姿势的有写文件,利用主从复制getshell,或者改数据触发反序列化,或者低版本的rce等
https://redis.io/topics/protocol
https://www.anquanke.com/post/id/181599#h2-2
https://www.anquanke.com/post/id/214108#h3-15
docker
可以看p神这篇文章
https://mp.weixin.qq.com/s/X04IhY9Oau-kDOVbok8wEw
如果docker配置了监听tcp端口,则可以通过ssrf攻击,只要有可控的http的post方法,就可以造成rce,利用create和exec的姿势需要path和body都可控,p神在这篇文章中
uWSGI
通过ssrf攻击uWSGI实现rce,
因为在uwsgi的协议中,允许传递一些魔术变量,调整参数,利用UWSGI_FILE变量,可以动态加载新的文件执行,并且uWSGI程序中默认注册了一系列schemes,可以通过这些schemes直接进行rce
https://github.com/wofeiwo/webcgi-exploits/blob/master/python/uwsgi-rce-zh.md
php-fpm
一般监听9000端口通过完全可控的一次tcp流可以rce,一般利用方法为
1 | { |
FastCGI 协议可以通过PHP_ADMIN_VALUE和PHP_VALUE指定php配置值,通过配置自动包含php://input,而进行rce
参考资料
https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Request%20Forgery