【问题标题】:Sanitize Markdown from XSS清理 XSS 中的 Markdown
【发布时间】:2013-02-01 14:52:57
【问题描述】:

我使用 Markdown 提供了一种在我的论坛脚本中向我的用户写帖子的简单方法。
我正在尝试清理每个用户输入,但我对 Markdown 的输入有疑问。

我需要在数据库中存储 Markdown 文本,而不是 HTML 转换的版本,因为允许用户编辑他们的帖子。

基本上我需要像 StackOverflow 那样的东西。

我阅读了this article 关于 Markdown 的 XSS 漏洞。我发现的唯一解决方案是在我的脚本提供的每个输出之前使用 HTML_purifier。

我认为这会减慢我的脚本,我想输出 20 个帖子并为每个帖子运行 HTML_purifier...

因此,我试图找到一种解决方案来清除 XSS 漏洞,从而清除输入而不是输出。

我无法在输入上运行 HTML_purifier,因为我的文本是 Markdown,而不是 HTML。如果我将其转换为获取 HTML,我将无法将其转换回 Markdown。

我已经删除(我希望)所有 HTML 代码:

htmlspecialchars(strip_tags($text));

我已经考虑过另一种解决方案:

当用户尝试提交新帖子时: 将输入从 Markdown 转换为 HTML,运行 HTML_purifier,如果它发现一些 XSS 注入,它只会返回一个错误。 但我不知道怎么做,也不知道 HTML_purifier 是否允许。

我在那里发现了很多关于同一问题的问题,但所有解决方案都是将输入存储为 HTML。我需要存储为 Markdown。

有人有什么建议吗?

【问题讨论】:

  • 1.使用 strip_tags() 从输入中删除 所有 标记,2. 清理在 [link](javascript:alert('xss')) 等属性中使用的输入:3. 考虑运行 htmlspecialchars()在将输入转换为 HTML 和输出之前。应该是相当安全的吧?我的意思是只有你可以控制要使用的 HTML 标签,只要你在输入中剥离它们并清理你可以完全控制 XSS 的属性。
  • 它不会阻止我的链接中显示的错误。
  • 嗯,如果它没有检测到多行标签,那就太令人沮丧了..
  • 你能解释一下你的句子吗?我不明白。
  • 我认为您在链接中提到的漏洞或错误表明,如果您将 html 标签分成多行,则不会正确剥离它。

标签: php html xss markdown code-injection


【解决方案1】:
  1. 在输入上运行 Markdown
  2. 对 Markdown 生成的 HTML 运行 HTML Purifier。对其进行配置,使其允许链接、href 属性等(它仍应去除javascript: 命令)

// the nasty stuff :)
$content = "> hello <a name=\"n\" \n href=\"javascript:alert('xss')\">*you*</a>";

require '/path/to/markdown.php';

// at this point, the generated HTML is vulnerable to XSS
$content = Markdown($content);

require '/path/to//HTMLPurifier/HTMLPurifier.auto.php';

$config = HTMLPurifier_Config::createDefault();
$config->set('Core.Encoding', 'UTF-8');
$config->set('HTML.Doctype', 'XHTML 1.0 Transitional');
$config->set('Cache.DefinitionImpl', null);

// put here every tag and attribute that you want to pass through
$config->set('HTML.Allowed', 'a[href|title],blockquote[cite]');

$purifier = new HTMLPurifier($config);

// here, the javascript command is stripped off
$content = $purifier->purify($content);

print $content;

【讨论】:

  • 谢谢,但是......找到所有出现的“javascript:”并删除它们还不够吗?没有 html_purifier 但只有一个正则表达式。
  • @FezVrasta 没有机会。有很多方法可以避免使用字符串“javascript”——owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet。此外,您甚至无法使用正则表达式解析 HTML。
  • 好的,所以...我将 Markdown 转换为 HTML,使用 HTML_purifier 对其进行清理,然后...如何将 Markdown 存储在数据库中?
  • 存储原始未修改的markdown,在需要显示时对其进行解析和清理。出于性能考虑,您可能希望缓存呈现的 HTML(或将其存储在数据库中)。
  • 你怎么知道他想黑你?这是默默无闻的安全。您最终可能会阻止合法用户。如果 SO 阻止我发布上面的代码怎么办?
【解决方案2】:

解决了……

$text = "> hello <a name=\"n\"
> href=\"javascript:alert('xss')\">*you*</a>";


$text = strip_tags($text);

$text = Markdown($text);

echo $text;

返回:

<blockquote>
  <p>hello  href="javascript:alert('xss')"&gt;<em>you</em></p>
</blockquote>

而不是:

<blockquote>
  <p>hello <a name="n" href="javascript:alert('xss')"><em>you</em></a></p>
</blockquote>

看来strip_tags() 确实有效。

合并:

$text = preg_replace('/href=(\"|)javascript:/', "", $text);

应从 XSS 注入中清除整个输入。如果我错了,请纠正我。

【讨论】:

    【解决方案3】:

    你的markdown的html输出只依赖md解析器,所以你可以

    1. 将您的 md 转换为 html,然后按照此处所述对 html 进行清理:

      Escape from XSS vulnerability maintaining Markdown syntax?

    2. 或者你可以修改你的 md 解析器来检查每个进入 html 属性的参数是否有 xss 的迹象。 Ofc 你应该在解析之前转义 html 标签。我认为这个解决方案比其他解决方案快得多,因为通过简单的文本,您通常应该只检查图片和链接的网址。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-10-20
      • 2010-11-25
      • 1970-01-01
      • 2013-06-11
      • 2018-12-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多