当然,攻击者未必在第一次就能猜中,他们常常还需要做一些试验。有一个比较好的试验方式是把单引号作为用户名录入,原因是这样可能会暴露一些重要信息。有很多开发人员在Mysql语句执行出错时会调用函数mysql_error()来报告错误。见下面的例子: 复制代码 代码如下: <?php mysql_query($sql) or exit(mysql_error()); ?>
虽然该方法在开发中十分有用,但它能向攻击者暴露重要信息。如果攻击者把单引号做为用户名,mypass做为密码,查询语句就会变成: 复制代码 代码如下: <?php $sql = "SELECT * FROM users WHERE username = """ AND password = "a029d0df84eb5549c641e04a9ef389e5""; ?>
当该语句发送到MySQL后,系统就会显示如下错误信息: 复制代码 代码如下: 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 "WHERE username = """ AND password = "a029d0df84eb55
不费吹灰之力,攻击者已经知道了两个字段名(username和password)以及他们出现在查询中的顺序。除此以外,攻击者还知道了数据没有正确进行过滤(程序没有提示非法用户名)和转义(出现了数据库错误),同时整个WHERE条件的格式也暴露了,这样,攻击者就可以尝试操纵符合查询的记录了。 在这一点上,攻击者有很多选择。一是尝试填入一个特殊的用户名,以使查询无论用户名密码是否符合,都能得到匹配: 复制代码 代码如下: myuser" or "foo" = "foo" --
假定将mypass作为密码,整个查询就会变成: 复制代码 代码如下: <?php
$sql = "SELECT * FROM users WHERE username = "myuser" or "foo" = "foo" -- AND password = "a029d0df84eb5549c641e04a9ef389e5"";