htmlspecialchars和mysql\u real\u escape\u字符串是否能保证我的PHP代码不被注入?
今天早些时候,有人就这一问题提出了一个问题 在撰写本文时,上面的答案建议在htmlspecialchars和mysql\u real\u escape\u字符串是否能保证我的PHP代码不被注入?,php,security,xss,sql-injection,Php,Security,Xss,Sql Injection,今天早些时候,有人就这一问题提出了一个问题 在撰写本文时,上面的答案建议在PHP中使用htmlspecialchars和mysql\u real\u escape\u string 我的问题是:这总是足够吗?还有更多我们应该知道的吗?这些函数在哪里失效?当涉及到数据库查询时,请始终尝试使用准备好的参数化查询。mysqli和PDO库支持这一点。这比使用转义函数(如mysql\u real\u escape\u string)安全得多 是的,mysql\u real\u escape\u strin
PHP
中使用htmlspecialchars
和mysql\u real\u escape\u string
我的问题是:这总是足够吗?还有更多我们应该知道的吗?这些函数在哪里失效?当涉及到数据库查询时,请始终尝试使用准备好的参数化查询。
mysqli
和PDO
库支持这一点。这比使用转义函数(如mysql\u real\u escape\u string
)安全得多
是的,mysql\u real\u escape\u string
实际上只是一个字符串转义函数。这不是一颗神奇的子弹。它所能做的就是转义危险字符,以便在单个查询字符串中安全使用这些字符。然而,如果您没有事先对输入进行消毒,那么您将容易受到某些攻击向量的攻击
想象一下下面的SQL:
$result = "SELECT fields FROM table WHERE id = ".mysql_real_escape_string($_POST['id']);
您应该能够看到这很容易被利用。想象一下包含公共攻击向量的
id
参数:
1 OR 1=1
那里没有危险的字符可编码,因此它将直接通过转义过滤器。留给我们:
SELECT fields FROM table WHERE id= 1 OR 1=1
这是一个可爱的SQL注入向量,允许攻击者返回所有行。
或
产生
SELECT fields FROM table WHERE id=1 or is_admin=1 order by id limit 1
这使得攻击者可以在这个完全虚构的示例中返回第一个管理员的详细信息
虽然这些功能很有用,但必须小心使用。您需要确保在某种程度上验证所有web输入。在本例中,我们发现我们可以被利用,因为我们没有检查作为数字使用的变量实际上是数字。在PHP中,您应该广泛使用一组函数来检查输入是否为整数、浮点数、字母数字等。但在SQL中,最需要注意的是准备好的语句的值。如果上面的代码是一条准备好的语句,那么它是安全的,因为数据库函数会知道1或1=1
不是有效的文本
至于htmlspecialchars()
。那是它自己的雷区
PHP中存在一个真正的问题,它有一整套与html相关的转义函数可供选择,并且没有明确的指导说明哪些函数做什么
首先,如果你在一个HTML标记中,你就真的有麻烦了。看
echo '<img src= "' . htmlspecialchars($_GET['imagesrc']) . '" />';
攻击是直接进行的
情况变得更糟了。为什么?因为htmlspecialchars
(以这种方式调用时)只编码双引号而不是单引号。所以如果我们有
echo "<img src= '" . htmlspecialchars($_GET['imagesrc']) . ". />";
给我们
<img src='pic.png' onclick='location.href=xxx' onmouseover='...' />
即使这样,IE6也容易受到攻击,因为它处理UTF的方式。然而,在IE6使用率下降之前,您可以退回到更有限的编码,如ISO-8859-1
有关多字节问题的更深入研究,请参见除Cheekysoft的优秀答案外的:
- 是的,它们会保护你的安全,但前提是它们的使用绝对正确。如果不正确地使用它们,您仍然会受到攻击,并且可能存在其他问题(例如数据损坏)
- 请改用参数化查询(如上所述)。您可以通过PDO或PEAR DB等包装器使用它们
- 确保magic_quotes_gpc和magic_quotes_运行时始终处于关闭状态,并且永远不会意外打开,即使是短暂打开。这些都是PHP开发人员为防止安全问题(破坏数据)而进行的早期错误尝试
在HTML中,需要根据上下文进行不同的转义。尤其是字符串被放入Javascript中时更是如此。我绝对同意上面的帖子,但我要补充一点来回答Cheekysoft的回答,特别是:
当涉及到数据库查询时, 始终尝试使用准备好的 参数化查询。mysqli和 PDO库支持这一点。这是 远比使用逃逸安全 功能,如 mysql\u real\u escape\u字符串 是的,mysql\u real\u escape\u字符串是 实际上只是一个字符串转义 功能。这不是一颗神奇的子弹。 它所能做的就是逃避危险 字符,以便它们可以 可以在单个查询字符串中安全使用。 但是,如果您不消毒您的 事先输入,然后您将 易受某些攻击向量的攻击 想象一下下面的SQL:
$result = "SELECT fields FROM table WHERE id = ".mysql_real_escape_string($_POST['id']);
$result=“从表中选择字段
何处id=
“.mysql\u real\u escape\u字符串($\u POST['id'])
你应该能看到这是
容易被利用。想象一下身份证
参数包含常见的攻击
向量:
1或1=1
那里没有危险的角色来保护你
编码,这样它就可以直接通过了
通过逸出过滤器。离开
美国:
从id=1的表中选择字段
或1=1
我编写了一个快速的小函数,我把它放在我的数据库类中,它将去掉任何不是数字的东西。它使用preg_replace,因此可能会有一个更优化的函数,但它在紧要关头工作
function Numbers($input) {
$input = preg_replace("/[^0-9]/","", $input);
if($input == '') $input = 0;
return $input;
}
因此,与其使用
$result=“从表中选择字段,其中id=“.mysqlrealeescapestring”(“1或1=1”)
我会用
$result=“从id=“.number”(“1或1=1”)的表格中选择字段
它将安全地运行查询
从id=111的表中选择字段
当然,这只是阻止了它显示正确的行,但我认为这对于试图将sql注入您的站点的人来说不是一个大问题;) 这个难题的一个重要部分是上下文。一些
<img src='pic.png' onclick='location.href=xxx' onmouseover='...' />
$str = mb_convert_encoding($str, 'UTF-8', 'UTF-8');
$str = htmlentities($str, ENT_QUOTES, 'UTF-8');
function Numbers($input) {
$input = preg_replace("/[^0-9]/","", $input);
if($input == '') $input = 0;
return $input;
}
SELECT fields FROM table WHERE id='".mysql_real_escape_string($_GET['id'])."'"
SELECT fields FROM table WHERE id='1 OR 1=1'
$result = "SELECT fields FROM table WHERE id = ".(INT) $_GET['id'];