今天早些时候的一个问题是,要求有关 输入确认的战略在网络应用程序.

顶部回答,在编写本报告时,建议在 PHP 只是使用 htmlspecialcharsmysql_real_escape_string.

我的问题是:这总够了吗?是否有更多我们应该知道吗?在哪里做这些职能打破?

有帮助吗?

解决方案

当涉及到数据库查询,总是试图和使用准备好的参数化的询问。的 mysqliPDO 图书馆提供支持。这是无限的比较安全的使用功能,例如逃避 mysql_real_escape_string.

是的, mysql_real_escape_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注射向量,并将允许攻击者返回的所有行。或

1 or is_admin=1 order by id limit 1

其产生的

SELECT fields FROM table WHERE id=1 or is_admin=1 order by id limit 1

它允许攻击者返回的第一管理的详细信息,这完全虚构的例子。

虽然这些功能是有用的,他们必须小心使用。你需要确保所有网络的投入进行验证。在这种情况下,我们看到,我们可以利用的,因为我们没有检查这一变我们作为一个数字,是实际数字。在PHP你应该广泛使用的一套功能检查的投入是整数,漂浮的字母数字等等。但是,当涉及到SQL,听取最大价值的准备好的发言。上述代码会有安全,如果它是一个准备的发言作为数据库的功能会知道 1 OR 1=1 是不是一个有效的文本。

作为对 htmlspecialchars().这是一个雷区。

有一个真正的问题在PHP在于,它有一个整体选择的不同html有关的逃离的功能,并且没有明确的指导意见究竟其功能做什么。

首先,如果你是内部的一个HTML标记,你是真正的麻烦。看看

echo '<img src= "' . htmlspecialchars($_GET['imagesrc']) . '" />';

我们已经在里面HTML标签,这样我们不需要 < 或做任何危险。我们的攻击向量可能仅仅是 javascript:alert(document.cookie)

现在所得HTML看起来像

<img src= "javascript:alert(document.cookie)" />

攻击得到直接通过。

它变得更糟。为什么?因 htmlspecialchars (当时称为这种方式)只编码双报价并不是单一的。因此,如果我们了

echo "<img src= '" . htmlspecialchars($_GET['imagesrc']) . ". />";

我们的邪恶攻击者现在可以注入全新的参数

pic.png' onclick='location.href=xxx' onmouseover='...

给了我们

<img src='pic.png' onclick='location.href=xxx' onmouseover='...' />

在这些情况下,没有神奇的子弹,你只需要santise输入自己。如果你尝试和筛选出恶人物你一定会失败。拿一个白名单办法,并仅让我们通过的文字,它是好的。看看 XSS作弊表 例如何多元化的载体可以

甚至如果你使用 htmlspecialchars($string) 外HTML标记,你仍然容易受到多字节charset的攻击向量。

最有效的,你可以是利用一个组合mb_convert_encoding和htmlentities如下。

$str = mb_convert_encoding($str, 'UTF-8', 'UTF-8');
$str = htmlentities($str, ENT_QUOTES, 'UTF-8');

即使这使IE6脆弱的,因为它处理UTF。但是,你可能会下降回到一个更有限的编码,如ISO-8859-1,直到IE6使用率下降。

为了更深入的研究的多问题,请参阅 https://stackoverflow.com/a/12118602/1820

其他提示

此外,Cheekysoft的极好的回答:

  • 是的,他们会保护你的安全,但仅仅如果它们的使用绝对正确。使用他们不正确,你将仍然是脆弱的,并且可能有其它问题(例如数据的腐败)
  • 请使用的参数化查询,而不是(正如上文)。你可以用它们通过例如公设辩护或通过一个包装的像梨DB
  • 确保magic_quotes_gpc和magic_quotes_runtime是在所有时候,从来没有获得不小心打开,甚至没有简要介绍。这些都是早期和深入错误的尝试通过PHP的开发,以防止安全问题(这破坏了数据)

