【问题标题】:Is preventing XSS and SQL Injection as easy as does this防止 XSS 和 SQL 注入就这么简单
【发布时间】:2011-01-01 01:36:02
【问题描述】:

问题:防止XSS(跨站点脚本)很简单,在任何保存的输入字段上使用strip_tags 并在任何显示的输出上运行htmlspecialchars.. . 并通过使用 PHP PDO 准备语句来防止 SQL 注入

这是一个例子:

// INPUT: Input a persons favorite color and save to database
// this should prevent SQL injection ( by using prepared statement)
// and help prevent XSS  (by using strip_tags)
$sql = 'INSERT INTO TABLE favorite (person_name, color) VALUES (?,?)';
$sth = $conn->prepare($sql);
$sth->execute(array(strip_tags($_POST['person_name']), strip_tags($_POST['color'])));


// OUTPUT: Output a persons favorite color from the database
// this should prevent XSS (by using htmlspecialchars) when displaying
$sql = 'SELECT color FROM favorite WHERE person_name = ?';
$sth = $conn->prepare($sql);
$sth->execute(array(strip_tags($_POST['person_name'])));
$sth->setFetchMode(PDO::FETCH_BOTH);
while($color = $sth->fetch()){
  echo htmlspecialchars($color, ENT_QUOTES, 'UTF-8');
}

【问题讨论】:

  • 没听懂你——你要去mysql_query() $save_to_database 值吗?那么你仍然需要在提交查询之前调用mysql_real_escape_string(),否则你将无法免受 SQL 注入的保护(这又不是 XSS)
  • @naivists:你确定吗?他正在使用准备好的语句。

标签: php html xss sql-injection


【解决方案1】:

它更简单。用户控制输入上的htmlspecialchars()(带有引号样式和字符集)就足够了。 strip_tags() 仅在您已经想在处理/保存到数据库之前清理数据时才有用,这在现实世界中通常不使用。 HTML 代码不会损害 PHP 源代码,但如果您在未经处理的用户控制输入或类似邪恶的东西上使用 eval(),PHP 代码可能会这样做。

但这并不能将您从SQL injections 中拯救出来,但那是另一回事了。

更新:要从请求中获取clean用户输入以避免magic quotes出现在用户控制的输入中,您可以使用以下函数:

function get_string($array, $index, $default = null) {
    if (isset($array[$index]) && strlen($value = trim($array[$index])) > 0) {
         return get_magic_quotes_gpc() ?  stripslashes($value) : $value;
    } else {
         return $default;
    }
}

可以用作:

$username = get_string($_POST, "username");
$password = get_string($_POST, "password");

(您可以对get_numberget_booleanget_array 等进行类似操作)

要准备 SQL 查询以避免SQL injections,请执行以下操作:

$sql = sprintf(
    "SELECT id FROM user WHERE username = '%s' AND password = MD5('%s')",
        mysql_real_escape_string($user),
        mysql_real_escape_string($password)
); 

要显示用户控制的输入以避免 XSS,请执行以下操作:

echo htmlspecialchars($data, ENT_QUOTES, 'UTF-8');

【讨论】:

  • 除了 XSS 之外,我如何修改以保护我免受 SQL 注入?
  • 使用mysql_real_esacpe_string():php.net/manual/en/function.mysql-real-escape-string.php。此外,您还需要考虑get_magic_quotes_gpc()。如果这在 PHP 环境中返回 true,您还需要在输入上运行 stripslashes()
  • 如果我使用 PDO 准备好的语句,是否可以防止 SQL 注入?
  • @BalusC,我更新的原始帖子会保护我免受来自用户的所有恶意活动(XSS、SQL 注入和其他我可能不知道的事情)吗?
  • 不在输入 ..在输出。这就是重点,每个人都在想念。
【解决方案2】:

是的,使用 PDO 准备好的语句可以防止 SQL 注入。 SQL注入攻击是基于攻击者提交的数据被视为查询的一部分。例如,攻击者提交字符串“a”或“a”=“a”作为他的密码。不是将整个字符串与数据库中的密码进行比较,而是将其包含在查询中,因此查询变为“SELECT * FROM users WHERE login='joe' AND password='a' or 'a'='a' ”。攻击者输入的部分被解释为查询的一部分。但是在准备好的语句的情况下,您是在具体告诉 SQL 引擎,查询的部分是什么,数据的部分是什么(通过设置参数),所以不会出现这种混淆。

不,使用 strip_tags 并不总能保护您免受跨站点脚本的侵害。考虑以下示例。假设您的页面包含:

<script>
location.href='newpage_<?php echo strip_tags($_GET['language']); ?>.html';
</script>

攻击者提交请求时“语言”设置为“';somethingevil();'”。 strip_tags() 按原样返回此数据(其中没有标签)。生成的页面代码变为:

<script>
location.href='newpage_';somethingevil();'.html';
</script>

