从XSS消除Markdown

时间:2013-02-16 20:42:31

标签: php html xss markdown code-injection

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

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

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

我阅读了关于Markdown的XSS漏洞的this article。我找到的唯一解决方案是在我的脚本提供的每个输出之前使用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。

有人有什么建议吗?

3 个答案:

答案 0 :(得分:7)

  1. 在输入上运行Markdown
  2. 在Markdown生成的HTML上运行HTML Purifier。配置它,以便它允许链接,href属性等(它应该仍然剥离javascript:命令)

  3. // 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;
    

答案 1 :(得分:0)

解决了......

$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注射中清除整个输入。如果我错了,请纠正我。

答案 2 :(得分:0)

降价的html输出仅取决于md解析器,因此您可以

  1. 将您的md转换为html,并在此之后清理html,如下所述:

    Escape from XSS vulnerability maintaining Markdown syntax?

  2. 或者您可以修改您的md解析器以检查转到html属性的每个参数以获取xss的符号。在解析之前,你应该为html标签转义。我认为这个解决方案比另一个快得多,因为通过简单的文本,你通常应该只通过图像和链接来检查网址。