当前位置:   article > 正文

TP5 框架 SQL 执行流程分析及 5.0.9 SQL 注入漏洞分析_tp5 find() 注入

tp5 find() 注入

SQL查询流程

TP5手册:https://www.kancloud.cn/manual/thinkphp5/118044

在分析 tp5 漏洞之前,先来看一看 tp5 在查询时的流程,与 tp3 有什么异同,写一个控制器

<?php
namespace app\index\controller;

class Index
{
    public function index()
    {
        $name = Input("name/d");
        $data = db("test")->where("name",$name)->find();
        dump($data);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

tp5 输入输入使用 Input 函数,代替 tp3 中使用的 I 函数,Input 函数有一个功能可以使用变量修饰符对输入数据进行转换

ThinkPHP5.0版本默认的变量修饰符是/s,如果需要传入字符串之外的变量可以使用下面的修饰符,包括:

修饰符作用
s强制转换为字符串类型
d强制转换为整型类型
b强制转换为布尔类型
a强制转换为数组类型
f强制转换为浮点类型

image-20220116140006221

接下来看看 Sql 查询分析,tp5 使用了 pdo 预编译,基本流程如下,有效防止 SQL 注入

  1. prepare($SQL) 编译 SQL 语句
  2. bindValue( p a r a m , param, param,value) 将 value 绑定在 param 的位置上
  3. execute 执行

find 函数中有整个 pdo 查询流程

image-20220116160023300

生成查询 SQL

image-20220116154929359

获取参数绑定

image-20220116155210373

执行查询

image-20220116160119102

image-20220116160220929

TP 5.0.9 SQL注入

5.0.9 及以下版本如果开启了 debug 都存在这个漏洞,危害较低,不能子查询,只能泄露一些信息,如 user()、database() 等

控制器

class Index
{
    public function index()
    {
        $name = Input("name/a");
        $data = db("test")->where("name","in",$name)->select();
        dump($data);
     }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

payload

?name[0,updatexml(0,concat(0xa,database()),0),0]
  • 1

image-20220116184326085

database 同时还会泄露数据库配置信息

image-20220116184406432

基础的调试流程

where() -> select -> parseWhere() -> buildWhere()
  • 1

这里直接进入 buildWhere()

image-20220118193206956

if 都不进入,到最后

image-20220118193335828

进入 parseWhereItem()直接看重点

image-20220118195143551

因为 $exp 是 in,满足条件进入 if,foreach 遍历拼接 $bindKey

$bindKey = $bindName . '_in_' . $k;
$bindKey = where_name_in_0,updatexml(0,concat(0xa,database()),0),0
  • 1
  • 2

最终 return wherestr

$whereStr = `name` IN (:where_name_in_0,updatexml(0,concat(0xa,database()),0),0)
  • 1

完整的 sql 语句

image-20220118214141062

:where_id_in_的后面,直接拼接传入的 id 的键,并没有进行过滤,可以造成 SQL 注入

主要问题是 tp5 使用了 pdo,正常来说不会出现注入,但是这里缺可以报错注入,而且正常 pdo 执行流程为三步(上边介绍了),但是这里在 prepare 截断就执行了 SQL 查询

image-20220118214318743

原因如下:

PDO::ATTR_EMULATE_PREPARES  => false
  • 1

这个选项涉及到 PDO 的“预处理”机制:

因为不是所有数据库驱动都支持 SQL 预编译,所以 PDO 存在“模拟预处理机制”。如果说开启了模拟预处理,那么 PDO 内部会模拟参数绑定的过程,SQL语句是在最后 execute() 的时候才发送给数据库执行

如果关闭即为 false 的话,PDO不会模拟预处理,参数化绑定的整个过程都是和Mysql交互进行的

非模拟预处理的情况下,参数化绑定过程分两步:

  1. 第一步是 prepare 阶段,发送带有占位符的 sql 语句到 mysql 服务器(parsing->resolution)
  2. 第二步是多次发送占位符参数给 mysql 服务器进行执行(多次执行optimization->execution)

但是,如果你将user()改成一个子查询语句,那么结果又会爆出Invalid parameter number: parameter was not defined的错误。因为没有过多研究,说一下我猜测:预编译的确是mysql服务端进行的,但是预编译的过程是不接触数据的 ,也就是说不会从表中将真实数据取出来,所以使用子查询的情况下不会触发报错;虽然预编译的过程不接触数据,但类似user()这样的数据库函数的值还是将会编译进SQL语句,所以这里执行并爆了出来

修复

在 tp5 新版本中,改成对值得处理,而且拼接用得时$i这个计数,最后拼接得预处理也只能是:where_id_in_1,:where_id_in_1这样的了

image-20220118215104706

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/269798
推荐阅读
相关标签
  

闽ICP备14008679号