ThinkPHP5.1.x SQL注入(orderby注入)

漏洞概要

  • 本次漏洞存在于 Builder 类的 parseOrder 方法中,由于程序没有对数据进行很好的过滤,直接将数据拼接进 SQL 语句,最终导致 SQL 注入漏洞的产生
  • 漏洞影响版本: 5.1.16<=ThinkPHP5<=5.1.22

初始配置

获取测试环境代码

composer create-project --prefer-dist topthink/think=5.1.22 tpdemo

在这里插入图片描述

将 composer.json 文件的 require 字段设置成如下

"require": {
        "php": ">=5.6.0",
        "topthink/framework": "5.1.22"
    },

然后执行 composer update

在这里插入图片描述

下载后的源码中,需要对 application/index/controller/Index.php 内容进行修改

<?php
namespace app\index\controller;

class Index
{
    public function index()
    {
        $orderby = request()->get('orderby');
        $result = db('users')->where(['username' => 'mochazz'])->order($orderby)->find();
        var_dump($result);
        return '<style type="text/css">*{ padding: 0; margin: 0; } div{ padding: 4px 48px;} a{color:#2E5CD5;cursor: pointer;text-decoration: none} a:hover{text-decoration:underline; } body{ background: #fff; font-family: "Century Gothic","Microsoft yahei"; color: #333;font-size:18px;} h1{ font-size: 100px; font-weight: normal; margin-bottom: 12px; } p{ line-height: 1.6em; font-size: 42px }</style><div style="padding: 24px 48px;"> <h1>:) </h1><p> ThinkPHP V5.1<br/><span style="font-size:30px">12载初心不改(2006-2018) - 你值得信赖的PHP框架</span></p></div><script type="text/javascript" src="https://tajs.qq.com/stats?sId=64890268" charset="UTF-8"></script><script type="text/javascript" src="https://e.topthink.com/Public/static/client.js"></script><think id="eab4b9f840753f8e7"></think>';
    }
}

config/database.php 文件中配置数据库相关信息,并开启 config/app.php 中的 app_debugapp_trace ,创建数据库信息如下

create database thinkphp;
use thinkphp;
create table users(
	id int primary key auto_increment,
	username varchar(50) not null
);
insert into users(id,username) values(1,'H3rmesk1t');

漏洞利用

Payload

http://127.0.0.1/cms/public/index.php?orderby[id`|updatexml(1,concat(0x7,user(),0x7e),1)%23]=1 

在这里插入图片描述

漏洞分析

首先数据都会进入到 Request 类中的 input 方法,并且经过 filterValue 方法的过滤和强制类型转换并返回 $data

在这里插入图片描述

这里 array_walk_recursive 函数对数组中的成员递归调用 filterValue 过滤函数,但是 filterValue 过滤函数,不过滤数组的 key , 只过滤了数组的 value,用户输入的数据会原样进入框架的 SQL 查询方法中,进入 Query

在这里插入图片描述

在这里插入图片描述

恶意Payload 未经过任何过滤直接传递给 options['order']

在这里插入图片描述

接着调用 find 方法,此处 $this->connectionthink/db/connectior/Mysql 类 ,继承于 Connection 类,于是此处继续调用该类的 find 方法

在这里插入图片描述
在这里插入图片描述

该方法继续调用了 $this->builder, 即 think/db/builder/Mysql 类的 select 方法,该方法通过 str_replace 函数,将数据填充到SQL语句中

在这里插入图片描述

然后调用了 parseOrder 方法,跟进该方法,$order 是输入的数据,然后经过了 parseKey 方法处理后返回给 $array,跟进查看该方法的实现

protected function parseOrder(Query $query, $order)
    {
        if (empty($order)) {
            return '';
        }

        $array = [];

        foreach ($order as $key => $val) {
            if ($val instanceof Expression) {
                $array[] = $val->getValue();
            } elseif (is_array($val)) {
                $array[] = $this->parseOrderField($query, $key, $val);
            } elseif ('[rand]' == $val) {
                $array[] = $this->parseRand($query);
            } else {
                if (is_numeric($key)) {
                    list($key, $sort) = explode(' ', strpos($val, ' ') ? $val : $val . ' ');
                } else {
                    $sort = $val;
                }

                $sort    = strtoupper($sort);
                $sort    = in_array($sort, ['ASC', 'DESC'], true) ? ' ' . $sort : '';
                $array[] = $this->parseKey($query, $key, true) . $sort;
            }
        }

        return ' ORDER BY ' . implode(',', $array);
    }

跟进 thinkphp/library/think/db/builder/Mysql.php,该方法在变量 $key 的两端添加了反引号进行拼接并且没有任何过滤

在这里插入图片描述

最终返回了一个带有 ORDER BY 的 SQL 注入 payload 给要执行的SQL语句,实现 ORDER BY 注入

在这里插入图片描述

完整的方法调用,从下往上

在这里插入图片描述

漏洞修复

官方的修复方法是:在拼接字符串前对变量进行检查,看是否存在 )、# 两个符号

在这里插入图片描述

攻击总结

参考Mochazz师傅的审计流程

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值