Sure Security Team - 西凯|关注网络安全

ThinkPHP框架<5.0.16 sql注入漏洞详细分析


0x01 前言


之前有看到某大牛发的一篇审计thinkphp的文章,于是乎就想写一个分析流程。之前看到过chybeta发的一篇分析文章感觉也不错。分析过程,我也会做thinkphp部分功能的解析。

   

0x02 环境搭建和漏洞复现


程序下载地址:

https://www.thinkphp.cn/down/1126.html
PHPstudy:Apache+php5.6+MySQL
工具:PHPstorm

1、首先建立一个数据库名为:thinkphp

2、建立一个表名为:user

3、添加三个字段:id,name,password


4、在thinkphp的数据库文件填上刚才我们建立的数据库信息:

文件位置:\thinkphp\application\database.php


5、打开thinkphp的调试模式:

文件位置:\thinkphp\application\config.php


6、简单写一个update功能,某大牛用到了模型,这里就简单写一个例子就行了。

文件位置:

\thinkphp\application\index\controller\Index.php


<?php

namespace app\index\controller;

class Index

{    

    public function index()    

   {        

        $password = input('get.password/a');

db('user')->where(['id'=>1])->update(['password'=>$password]);     

             } 

        }


这里用到了thinkphp的助手函数input(),是专用来接收get,post等的值。具体可以看:https://www.kancloud.cn/manual/thinkphp5/118044


还有就是thinkphp的数据库操作,框架本身写好了我们调用就比较方便。所以为什么那么多人用框架去开发程序,快捷而且安全,不过也会有安全问题,就像本次分析的这个sql漏洞,不过如果是新手的话总比自己写的好,对吧。
具体可以看链接:

https://www.kancloud.cn/manual/thinkphp5/135178


7、现在就可以访问我们的payload了:

https://thinkphp.test/thinkphp/public/index.php?password[0]=inc&password[1]=updatexml(2,concat(0x7e,user()),0)&password[2]=1



0x03 漏洞分析

   

1、这里用phpstorm+debug来动态分析,有不懂配置的可以访问我写一篇配置文章:

利用phpstorm+xdebug进行断点调试
我们在主函数下一断点:


然后访问我们payload,它会跳到入口文件,我们只要分析的是sql执行的地方,所以我们直接F8跳到执行sql地方:



2、我们继续跟进到loader.php它会包含thinkphp的Db.php文件,


接下还会包\thinkphp\library\think\db\connector\Mysql.php文件,主要是连接数据库的操作,这里就直接跳过了。别分析分析把自己绕进去了,我只是在这里讲诉下过程,我们还是直接分析sql执行的部分吧。

3、我们跳到update执行的部分,文件位置:\thinkphp\library\think\db\Query.php



继续往下看,这句是执行我们sql的地方:


4、我们F7跟进去,跳到文件位置\thinkphp\library\think\db\Builder.php
parseTable函数直接F8往下执行了,这函数是处理table分析的,主要还是parseData函数,我们继续F7跟进


5、我们继续往下跟进


我们看到了这里如果传入的值为数组形式的话,并且第一个参数为inc就执行switch所对应的的语句。


可以看到这里函数对我们传入的值没有做任何处理,返回内容仍然是我们的语句:


跟到后面返回的执行sql语句:


执行完,我们跟进到报错的地方,说明我的语句执行成功:


6、到这里就差不多结束了,有人问,为什么要这样给数组三个字段?
因为我们刚才传入数组的地方,分别有三个数组


到后面返回$result的时候就组合在一起了:


下面是parseData的代码:

protected function parseData($data, $options)   

  {        if (empty($data)) {   

         return []; 

       }    

    // 获取绑定信息        

   $bind = $this->query->getFieldsBind($options['table']);      if ('*' == $options['field']) {      

      $fields = array_keys($bind);      

     } else {     

       $fields = $options['field'];    

    }    

    $result = [];    

    foreach ($data as $key => $val) {    

        $item = $this->parseKey($key, $options); 

if (is_object($val) && method_exists($val, '__toString')) {               

     // 对象数据写入          

      $val = $val->__toString();      

      }      

      if (false === strpos($key, '.') && !in_array($key, $fields, true)) {       

         if ($options['strict']) {         

           throw new Exception('fields not exists:[' . $key . ']');                }      

      } elseif (is_null($val)) {     

           $result[$item] = 'NULL';       

     } elseif (is_array($val) && !empty($val)) {                         switch ($val[0]) {             

       case 'exp':            

            $result[$item] = $val[1];             

           break;            

        case 'inc':            

      $result[$item] = $this->parseKey($val[1]) . '+' . floatval($val[2]);           

             break;       

             case 'dec':          

              $result[$item] = $this->parseKey($val[1]) . '-' . floatval($val[2]);         

               break;                }       

     } elseif (is_scalar($val)) {          

      // 过滤非标量数据          

      if (0 === strpos($val, ':') && $this->query->isBind(substr($val, 1))) {      

              $result[$item] = $val;                } else {                    $key = str_replace('.', '_', $key);       

             $this->query->bind('data__' . $key, $val, isset($bind[$key]) ? $bind[$key] : PDO::PARAM_STR);                    $result[$item] = ':data__' . $key;                }            }        }        return $result;    }

   

0x04 结束

   

如果看不懂的,可以先去了解一下thinkphp这个框架,其他框架大同小异。如果里面一些PHP代码看不懂的话,可以去复习下PHP。

评论

小成功依靠个人,大成功依靠团队,天下没有完美的个人,只有完美的团队。