PHP安全性:评估用户输入的字符串的风险


PHP security: risks in evaluating a user-entered string

让我在前面说,我很清楚在服务器环境中运行用户提供的代码是有风险的。幽默的我——我的问题是特定于字符串求值和可以在该上下文中执行的语言子集。

所以我现在正在构建一个模板生成系统,我希望它能很快。超级,超级,超级快。这件事会因为群发电子邮件之类的事情而受到抨击。我使用的方法是让用户提供用户输入的模板标记,这些标记在存储之前通过正则表达式转换为PHP变量替换。假设我的正则表达式是防弹的,你觉得这个过程的安全性可以接受吗?

  • 模板由用户输入,带有[[contact.name]]等标签
  • 保存后,regex将这些变量转换为PHP变量,因此上面的通配符在模板字符串中变为{$contact['name']}
  • 我们还检查是否存在任何可以从超全局范围转换为可访问变量的内容,因此[[_SERVER]][[GLOBALS]]等以及[[this都被禁止并记录为黑客尝试
  • 在双引号字符串中具有特殊含义的其他字符($"')也被转义
  • 生成过程如下:
    • generation是一个运行的类方法。传入的唯一变量是$contact,它是一个数组
    • 模板字符串被读出到另一个局部变量(在这种情况下是$__templateString)中。理论上,用户可以在他们的模板中访问这个变量,但如果他们这样做并不重要——这不是安全风险,只是愚蠢
    • 生成模板的代码就是简单的eval('return "' . $__templateString . '";');

这里有我遗漏的洞吗?我很确定唯一的潜在风险是范围访问问题,我想我已经涵盖了我在那里的所有基础。

如果我输入这个模板:

" . mysql_query('DROP TABLE users') . "

很好的是,您可以防止可能访问您不希望人们访问的变量,但eval会评估所有代码,而不仅仅是变量。试着找到一个正则表达式来过滤掉。。。

轶事驱动:当我是Linux发行版的安全联系人时,PHP开发人员要求我们停止将错误输入的解释器崩溃称为"安全漏洞"。他们坚持认为,提供脚本的人是100%可信的,我完全希望eval()也能以同样的方式处理。

你可以尝试修补问题,但我肯定不会向无限用户开放输入。忽略解释器崩溃错误的可能性太高了。

此外,考虑使用强制性访问控制系统进行部署,如AppArmor、SELinux、TOMOYO或SMACK。通过这种方式,你可以将黑客输入的潜在损害限制在最初完成工作所需的最小资源量内。(我从2000年开始使用AppArmor,因此它将是我在许多环境中的首选。但考虑一下其他产品,它们都是为解决不同问题而设计的高质量产品,其中一种或另一种可能更适合您的环境。)