我有一个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>
答案 0 :(得分:1)
答案 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?它代表改进)。
但我建议您跳过这些内容,然后开始使用PDO和prepared statements。 PDO提供了一个与数据库无关的面向对象的接口,并且准备好的语句为您清理变量。
就是这样。
答案 2 :(得分:0)
避免SQL注入非常容易。
目前修复sql注入的趋势似乎指向了一个声称是解决方案的神奇流行语。这并不能解决真正的问题,即编写代码的开发人员缺乏知识。
想象一家销售产品的公司。他们肯定不会在没有任何包装的情况下直接提供产品。相反,他们将它传递给包装部门。
在这种情况下也一样。您没有向数据库提供原始产品,您需要先将其打包。
为什么这很重要?这很重要,因为当您希望“在HTML中输出PHP变量”(“或javascript”)时,预备语句和诸如此类的东西将无法使用。是的,它与手头的问题同样重要。 开发人员需要学会正确“打包”信息(mysql_real_escape_string
,htmlspecialchars
,json_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也有这样的功能)。