Php 如何保护我的网站不受sql注入的影响?

Php 如何保护我的网站不受sql注入的影响?,php,mysql,search-engine,sql-injection,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>

我有一个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>

搜索引擎-搜索
搜索引擎
一如既往,这是一个非常好的起点。阅读本文,其中包括各种示例和相关技术

其要点是,您永远不应该信任用户输入,用户输入包括来自环境的所有内容,包括
$\u GET
$\u POST
$\u COOKIE
$\u SESSION
,甚至
`$\u SERVER

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

$k = $_GET['k'];
并在查询中使用其内容:

if ($i == 1)
$query .= "keywords LIKE '%$each%' ";
else
$query .= "OR keywords LIKE '%$each%' ";
}
再也不要那样做了

您需要验证用户输入是否符合预期,并在SQL查询中使用之前对其进行清理。这两种功能都可以轻松实现

此外,您应该真正忘记
mysql.*
函数,它们是,扩展的开发状态是仅维护和。相反,您应该转到(注意末尾的i?它代表改进)

但我建议你也跳过这些,开始使用和。PDO提供了一个与数据库无关的面向对象接口,准备好的语句可以为您清理变量


就是这样。

PHP文档中有一篇关于这方面的文章


在mysql上使用库是一个更好的主意,因为它支持预先准备好的语句,并且主要为您进行转义。

避免SQL注入非常容易

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

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

在这种情况下也是如此。您不需要将原始产品提供给数据库,您需要先将其打包


为什么这很重要?这一点很重要,因为当您想要“以HTML形式输出PHP变量”(“或javascript”)时,准备好的语句和诸如此类的内容将不可用。是的,它与当前的问题同样相关。开发者需要学会正确地“打包”信息(
mysql\u real\u escape\u string
htmlspecialchars
json\u encode
),然后,他还可以学习更好的打包系统(PDO,模板引擎…)

直接查询 让我们看看您的代码:

if ($i == 1)
    $query .= "keywords LIKE '%$each%' ";
else
    $query .= "OR keywords LIKE '%$each%' ";
在将$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也有这样的功能)。

这是一个常见的问题,您应该读一篇类似这样的文章:@bummzack-有趣的是,wbesite也把它全部弄错了。清理输入与自己动手无关。@Oyeme是一篇错误得难以置信的文章。自称是停止注入的灵丹妙药的代码片段实际上允许注入。这些人对注射一点概念都没有。请不要再链接那个网站。这甚至不能解释SQL注入是什么,更不用说提供解决方案了。@ChristianSciberras这就是为什么我留下评论说我正在写一个正确的答案。。。读一读,告诉我你的想法。好多了,但正如我在下面所说的,PDO和mysqli只是一个方便的问题。优先考虑,但不是必需的。顺便说一下,mysqli支持预先准备好的语句。@ChristianSciberras是的,它支持。但我的部分答案是跳过mysqli,转而使用PDO。谢谢(我会尝试使用PDO)
mysql\u real\u escape\u string
在2012年真是个糟糕的建议,
mysql\u*
很久以前就基本上被弃用了……谢谢(我想我开始理解它了)@YannisRizos——该函数构建在mysqli的相同代码之上。如果易受攻击,mysqli以及准备好的语句都将易受攻击,因为它们都依赖于该功能
mysql是一个完整的库,不需要任何升级,因此开发停止了。它与非参数化mysqli一样强大。此外,您的评论类似于说“2012年批处理/bash脚本文件是错误的建议”。仅仅因为它们是老的、经过验证的,并不意味着它们是坏的。@ChristianSciberras实际上
mysql.*
开发停止了,因为它是坏的
mysqli.*
是一次从头重写,与
mysql.*
相比,它的源代码是惊人的。在发表社论之前,请做一些研究。有趣的是,你链接的文章说“难以维护”而不是“不可能”。也许你应该做一些研究,而不是依赖于货物崇拜编程。如果ext/mysql确实易受攻击,那么现代cmse早就停止支持它了——这与事实相去甚远。