SQL注入攻击完全指南

👨‍💻 攻击者 ' OR '1'='1 -- DROP TABLE 恶意SQL代码 🌐 Web应用 未过滤输入 Database 数据泄露! 正常: SELECT * FROM users WHERE id = 1 注入: SELECT * FROM users WHERE id = 1 OR 1=1 !

SQL注入(SQL Injection)是最常见且危害最大的Web安全漏洞之一,攻击者通过在应用程序的输入字段中注入恶意SQL代码, 操纵后台数据库执行非预期的命令,从而实现数据窃取、篡改甚至完全控制数据库服务器。

⚠️

OWASP Top 10

SQL注入长期位列OWASP Top 10安全风险榜单,2021年排名第三(A03:2021 – Injection)。据统计,全球超过65%的Web应用存在SQL注入风险。

一、SQL注入原理

SQL注入的根本原因是应用程序在构造SQL查询时,未对用户输入进行充分验证和过滤,导致攻击者可以闭合原有SQL语句,并注入自己的恶意代码。

1.1 脆弱代码示例

// PHP脆弱代码示例 $id = $_GET['id']; $query = "SELECT * FROM users WHERE id = '$id'"; $result = mysqli_query($conn, $query); // 当用户输入: 1' OR '1'='1 // 实际执行的SQL: SELECT * FROM users WHERE id = '1' OR '1'='1' // 结果: 返回所有用户数据!

二、SQL注入类型

SQL注入分类 Union注入 联合查询注入 UNION SELECT NULL,username, password-- 布尔盲注 Boolean盲注 AND 1=1 (True) AND 1=2 (False) 根据响应判断 时间盲注 Time-based盲注 SLEEP(5) BENCHMARK() 延迟响应判断 堆叠注入 Stacked Queries SELECT...; DROP TABLE--; 多语句执行 报错注入 Error-based extractvalue() updatexml() 错误信息泄露 二次注入 Second Order 存储→读取→触发 延迟执行攻击 绕过过滤机制

2.1 Union注入

Union注入是最直接有效的注入方式,通过UNION操作符将恶意查询与原始查询结合,直接获取数据库数据。

// 判断字段数 ?id=1' ORDER BY 3--+ // 联合查询获取数据 ?id=-1' UNION SELECT 1,database(),version()--+ // 获取表名 ?id=-1' UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema=database()--+

2.2 布尔盲注

当应用不回显查询结果,但会根据查询真假返回不同响应时,可使用布尔盲注逐字符猜解数据。

// 判断数据库名长度 ?id=1' AND LENGTH(database())=8--+ // 逐字符猜解(二分法) ?id=1' AND ASCII(SUBSTRING(database(),1,1))>100--+ ?id=1' AND ASCII(SUBSTRING(database(),1,1))>110--+ // 重复直到确定每个字符

三、攻击流程

1

信息收集

识别注入点
判断数据库类型

2

漏洞验证

测试注入语法
确认可利用性

3

数据提取

获取数据库结构
提取敏感数据

4

权限提升

尝试文件读写
获取Shell

四、常用工具

🔧

SQLMap

自动化SQL注入工具,支持多种数据库和注入技术,功能强大且易用

sqlmap -u "url" --batch --dbs
🛠️

Burp Suite

抓包改包神器,配合Intruder模块可进行自定义注入测试

手工注入

掌握手工注入技巧是渗透测试的基本功,可绕过WAF和自动化工具限制

五、防御措施

🛡️

最佳实践

  • 使用参数化查询:预编译SQL语句,彻底分离代码与数据
  • 输入验证与过滤:白名单验证、转义特殊字符
  • 最小权限原则:限制数据库账户权限,禁用危险函数
  • 错误信息处理:不向用户显示详细的数据库错误
  • 使用WAF:部署Web应用防火墙进行实时防护

5.1 安全代码示例

// PDO参数化查询(推荐) $stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id"); $stmt->bindParam(':id', $id, PDO::PARAM_INT); $stmt->execute(); // MySQLi预处理语句 $stmt = $mysqli->prepare("SELECT * FROM users WHERE username = ?"); $stmt->bind_param("s", $username); $stmt->execute();

六、实战案例

💼

某电商平台SQL注入案例

通过商品搜索功能的参数注入,成功获取20万用户信息,包括加密密码、手机号等敏感数据。攻击者利用Union注入在3小时内完成数据窃取。

🏦

金融系统二次注入

攻击者在注册时提交恶意用户名,系统虽对输入进行了过滤,但在后续密码重置功能中直接从数据库读取用户名拼接SQL,触发二次注入,最终获取管理员权限。

Telegram