代码审计:thinkphp3.2.3sql注入漏洞分析

admin 2023年11月13日23:31:16评论32 views字数 2867阅读9分33秒阅读模式

一、环境配置

  1. 源码:thinkphp-3.2.3

  2. phpstudy中开启php的xdebug插件


    代码审计:thinkphp3.2.3sql注入漏洞分析

  3. vscode配置php环境,如下,在vscode中搜索php,找到php的Executable Path,点击下面的在setting.json中编辑


    代码审计:thinkphp3.2.3sql注入漏洞分析

  4. 在setting.json中填写php的可执行文件路径


    代码审计:thinkphp3.2.3sql注入漏洞分析

  5. 在vscode的运行和调试中打开launch.json,类型选择php,进入如下界面,将xdebug的端口修改为phpstudy中设置的端口


    代码审计:thinkphp3.2.3sql注入漏洞分析

  6. 修改php.ini中的xdebug设置如下


    代码审计:thinkphp3.2.3sql注入漏洞分析

  7. 修改thinkphp的数据库配置,配置文件路径为ThinkPHP/Conf/convention.php


    代码审计:thinkphp3.2.3sql注入漏洞分析

  8. 新建一个数据库tp3.2.3,在库中新建一个表,注意这个表得和sql查询入口中写的保持一致,如下


    代码审计:thinkphp3.2.3sql注入漏洞分析

  9. 在Application目录下新建一个/Home/Controller/IndexController.class.php文件,写一个查询入口,如下。然后使用phpstudy和thinkphp3.2.3的源码在本地搭建一个网站,至此thinkphp 5.2.3的sql注入审计环境配置完成

       
    <?phpnamespace HomeController;use ThinkController;class IndexController extends Controller {   public function index(){       highlight_file(__FILE__);       $data = M('users')->find(I('GET.id'));       var_dump($data);   }}


二、漏洞分析

  1. 打开上面写好的sql查询入口,出现如下界面即代表配置无误


    代码审计:thinkphp3.2.3sql注入漏洞分析

  2. vscode中设置断点,如下


    代码审计:thinkphp3.2.3sql注入漏洞分析

  3. 浏览器中访问sql查询入口http://localhost:81/index.php/home/index/index?id=1,单步调试后到这个地方,开始传入get方法的id参数


    代码审计:thinkphp3.2.3sql注入漏洞分析

  4. 跟踪到这里,发现了filter过滤,filter使用的是默认的DEFAULT_FILTER,其值为htmlspecialchars,该函数把一些预定义的字符转换为 HTML 实体,预定义的字符是:


    • & (和号)成为 &amp;

    • " (双引号)成为 &quot;

    • ' (单引号)成为 '

    • < (小于)成为 &lt

    • >(大于)成为 &gt;



      代码审计:thinkphp3.2.3sql注入漏洞分析

  5. 继续往下存在一处参数过滤,array_walk_recursive() 函数对数组中的每个元素应用用户自定义函数,data参数为接受的用户输入参数,使用自定义的think_filter对data数据进行了过滤


    代码审计:thinkphp3.2.3sql注入漏洞分析

  6. 全局搜索think_filter,发现过滤了如下关键字,会置换为空


    EXP|NEQ|GT|EGT|LT|ELT|OR|XOR|LIKE|NOTLIKE|NOT BETWEEN|NOTBETWEEN|BETWEEN|NOTIN|NOT IN|IN


    代码审计:thinkphp3.2.3sql注入漏洞分析

  7. 继续往下,又发现一处判断


    代码审计:thinkphp3.2.3sql注入漏洞分析

  8. 进入这个函数,代码如下,会对表达式进行判断,根据表达式的不同会进入不同的if


    protected function _parseOptions($options = array()){               if (is_array($options)) {                       $options = array_merge($this->options, $options);               }
    if (!isset($options['table'])) { // 自动获取表名 $options['table'] = $this->getTableName(); $fields = $this->fields; } else { // 指定数据表 则重新获取字段列表 但不支持类型检测 $fields = $this->getDbFields(); }
    // 数据表别名 if (!empty($options['alias'])) { $options['table'] .= ' ' . $options['alias']; } // 记录操作的模型名称 $options['model'] = $this->name;
    // 字段类型验证 if (isset($options['where']) && is_array($options['where']) && !empty($fields) && !isset($options['join'])) { // 对数组查询条件进行字段类型检查 foreach ($options['where'] as $key => $val) { $key = trim($key); if (in_array($key, $fields, true)) { if (is_scalar($val)) { $this->_parseType($options['where'], $key); } } elseif (!is_numeric($key) && '_' != substr($key, 0, 1) && false === strpos($key, '.') && false === strpos($key, '(') && false === strpos($key, '|') && false === strpos($key, '&')) { if (!empty($this->options['strict'])) { E(L('_ERROR_QUERY_EXPRESS_') . ':[' . $key . '=>' . $val . ']'); } unset($options['where'][$key]); } } } // 查询过后清空sql表达式组装 避免影响下次查询 $this->options = array(); // 表达式过滤 $this->_options_filter($options); return $options; }


  9. 由于上面跟踪发现的过滤器会将常见的报错符号过滤掉,所以这里使用单引号肯定是不行的,先构造一条payload

    id=1 union select 1,database(),3#


    代码审计:thinkphp3.2.3sql注入漏洞分析

  10. 继续往下跟,进入_parseType函数,这里会对参数的类型进行检测,如果不是数字型的就会强制转换,也就是说上面构造的payload是无法绕过这里的。


    代码审计:thinkphp3.2.3sql注入漏洞分析

  11. 修改payload为数组,如下,重新断点调试,跟踪后发现成功绕过了上面的if判断,进入到了select函数


    id[where]=1 union select 1,database(),3#


    代码审计:thinkphp3.2.3sql注入漏洞分析

  12. 然后又从buildSelectSql()函数进入到了parseSql()函数


    代码审计:thinkphp3.2.3sql注入漏洞分析

  13. 进入到parseSql()函数


    代码审计:thinkphp3.2.3sql注入漏洞分析

  14. 继续往下跟,又发现一处过滤


    代码审计:thinkphp3.2.3sql注入漏洞分析

  15. 继续往下跟,进入到了parseWhere()函数


    代码审计:thinkphp3.2.3sql注入漏洞分析

  16. 继续往下看,进入parseWhereItem函数,没有特别值得关注的


    代码审计:thinkphp3.2.3sql注入漏洞分析

  17. 再往下,进入parseValue函数,这里就是对查询结果进行处理了


    代码审计:thinkphp3.2.3sql注入漏洞分析

  18. 最后跟完全部过程,发现执行成功,但是获取到的是id=1的用户数据,而不是数据库名


    代码审计:thinkphp3.2.3sql注入漏洞分析

  19. 继续修改payload如下,断点跟踪,发现注入成功,获取到了数据库名tp3.2.3


    id[where]=id=-1 union select 1,database(),3#


    代码审计:thinkphp3.2.3sql注入漏洞分析


原文始发于微信公众号(菜鸟的渗透测试之路):代码审计:thinkphp3.2.3sql注入漏洞分析

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年11月13日23:31:16
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   代码审计:thinkphp3.2.3sql注入漏洞分析http://cn-sec.com/archives/2201500.html

发表评论

匿名网友 填写信息