式是把单引号作为用户名录入,原因是这样可能会暴露一些重要信息。有很多开发人员在
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'";
?>
幸运的是,
SQL 注入是很容易避免的。正如前面所提及的,你必须坚持过滤输入和转义输