SQL注入之联合查询注入

SQL注入之联合查询注入

一、联合查询注入原理

联合查询注入是一种常见的SQL注入攻击手法,其核心原理是利用SQL中的UNION操作符将多个SELECT语句的结果集合并,从而返回一个统一的结果集。在使用UNION时,必须确保前后两个查询的列数相同,且对应列的数据类型兼容。攻击者通过构造恶意查询,将数据库中的敏感信息(如数据库名称、表名、列名等)与正常查询结果一并输出,从而窃取关键数据。这种攻击方式通常用于探测数据库结构并获取未经授权的信息。

二、联合查询注入方法

联合查询注入的方法一共分三步:

  1. 确定列数:通过ORDER BY子句利用二分法确定查询的列数(超出列数时会报错)。
  2. 确定可显示列:利用UNION SELECT,将数字或字符串替换到不同列,找出回显数据的列。
  3. 获取数据:构造恶意查询,获取数据库中的敏感信息。

例如某个功能的SQL语句如下:

SELECT id, name, age, sex FROM students WHERE name LIKE '%用户输入%'

①确认列数

我们可以在【用户输入】中输入 1' ORDER BY 4 --,此时 SQL 语句会被拼接为:

SELECT id, name, age, sex FROM students WHERE name LIKE '%1' ORDER BY 4 --%'

当使用 ORDER BY 4 时,SQL 语句不会报错;然而,当使用 ORDER BY 5 时,SQL 语句会抛出错误:ERROR 1054 (42S22): Unknown column '5' in 'order clause'

通过观察是否出现报错,我们可以确定查询结果中的列数。

②确定可显示列

由于 SQL 查询语句中的字段不会全部显示在页面上或通过接口返回,因此我们需要通过 UNION SELECT 将数字或字符串替换到不同的列,以确定回显数据的位置。

我们可以在【用户输入】中输入 1' UNION SELECT 1, 2, 3, 4 --,此时 SQL 语句会被拼接为:

SELECT id, name, age, sex FROM students WHERE name LIKE '%1' UNION SELECT 1, 2, 3, 4 --%'

通过观察页面,我们可以查找是否有数据显示为 1234(如果原本数据中已经存在 1234,则可以替换为其他数据)。如果存在,则这些位置即为可显示列。

③获取数据

在找到可显示列后,我们就可以利用这些位置查询所需的数据。例如,假设位置 3 是可显示列,我们可以在【用户输入】中输入 1' UNION SELECT 1, 2, user(), 4 --,此时 SQL 语句会被拼接为:

SELECT id, name, age, sex FROM students WHERE name LIKE '%1' UNION SELECT 1, 2, user(), 4 --%'

通过这种方式,我们可以在页面上查看到 SELECT user() 的返回内容。

三、联合查询注入实例

在Pikachu中,进行实践。

①确认列数

在输入框中分别输入以下内容:

  • 1' order by 3 #
    image
  • 1' order by 4 #
    image

通过观察页面响应,可以确认查询结果的列数为 3。

②确定可显示列

在输入框输入:1' UNION SELECT 1, 2, 3 #

image

发现三个字段均可显示

③获取数据

在输入框输入:1' UNION SELECT database(), version(), user() #

image

随便在某个字段进行查询脱库

### SQL注入联合查询的利用方法和技巧 #### 联合查询的基本原理 联合查询UNION Query)是SQL注入中一种常见的攻击方式,它通过将恶意构造的SQL语句附加到原始查询中,从而获取额外的数据。联合查询的核心在于使用`UNION`操作符将两个或多个SELECT语句的结果集合并为一个结果集。为了成功执行联合查询注入,攻击者需要确保以下条件[^1]: - 原始查询与构造的恶意查询返回的列数相同。 - 每一列的数据类型兼容。 #### 联合查询注入的利用方法 攻击者通常会利用联合查询来绕过输入验证并获取敏感信息。例如,假设存在一个未经过滤的登录表单,其SQL查询可能如下所示: ```sql SELECT username, password FROM users WHERE username = '$username' AND password = '$password'; ``` 如果用户输入被直接拼接到SQL语句中,攻击者可以构造如下输入: ```plaintext ' UNION SELECT null, table_name FROM information_schema.tables -- ``` 这将导致最终执行的SQL语句变为: ```sql SELECT username, password FROM users WHERE username = '' UNION SELECT null, table_name FROM information_schema.tables -- ' AND password = ''; ``` 通过这种方式,攻击者可以枚举数据库中的所有表名[^3]。 #### 防御联合查询注入的方法 防御联合查询注入的关键在于从源头上杜绝恶意输入的影响。以下是几种有效的防御措施[^2]: 1. **参数化查询**:始终使用预编译语句和参数化查询,避免直接将用户输入嵌入SQL语句中。例如,在Python中可以使用`sqlite3`模块的参数化功能: ```python import sqlite3 conn = sqlite3.connect('database.db') cursor = conn.cursor() cursor.execute("SELECT * FROM users WHERE username = ? AND password = ?", (username, password)) ``` 2. **白名单过滤**:仅允许用户输入符合特定规则的数据。例如,如果应用程序只需要数字输入,则可以通过正则表达式或类型检查进行过滤: ```python if not username.isdigit(): raise ValueError('Invalid username') ``` 3. **最小权限原则**:确保数据库用户的权限仅限于完成任务所需的最低权限。例如,Web应用程序的数据库账户不应具有删除或修改表结构的权限[^4]。 4. **WAF(Web应用防火墙)**:部署WAF以检测和阻止常见的SQL注入模式。WAF可以作为额外的安全层,但不能完全替代其他防御措施。 #### 示例代码 以下是一个结合参数化查询和白名单过滤的示例: ```python import re import sqlite3 def validate_username(username): # 白名单过滤:仅允许字母、数字和下划线 if not re.match(r'^\w+$', username): raise ValueError('Invalid username') def authenticate_user(username, password): validate_username(username) # 白名单过滤 conn = sqlite3.connect('database.db') cursor = conn.cursor() # 参数化查询 cursor.execute("SELECT * FROM users WHERE username = ? AND password = ?", (username, password)) user = cursor.fetchone() conn.close() return user ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值