TP5 框架 SQL 执行流程分析及 5.0.9 SQL 注入漏洞分析_预处理

文章目录

  • ​​SQL查询流程​​
  • ​​TP 5.0.9 SQL注入​​
  • ​​修复​​

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);
}
}

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

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

修饰符

作用

s

强制转换为字符串类型

d

强制转换为整型类型

b

强制转换为布尔类型

a

强制转换为数组类型

f

强制转换为浮点类型

TP5 框架 SQL 执行流程分析及 5.0.9 SQL 注入漏洞分析_预处理_02

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

  1. prepare($SQL) 编译 SQL 语句
  2. bindValue(TP5 框架 SQL 执行流程分析及 5.0.9 SQL 注入漏洞分析_预处理_03value) 将 value 绑定在 param 的位置上
  3. execute 执行

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

TP5 框架 SQL 执行流程分析及 5.0.9 SQL 注入漏洞分析_SQL_04

生成查询 SQL

TP5 框架 SQL 执行流程分析及 5.0.9 SQL 注入漏洞分析_数据库_05

获取参数绑定

TP5 框架 SQL 执行流程分析及 5.0.9 SQL 注入漏洞分析_预处理_06

执行查询

TP5 框架 SQL 执行流程分析及 5.0.9 SQL 注入漏洞分析_SQL_07

TP5 框架 SQL 执行流程分析及 5.0.9 SQL 注入漏洞分析_web安全_08

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);
}
}

payload

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

TP5 框架 SQL 执行流程分析及 5.0.9 SQL 注入漏洞分析_SQL_09

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

TP5 框架 SQL 执行流程分析及 5.0.9 SQL 注入漏洞分析_SQL_10

基础的调试流程

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

这里直接进入 buildWhere()

TP5 框架 SQL 执行流程分析及 5.0.9 SQL 注入漏洞分析_SQL_11

if 都不进入,到最后

TP5 框架 SQL 执行流程分析及 5.0.9 SQL 注入漏洞分析_预处理_12

进入 parseWhereItem()直接看重点

TP5 框架 SQL 执行流程分析及 5.0.9 SQL 注入漏洞分析_sql_13

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

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

最终 return wherestr

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

完整的 sql 语句

TP5 框架 SQL 执行流程分析及 5.0.9 SQL 注入漏洞分析_web安全_14

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

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

TP5 框架 SQL 执行流程分析及 5.0.9 SQL 注入漏洞分析_sql_15

原因如下:

PDO::ATTR_EMULATE_PREPARES  => false

这个选项涉及到 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​​这样的了

TP5 框架 SQL 执行流程分析及 5.0.9 SQL 注入漏洞分析_SQL_16


TP5 框架 SQL 执行流程分析及 5.0.9 SQL 注入漏洞分析_web安全_17