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

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

ThinkPHP5.1.x SQL注入(orderby注入)_第1张图片

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

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

然后执行 composer update

ThinkPHP5.1.x SQL注入(orderby注入)_第2张图片

下载后的源码中,需要对 application/index/controller/Index.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 '

:)

ThinkPHP V5.1
12载初心不改(2006-2018) - 你值得信赖的PHP框架

'
; } }

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 

ThinkPHP5.1.x SQL注入(orderby注入)_第3张图片

漏洞分析

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

ThinkPHP5.1.x SQL注入(orderby注入)_第4张图片

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

ThinkPHP5.1.x SQL注入(orderby注入)_第5张图片

ThinkPHP5.1.x SQL注入(orderby注入)_第6张图片

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

ThinkPHP5.1.x SQL注入(orderby注入)_第7张图片

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

ThinkPHP5.1.x SQL注入(orderby注入)_第8张图片
ThinkPHP5.1.x SQL注入(orderby注入)_第9张图片

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

ThinkPHP5.1.x SQL注入(orderby注入)_第10张图片

然后调用了 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 注入

ThinkPHP5.1.x SQL注入(orderby注入)_第11张图片

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

ThinkPHP5.1.x SQL注入(orderby注入)_第12张图片

漏洞修复

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

ThinkPHP5.1.x SQL注入(orderby注入)_第13张图片

攻击总结

参考Mochazz师傅的审计流程

ThinkPHP5.1.x SQL注入(orderby注入)_第14张图片

你可能感兴趣的:(#,ThinkPHP代码审计,thinkphp,代码审计,SQL注入)