如何保护我的网站免受sql注入?

时间:2012-01-22 20:42:48

标签: php mysql search-engine sql-injection

我有一个PHP的基本网站,它是一个搜索引擎并运行一个mysql数据库,但是我需要保护它免受sql注入,有人可以向我解释我是如何做到这一点的吗?

我的PHP脚本:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Search Engine - Search</title>
</head>
<body>

<h2>Search Engine</h2>
<form action='./search.php' method='get'>
<input type='text' name='k' size='50' value='<?php echo $_GET['k']; ?>' />
<input type='submit' value='Search'>
</form>
<hr />
<?php
$k = $_GET['k'];

$terms = explode (" ", $k);
$query = "SELECT * FROM search WHERE ";

foreach ($terms as $each) {
$i++;

if ($i == 1)
$query .= "keywords LIKE '%$each%' ";
else
$query .= "OR keywords LIKE '%$each%' ";
}

// connect
mysql_connect("*******", "******", "*******");
mysql_select_db(*******);

$query = mysql_query("$query");
$numrows = mysql_num_rows($query);
if ($numrows > 0) {

while ($row = mysql_fetch_assoc($query)) {
$id = $row['id'];
$title = $row['title'];
$description = $row['description'];
$keywords = $row['keywords'];
$link = $row['link'];

echo "<h2><a href='$link'>$title</a></h2>
$description<br /><br />";
}

}
else
echo "No results found for \"<b>$k</b>\"";

// disconnect
mysql_close();


?>
</body>
</html>

3 个答案:

答案 0 :(得分:1)

PHP文档中有一篇文章,see here

在mysql上使用mysqli库是一个更好的主意,因为它支持预处理语句并且主要为你进行转义。

答案 1 :(得分:0)

与往常一样,the manual是一个非常好的起点。阅读文章,它包括各种示例和相关技术。

它的要点是您永远不应该信任用户输入,用户输入包括来自环境的所有内容,包括$_GET$_POST$_COOKIE,{{1} ,甚至$_SESSION

在您的代码中,您盲目信任:

`$_SERVER

并在查询中使用其内容:

$k = $_GET['k'];

永远不要再这样做了

您需要验证用户输入是否符合预期,并在SQL查询中使用之前对其进行清理。您可以使用Filter函数轻松完成这两项工作。

此外,您应该忘记if ($i == 1) $query .= "keywords LIKE '%$each%' "; else $query .= "OR keywords LIKE '%$each%' "; } 个功能,它们是essentially deprecated,扩展程序的开发状态仅为维护,long term deprecation was announced recently。相反,你应该转到mysqli_* functions(注意结尾的i?它代表改进)。

但我建议您跳过这些内容,然后开始使用PDOprepared statements。 PDO提供了一个与数据库无关的面向对象的接口,并且准备好的语句为您清理变量。

就是这样。

答案 2 :(得分:0)

避免SQL注入非常容易。

为什么?

目前修复sql注入的趋势似乎指向了一个声称是解决方案的神奇流行语。这并不能解决真正的问题,即编写代码的开发人员缺乏知识。

想象一家销售产品的公司。他们肯定不会在没有任何包装的情况下直接提供产品。相反,他们将它传递给包装部门。

在这种情况下也一样。您没有向数据库提供原始产品,您需要先将其打包。

为什么这很重要?这很重要,因为当您希望“在HTML中输出PHP变量”(“或javascript”)时,预备语句和诸如此类的东西将无法使用。是的,它与手头的问题同样重要。 开发人员需要学会正确“打包”信息mysql_real_escape_stringhtmlspecialcharsjson_encode),然后,他也可以了解更好的打包系统( PDO 模板引擎 ...)。

直接查询

让我们来看看你的代码:

if ($i == 1)
    $query .= "keywords LIKE '%$each%' ";
else
    $query .= "OR keywords LIKE '%$each%' ";

在将它们放入查询之前,只需确保$ each实际编码,如下所示:

$each = mysql_real_escape_string( $each );

if ($i == 1)
    $query .= "keywords LIKE '%$each%' ";
else
    $query .= "OR keywords LIKE '%$each%' ";

容易,不是吗?

参数化查询

这些往往会自己进行编码。这是一个更好的系统,但是如果你认为你的SQL注入问题已经结束,请再想一想。

参数化查询将您的数据作为参数而不是直接查询,并且它们自己对输入进行编码。

但实际上,您可能会错误地或必然地将数据直接传递给查询。

如果您按照上面的建议切换到PDO,而不知道后果,您可能还有SQL注入,但仍然不知道它。 PDO没有阻止你直接运行SQL查询,因此同样的错误可以移植到那里。

在这种情况下,要么按照上面的建议编码输入(PDO也有这样的功能)。