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

Posted H3rmesk1t

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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师傅的审计流程

以上是关于ThinkPHP5.1.x SQL注入(orderby注入)的主要内容,如果未能解决你的问题,请参考以下文章

SQL注入 order by后的注入(Less-46)

sql注入中order by的作用

sql注入 and 确认了注入点,但order by 无论多少都不会报错 是啥原因?

sql注入进阶-报错注入盲注order by注入二次注入SQL注入绕过速查表

1015.WebGoat SQL注入之 Order by注入解题思路

如何在 order rails 查询中修复 sql 注入