23

CodeIgniter PHP 框架中,有一个函数会在每个请求上自动运行,除其他外,过滤 GET/POST/COOKIE 数组键,并在遇到它认为不安全的字符时终止应用程序。

为了防止恶意用户尝试利用密钥,我们确保密钥仅以字母数字文本和其他一些项目命名。

就像是:

// foreach GET/POST/COOKIE keys as $str...
if ( ! preg_match("/^[a-z0-9:_\/-]+$/i", $str))
{
    exit('Disallowed Key Characters.');
}

例如,如果您不小心发布了类似<input name="TE$T">的内容或有类似的查询字符串,这将触发?name|first=1

我可以看到这是强制执行常识键名或在开发应用程序时发现错误的好方法,但我不明白:例如,恶意用户如何可能“利用$_POST数据中的键”?特别是因为(我会假设)输入同样可以利用,这实际上阻止了什么?

4

5 回答 5

18

你经常在新手代码中看到这个垃圾:

$_SESSION = $_POST;

一个鲜为人知的秘密是$_SESSION“特殊”并且不能将管道字符,处理|为顶级数组键。php 在关机/session_write_close 期间无法保存会话变量,而是擦除整个数组。

session_start();

if (!isset($_SESSION['cnt'])) {
    $_SESSION['cnt'] = 0;
}

$_SESSION['cnt']++;

/* prior to php 5.4, it will never increment, because it never successfuly saves
unless you comment line below
*/
$_SESSION['a|b'] = 1;

print_r($_SESSION);

我并不是说这就是 CodeIgniter 清除键的原因,但它是许多“可利用输入键的方式”之一。

也许一个更可能的原因是因为人们肯定会做这样的事情:

if ($formPostDidntValidate) {
    echo "Please fix the form submission errors and try again\n";
    foreach ($_POST as $key => $value) {
        echo "<p>$key<br>
              <input name='$key' value='$value'></p>";
    }
}

输出请求变量而不进行适当的特定于上下文的转义,例如转义 html 上下文、html 属性上下文,甚至 sql 上下文:

$sql = "select * from myTable where 1=1";
foreach ($_POST as $key => $value) {
    $sql .= " and $key = '$value'";
}

我见过很多人逃避价值,但不是构建 sql 和/或 html 时的关键。

如果你不逃避一切,你很容易被黑客入侵。清理值不如转义,但总比没有好,而且考虑到有多少开发人员还不够成熟,无法理解何时以及如何转义,我可以看到添加自动请求变量清理的吸引力。

于 2012-05-11T23:38:44.763 回答
9

你的问题本身就提出了一个很好的观点:目前还不清楚到底受到了什么保护。但它可以解决一些受欢迎的项目:

  • 魔术语录
  • 最终可能导致SQL 注入的事情
  • 可以通过 shell 命令执行的字符串
  • 可能与您的网址冲突的事情
  • 可能与 HTML 冲突的东西
  • 类似于目录遍历攻击的东西
  • 跨站点脚本(XSS) 攻击

但除此之外,我真的想不出为什么你总是为什么要保护 via preg_match("/^[a-z0-9:_\/-]+$/i", $str)

我有一种感觉,他们过度保护只是因为 CodeIgniter 的使用如此广泛,以至于他们需要保护他们自己还没有想到的事情,因为他们的用户可能对此类攻击知之甚少。 CodeIgniter 的开发人员。

于 2012-05-11T22:58:41.130 回答
4

在控制台中说我将表单的字段名称从更改name="email"name="email\"); DROP TABLE users;

这不太可能是一次成功的 XSS 攻击,但我可以看到类似的东西会对编码不佳的 PHP 造成损害。CI 可能只是试图覆盖他们所有的基础,以便他们可以声称尽可能受到 XSS 保护。

于 2012-05-11T22:58:14.127 回答
3

这种检查是浪费时间。无论如何,您只能访问您期望的键 - 如果由于某种原因您遍历所有元素,您很可能会正确地转义它们,无论您要对它们做什么。

然而,看看一个普通新手 PHP 程序员的技能(即使这个物种的成员很可能根本不使用框架)这是有道理的,你永远不知道他会用代码做什么讨厌的事情甚至可能在没有这样的检查的情况下杀死他的猫。

同样的事情也适用于拒绝包含例如“删除”作为反 SQL 注入措施的帖子。它很容易导致误报,如果您使用参数化查询,无论如何您都是安全的。

于 2012-05-11T22:54:12.583 回答
2

或许它正试图阻止这种攻击

该攻击通过使用 PHP 如何构建其散列结构的知识来制作$_POST需要任意长时间来处理的密钥。

我怀疑它可能只是试图阻止更普通的 SQL 注入攻击。

于 2012-05-11T22:59:32.170 回答