somethingevil() 被执行。将 somethingevil() 替换为实际的 XSS 漏洞利用代码。

您的最后一个带有 htmlspecialchars() 的示例将防止这个,因为它会转义单引号。然而,我在 JavaScript 代码中看到了更奇怪的用户提供数据的情况,它甚至不在带引号的字符串中。我认为它在变量或函数名称中。在最后一种情况下,再多的逃避可能也无济于事。我相信最好避免使用用户输入来生成 JavaScript 代码。

【讨论】:

  • &lt;script&gt; 具有不支持实体的 CDATA 内容模型。您必须将&lt;/ 转义为&lt;\/json_encode() 这样做。
【解决方案3】:

一般规则/模因是“过滤输入,转义输出”。在您的输入中使用strip_tags 来删除任何HTML 是输入过滤的一个好主意,但您应该尽可能严格地限制您允许的输入。例如,如果输入参数只应为整数,则只接受数字输入并始终将其转换为整数,然后再对其进行任何操作。一个经过严格审查的输入过滤库将在这里为您提供很多帮助;不是特定于特定框架的一个是Inspekt(我写的,所以我有点偏见)。

对于输出,htmlspecialchars 应该能够逃脱 XSS 攻击,但前提是您传递了正确的参数。您必须传递引号转义样式一个字符集。

一般来说,这应该去除XSS攻击:

$safer_str = htmlspecialchars($unsafe_str, ENT_QUOTES, 'UTF-8');

如果没有传递ENT_QUOTES 作为第二个参数,单引号字符不会被编码。此外,当没有传递正确的字符集(通常 UTF-8 就足够了)时,已经证明了 XSS 攻击。 htmlspecialchars 应该始终使用 ENT_QUOTES 和字符集参数调用。

请注意,PHP 5.2.12 包含对 a multibyte XSS attack 的修复。

您可能会发现 OWASP ESAPI PHP port 有趣且有用,尽管 PHP 版本不完整 AFAIK。

【讨论】:

  • @Funkatron,那么我更新的原始帖子是否可以保护我免受所有邪恶的侵害?
  • 看起来比较安全,是的。
  • 我不认为strip_tags 是个好主意。它破坏了一些合法的输入,但不足以保证安全。只需htmlspecialchars() 就足够了,而且不会有损。
【解决方案4】:

这取决于您希望在何处以及如何使用用户数据。您需要知道要在其中插入数据的上下文以及该上下文的元字符。

如果您只想允许用户在您的网站上放置文本,htmlspecialchars 足以转义 HTML 元字符。但是,如果您想允许某些 HTML 或想在现有 HTML 元素中嵌入用户数据(例如将 URL 嵌入到 A/IMG 元素中),htmlspecialchars 是不够的,因为您不再处于 HTML 上下文中但在 URL 上下文中。

因此,在图像 URL 字段中输入 &lt;script&gt;alert("xss")&lt;/script&gt; 将产生:

<img src="&lt;script&gt;alert(&quot;xss&quot;)&lt;/script&gt" />

但是输入javascript:alert("xss")会成功:

<img src="javascript:alert(&quot;xss&quot;)" />

在这里,您应该看看精彩的XSS (Cross Site Scripting) Cheat Sheet,看看您的用户数据可以注入到哪些上下文中。

【讨论】:

  • @Gumbo,我更新的原始帖子是否可以保护我免受您不使用脚本标签的示例的影响?
  • @TimTim:这仅取决于您要使用该数据的上下文。
  • @Gumbo 你如何防止这种攻击?我正在阅读您提供的 owasp 链接,但我看不到它在哪里说明如何防止这些攻击..
  • @Deadpool 验证输入。
【解决方案5】:

简单的答案:没有

更长的答案:有一些方法可以注入 PHP strip_stags 无法避免的 xss。

为了更好的保护尝试HTML purifier

【讨论】:

  • 感谢您的提示!我不认为这是解决这个确切问题的唯一方法,但如果我想允许一些 HTML 格式,它肯定很好。
  • 假设我们有一个页面,其正文中只有&lt;?echo strip_tags($_GET['query']);?&gt;。这里可以进行哪些注射?
  • .. 当strip_tags() 被使用没有 htmlspecialchars().
  • 输出使用htmlspecialchars也能实现XSS吗?
  • @navist,请注意 - 你写的不是我的用例。我说的是在 INPUTTED 数据上使用 strip_tags,而不是 OUTPUTTED(显示)数据
【解决方案6】:

strip_tags 不是必需的。在大多数情况下,strip_tags 只是令人讨厌,因为您的一些用户可能希望在他们的文本中使用 &lt;&gt;。在将文本回显到浏览器之前,只需使用 htmlspecialchars(或 htmlentities,如果您愿意)。

(在向数据库中插入任何内容之前,不要忘记 mysql_real_esacpe_string!)

【讨论】:

    猜你喜欢
    • 2019-06-03
    • 2013-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-14
    相关资源
    最近更新 更多