当前位置: 首页 > 网络学院 > 服务端脚本教程 > PHP > PHP 防止 SQL 注入攻击

PHP
PHP 安全邮件
MySQL 介绍
连接 MySQL
创建 MySQL
MySQL 插入记录
MySQL 选择记录
MySQL Where
MySQL Order By
MySQL 记录更新
MySQL 删除记录
PHP ODBC
XML Expat Parser
XML SimpleXML
PHP 数组参考
PHP Calendar
PHP Date
PHP Directory
PHP Filesystem
PHP FTP
PHP HTTP

PHP 防止 SQL 注入攻击


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-03-01   浏览: 970 ::
收藏到网摘: n/a

防止 SQL 注入攻击

SQL 注入攻击 中,用户通过操纵表单或 GET 查询字符串,将信息添加到数据库查询中。例如,假设有一个简单的登录数据库。这个数据库中的每个记录都有一个用户名字段和一个密码字段。构建一个登录表单,让用户能够登录。


清单 5. 简单的登录表单


<html>
<head>
<title>Login</title>
</head>
<body>
<form action="verify.php" method="post">
<p><label for='user'>Username</label>
<input type='text' name='user' id='user'/>
</p>
<p><label for='pw'>Password</label>
<input type='password' name='pw' id='pw'/>
</p>
<p><input type='submit' value='login'/></p>
</form>
</body>
</html>

 

这个表单接受用户输入的用户名和密码,并将用户输入提交给名为 verify.php 的文件。在这个文件中,PHP 处理来自登录表单的数据,如下所示:


清单 6. 不安全的 PHP 表单处理代码


<?php
$okay = 0;
$username = $_POST['user'];
$pw = $_POST['pw'];

$sql = "select count(*) as ctr from users where
username='".$username."' and password='". $pw."' limit 1";

$result = mysql_query($sql);

while ($data = mysql_fetch_object($result)){
if ($data->ctr == 1){
//they're okay to enter the application!
$okay = 1;
}
}

if ($okay){
$_SESSION['loginokay'] = true;
header("index.php");
}else{
header("login.php");
}
?>

 

这段代码看起来没问题,对吗?世 界各地成百(甚至成千)的 PHP/MySQL 站点都在使用这样的代码。它错在哪里?好,记住 “不能信任用户输入”。这里没有对来自用户的任何信息进行转义,因此使应用程序容易受到攻击。具体来说,可能会出现任何类型的 SQL 注入攻击。

例如,如果用户输入 foo 作为用户名,输入 ' or '1'='1 作为密码,那么实际上会将以下字符串传递给 PHP,然后将查询传递给 MySQL:

$sql = "select count(*) as ctr from users where 
username='foo' and password='' or '1'='1' limit 1";

 

这个查询总是返回计数值 1,因此 PHP 会允许进行访问。通过在密码字符串的末尾注入某些恶意 SQL,黑客就能装扮成合法的用户。

解决这个问题的办法是,将 PHP 的内置 mysql_real_escape_string() 函数用作任何用户输入的包装器。这个函数对字符串中的字符进行转义,使字符串不可能传递撇号等特殊字符并让 MySQL 根据特殊字符进行操作。清单 7 展示了带转义处理的代码。


清单 7. 安全的 PHP 表单处理代码


<?php
$okay = 0;
$username = $_POST['user'];
$pw = $_POST['pw'];

$sql = "select count(*) as ctr from users where
username='".mysql_real_escape_string($username)."'
and password='". mysql_real_escape_string($pw)."' limit 1";

$result = mysql_query($sql);

while ($data = mysql_fetch_object($result)){
if ($data->ctr == 1){
//they're okay to enter the application!
$okay = 1;
}
}

if ($okay){
$_SESSION['loginokay'] = true;
header("index.php");
}else{
header("login.php");
}
?>

 

使用 mysql_real_escape_string() 作为用户输入的包装器,就可以避免用户输入中的任何恶意 SQL 注入。如果用户尝试通过 SQL 注入传递畸形的密码,那么会将以下查询传递给数据库:

select count(*) as ctr from users where \
username='foo' and password='\' or \'1\'=\'1' limit 1"

 

数据库中没有任何东西与这样的密码匹配。仅仅采用一个简单的步骤,就堵住了 Web 应用程序中的一个大漏洞。这里得出的经验是,总是应该对 SQL 查询的用户输入进行转义。

评论 (1) 1 All

登陆 | 还没注册?