确实没有银弹防止HTML注射(例如跨站脚本),但是你可能能够实现它更加容易,如果你使用的图书馆或模板系统,用于输出HTML。阅读该文件,对于如何逃生的事情适当地进行。

在HTML,事情需要逃脱不同的上下文。这是真实的,尤其是串被放置到Javascript。

我肯定会同意上述帖子,但我有一个小问题可以回答Cheekysoft的回答,具体来说:

  

说到数据库查询,   总是尝试使用准备好的   参数化查询。 mysqli和   PDO库支持这一点。这是   比使用转义更安全   功能如   mysql_real_escape_string。

     

是的,mysql_real_escape_string是   实际上只是一个字符串转义   功能。它不是一个神奇的子弹。   它所能做的只是逃避危险   字符,以便它们可以   可以安全地在单个查询字符串中使用。   但是,如果你没有消毒你的   事先输入,然后你会   容易受到某些攻击媒介的影响。

     

想象一下以下SQL:

     

$ result = <!> quot; SELECT字段FROM表   WHERE id =   <!> QUOT; .mysql_real_escape_string($ _ POST [ 'ID']);

     

你应该能够看到这是   容易被剥削。想象一下id   参数包含常见攻击   矢量:

     

1 OR 1 = 1

     

那里没有冒险的人物   编码,所以它将直接通过   通过逃逸过滤器。离开   我们:

     

SELECT字段FROM表WHERE id = 1   或1 = 1

我编写了一个快速的小函数,我放在我的数据库类中,它将删除任何不是数字的东西。它使用了preg_replace,所以有一些问题可能会更加优化,但是它可以用来捏......

function Numbers($input) {
  $input = preg_replace("/[^0-9]/","", $input);
  if($input == '') $input = 0;
  return $input;
}

所以不要使用

  

$ result = <!> quot; SELECT字段FROM表WHERE id = <!> quot; .mysqlrealescapestring(<!> quot; 1 OR 1 = 1 <!> quot;);

我会用

  

$ result = <!> quot; SELECT字段FROM表WHERE id = <!> quot; .Numbers(<!> quot; 1 OR 1 = 1 <!> quot;);

它可以安全地运行查询

  

SELECT字段FROM表WHERE id = 111

当然,这只是阻止它显示正确的行,但我不认为对于试图将sql注入您的网站的人来说这是一个大问题;)

这个难题的一个重要部分是背景。发送<!>“1 OR 1 = 1 <!>”的人因为如果引用查询中的每个参数,ID都不是问题:

SELECT fields FROM table WHERE id='".mysql_real_escape_string($_GET['id'])."'"

结果是:

SELECT fields FROM table WHERE id='1 OR 1=1'

无效。由于您正在转义字符串,因此输入不会突破字符串上下文。我已经对MySQL的5.0.45版本进行了测试,并且对整数列使用字符串上下文不会导致任何问题。

$result = "SELECT fields FROM table WHERE id = ".(INT) $_GET['id'];

在64位系统上运行良好,甚至更好。请注意您在处理大数字时遇到的系统限制,但对于数据库ID,99%的情况下这很有用。

您也应该使用单一功能/方法来清理您的值。即使这个函数只是mysql_real_escape_string()的包装器。为什么?因为有一天会发现您首选的清理数据方法,只需将其更新到一个地方,而不是在系统范围内查找和替换。

为什么,为什么,你在sql语句中包含用户输入的引号?似乎很傻到不!在sql语句中包含引号会呈现<!> quot; 1或1 = 1 <!> quot;没有成功的尝试,不是吗?

现在,你会说,<!>“如果用户在输入中包含引号(或双引号)怎么办?<!>

嗯,很容易解决这个问题:只需删除用户输入的引号即可。例如:input =~ s/'//g;。现在,无论如何,在我看来,用户输入将是安全的......

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top