Luke a Pro

Luke Sun

Developer & Marketer

🇺🇦
EN||

SQL 注入 (SQLi)

| , 2 minutes reading.

1. 定义

SQL 注入 (SQL Injection, SQLi) 发生在不受信任的用户输入被动态拼接到结构化查询语言 (SQL) 语句中时。这允许攻击者操纵查询结构,从而查看、修改或删除他们未被授权访问的数据。

2. 技术原理

SQL 解释器会同时处理指令和数据。如果应用通过字符串拼接来构建查询:

query = "SELECT * FROM users WHERE username = '" + user_input + "'";

攻击者可以输入 ' OR '1'='1。生成的查询将变为:

SELECT * FROM users WHERE username = '' OR '1'='1';

由于 '1'='1' 永远为真,数据库将返回表中的所有行,从而绕过用户名检查。

SQLi 的类型:

  • 带内 (In-band, 经典型): 结果直接返回在网页中(如基于 UNION 的注入)。
  • 盲注 (Blind): 不直接返回数据,但应用的行为会发生变化(基于时间或布尔值)。
  • 带外 (Out-of-band): 通过 DNS 或 HTTP 请求将数据导出(较罕见,取决于数据库)。

3. 攻击流程 (基于 Union)

sequenceDiagram
    participant Attacker
    participant App
    participant DB as 数据库

    Attacker->>App: GET /search?q=' UNION SELECT username, password FROM users--
    
    Note over App: 代码构建查询:<br/>SELECT title FROM products WHERE name = '' UNION ... --'
    
    App->>DB: 执行畸形查询
    
    Note over DB: 'UNION' 合并了来自 'products' 和 'users' 的结果
    
    DB-->>App: 返回产品列表 + 用户凭据
    App-->>Attacker: 在搜索结果中显示管理员密码

4. 真实案例:TalkTalk 遭受黑客攻击 (2015)

目标: TalkTalk (英国电信运营商)。 漏洞类别: 盲 SQL 注入。

事件回顾: 攻击者在 TalkTalk 域名上发现了一些未维护的旧网页,这些网页仍然连接着核心客户数据库。这些页面使用的 GET 参数存在 SQL 注入漏洞。

攻击技术: 他们使用 SQLMap(一种自动化工具)利用了盲 SQLi 漏洞。

  • 注入 SQL 命令来提取数据库架构信息。
  • 导出了 156,959 名客户 的个人资料和 15,000 多个银行账号。

影响: TalkTalk 被处以 40 万英镑 的罚款(当时创下了纪录),并估计在业务流失和补救方面损失了 7700 万英镑。这凸显了“僵尸”遗留代码带来的巨大风险。

5. 深度防御策略

A. 预处理语句 (参数化查询)

这是唯一的主要防御手段。 使用数据库驱动提供的参数化功能,而不是字符串拼接。

  • 机制: SQL 查询结构先被发送到数据库并编译。用户输入随后发送,且仅被视为数据,而非可执行的代码。

  • Java/JDBC 示例:

    String query = "SELECT * FROM users WHERE username = ?";
    PreparedStatement pstmt = connection.prepareStatement(query);
    pstmt.setString(1, userInput); // 安全
    ResultSet results = pstmt.executeQuery();

B. 存储过程

将查询封装在数据库内部。但请注意,存储过程本身必须使用参数,并避免在过程内部生成动态 SQL。

C. 最小权限原则

Web 应用使用的数据库账号应仅拥有以下权限:

  • 仅访问其所需的特定表。
  • 仅执行必要的命令(SELECT, INSERT, UPDATE)。
  • 绝不拥有 DROP TABLE, GRANT 或管理员权限。
  • 绝不允许访问操作系统文件系统(如 xp_cmdshell)。

6. 参考资料