HacKerQWQ的博客空间

2020-网鼎杯-青龙组-Web

Word count: 596Reading time: 2 min
2020/08/13 Share

AreUSerialz

源码:

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
79
80
81
<?php

include("flag.php");

highlight_file(__FILE__);

class FileHandler {

protected $op;
protected $filename;
protected $content;

function __construct() {
$op = "1";
$filename = "/tmp/tmpfile";
$content = "Hello World!";
$this->process();
}

public function process() {
if($this->op == "1") {
$this->write();
} else if($this->op == "2") {
$res = $this->read();
$this->output($res);
} else {
$this->output("Bad Hacker!");
}
}

private function write() {
if(isset($this->filename) && isset($this->content)) {
if(strlen((string)$this->content) > 100) {
$this->output("Too long!");
die();
}
$res = file_put_contents($this->filename, $this->content);
if($res) $this->output("Successful!");
else $this->output("Failed!");
} else {
$this->output("Failed!");
}
}

private function read() {
$res = "";
if(isset($this->filename)) {
$res = file_get_contents($this->filename);
}
return $res;
}

private function output($s) {
echo "[Result]: <br>";
echo $s;
}

function __destruct() {
if($this->op === "2")
$this->op = "1";
$this->content = "";
$this->process();
}

}

function is_valid($s) {
for($i = 0; $i < strlen($s); $i++)
if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
return false;
return true;
}

if(isset($_GET{'str'})) {

$str = (string)$_GET['str'];
if(is_valid($str)) {
$obj = unserialize($str);
}

}

大概逻辑就是用$_GET[‘str’]接收参数然后序列化,用强类型比较判断$op是不是”2”,如果是”2”就改成”1”,然后进入process函数,如果$op是”1”就将$content写入$filename,并且返回结果,如果是”2”就读入$filename文件的内容并返回到页面上

解题

一开始看了很多遍,缕了很多遍逻辑,就是感觉没有漏洞,毕竟这个强类型的比较实在让人头疼,但是后面看了wp之后才知道我的思路出错了,我应该关注的是后面process函数里的弱类型(说实话我没有注意到…)比较,而不是前面的强类型比较。想通了就好说了,直接用2(数字类型的2和”2”强类型比较返回0)绕过前面的比较,而process里的”2”==2返回正确,因为是弱类型比较,所以只要自己构造一个$a对象序列化传上去就好了。

构造$a对象:

1
2
3
4
5
$a = new FileHandler();
$a->op=2;
$a->content='1234'; #因为我们是读取flag.php文件,所以这里的$content随便写点什么都可以
$a->filename="flag.php";
echo serialize($a);

str参数传入序列化后的$a对象:

CATALOG
  1. 1. AreUSerialz
    1. 1.1. 解题