thinkphp3.2.5的一个伪0day
x1a0t 发表于 四川 漏洞分析 903浏览 · 2024-05-20 17:21

前言

话还要从一次渗透测试任务说起,根据目标指纹在github上找到了某套基于thinkphp3的代码,登录口的代码大概长这样子:

<?php
namespace Home\Controller;

class IndexController {

    public function login() {
        $param = I('post.');
        $param['password'] = md5($param['password']);
        $data = M('Users')->where($param)->find();
    }
}

可以看到这里直接将POST数组传入了where(函数,这种操作是不是很眼熟呀Laraval有过这种问题,貌似CI还是YII也有过(不记得了)

分析代码

忽略可能导致的业务逻辑漏洞,这里极有可能存在sql注入问题,直接使用tp3.2.5的代码做为演示,跟入代码到ThinkPHP/Library/Think/Model.class.php

这里将传入的$_POST数组最终存放到了$this->options['where']就结束了,返回Model类

之后会进入到增删该查的sql语句构建代码中,示例代码用的是find(,跟入代码:

上图红框的位置判断了find(数组参数的键,也就是对之前sqli注入的修复

蓝色箭头是对$this->options['where'](这里也就是$_POST数组),根据数据表中的的字段类型进行相应的强制转化

这里值得注意的是,只针对数据表里有的字段进行类型转化,如果传入xxx=123之类的并不会被删除过滤,但后面会怎么处理呢?

回到蓝色箭头后面红色箭头处的函数select(,一直跟入src/ThinkPHP/Library/Think/Db/Driver.class.php

Think\Db\Driver->select
Think\Db\Driver->buildSelectSql
Think\Db\Driver->parseSql
Think\Db\Driver->parseWhere

最终来到Think\Db\Driver->parseWhere(

传入的部分$_POST数组现在是$where,可以看到箭头处中对以_为前缀的键有特殊处理,跟进parseThinkWhere(方法

这里声明了三种键值的不同处理方式,最终成为sql的where语句,这三种方式均可被利用,这里展示利用_string_complex进行sql注入


剩下_query有兴趣的师傅可自行尝试利用

参考

https://www.leavesongs.com/PENETRATION/cachet-from-laravel-sqli-to-bug-bounty.html

0 条评论
某人
表情
可输入 255
目录