1

我一直对编写像论坛或博客这样的网络软件很感兴趣,这些东西需要有限的标记才能重写为 HTML。但是最近,我越来越多地注意到对于 PHP,尝试谷歌搜索“PHP BBCode parser -PEAR”并测试一些,你要么得到一个低效的混乱,要么你得到的代码很糟糕,到处都是 XSS 漏洞。

以我之前提到的例子为例,在那些糟糕的 BBCode 解析器中,你将如何避免 XSS?我现在将使用您的典型正则表达式来处理链接,您可以提及它的脆弱性以及如何避免它。

// Assume input has already been encoded by htmlspecialchars with ENT_QUOTES
$text = preg_replace('#\[url\](.*?)\[/url\]#i','<a href="\1">\1</a>', $text);
$text = preg_replace('#\[url=(.*?)\](.*?)\[/url\]#i','<a href="\1">\2</a>', $text);

处理图像标签几乎没有比这更安全的了。

所以我有几个具体的问题,主要是针对 PHP 实现的。

  1. 在此示例中,仅使用 uri/url 验证表达式进行匹配是否更好?或者,最好使用(.*?)回调,然后确定输入是否是有效链接?正如上面显而易见的javascript:alert('XSS!')那样,在上面的 URL 标记中可以工作,但如果完成 uri 匹配,则会失败。
  2. 回调中的函数怎么样urlencode(),它们会是什么威慑或问题(就 URI 标准而言)?
  3. 编写全栈解析器会更安全吗?或者,对于每页处理多个不同条目的东西来说,开发和使用这样的东西所需的时间和处理能力是否太重了?

我知道我的示例是众多示例之一,并且比某些示例更具体。但是,不要逃避提供自己的。 因此,我正在寻找文本解析情况下 XSS 保护的原则和最佳实践以及一般建议。

4

1 回答 1

4

测试一些,你要么得到一个低效的混乱,要么你得到带有 XSS 漏洞的糟糕代码

地狱是的。我还没有遇到过不受 XSS 攻击的 bbcode 实现。

'<a href="\1">\1</a>'

不好:无法 HTML 转义 '<'、'&' 和 '"' 字符。

在此示例中,仅使用 uri/url 验证表达式进行匹配是否更好?或者,最好使用 (.*?) 和回调,然后确定输入是否是有效链接?

我会接电话。无论如何,您都需要回调来进行 HTML 转义;仅通过简单的字符串替换是不可能安全的。在你做的时候把消毒剂放进去。

回调中的 urlencode() 之类的函数呢?

几乎; 实际上你需要 htmlspecialchars()。urlencode() 是关于编码查询参数的,这不是你需要的。

编写全栈解析器会更安全吗?

是的。

bbcode 并不真正适合正则表达式解析,因为它是一种基于递归标记的语言(如 XML,正则表达式也无法解析)。许多 bbcode 漏洞是由嵌套和错误嵌套问题引起的。例如:

[url]http://www.example.com/[i][/url]foo[/i]

可能会像这样

<a href="http://www.example.com/&lt;i>">foo</i>

还有许多其他陷阱会在各种 bbcode 实现上生成损坏的代码(最多包括 XSS 漏洞)。

我正在寻找原则和最佳实践

如果您需要一种可以正则表达式的类似 bbcode 的语言,您需要:

  • 减少可以放在其他标签内的可能标签的数量。任意嵌套实际上是不可能支持的
  • 对 '<' 使用特殊字符 和'>' HTML 标记分隔符,以将它们与应该在文本中显示的真实尖括号区分开来。我使用 ASCII 控制代码(之前在用户输入阶段过滤了任何控制字符)。
  • 将在这些控制字符上处理的字符串拆分为这两个控制字符之间的内容,这样您就永远不会让 bbcode 跨度到达标签内部或标签边界之上。
  • 因为你不能让 bbcode 跨度通过标签边界从外向内工作,首先做大块元素,然后向内工作到链接,最后是粗体和斜体。
  • 为了理智,一次处理一个块。例如。如果您在双换行符上开始一个新的 <p>,则没有 bbcode 标记可以跨越两个单独的块。

做对还是很困难的。一个合适的解析器更有可能是无懈可击的。

于 2009-04-09T17:27:19.593 回答