本文概述
Markdown使用非常用户友好的格式语法来完成HTML或Rich Text Formatting的功能, 并且使用正确的工具在服务器端进行解析过程也非常容易。但是, 如果你最喜欢的Markdown解析器无法正确处理生成的HTML, 那么当有人发现你的应用程序容易受到XSS攻击时, 你将会遇到麻烦。 XSS攻击是指代码注入攻击, 攻击者可以在其中将恶意脚本执行到网站或Web应用程序中。关键是, 只有在攻击者插入的有效负载(恶意脚本)在受害者浏览器中被解析为HTML的情况下, 才可以利用XSS漏洞。
当然, 你已经听说过PHP函数htmlentities, htmlspecialchars等, 这些函数允许你对HTML上使用的符号进行编码和解码, 但是如果你没有太多时间, 则无法自行使用它。主要是, 解析器应提供正确的功能, 但是它们也必须灵活且有用, 但是有时由于项目的特性, 它可能无法100%正确地工作。例如, 以下降价促销:
# Hello World
I am a programmer and i wrant to write code. I don't write code with bad intentions, just share my knowledge
```html
<script>
alert("First alert");
</script>
```
<script>alert("second alert");</script>
<img src="http://url.to.file.which/not.exist" onerror=alert(document.cookie);>
使用cebeb的markdown解析器将其解析为HTML, 并在浏览器中呈现, 将仅发出”第二警报”警报。这是因为解析器足够聪明, 可以将代码块内的所有内容自动转换为相应的HTML实体。但是, 任何代码块之外的脚本标签仍被浏览器解释为JavaScript, 这显然是一个问题, 从不存在的文件加载的img也将被触发。
在本文中, 我们将向你展示如何防止JavaScript插入
Parsedown解决方案
通过解析提供在解析中的markdown内的所有标记, Parsedown使事情变得非常容易。但是, 默认情况下未启用它, 并且不足以阻止所有XSS攻击方式。因此, 如果你想使用安全版本的Parsedown, 我们建议你使用secureparsedown软件包。 Aidan Woods对原始parsedown库所做的更改提供了一种安全模式的实现, 该模式将保护HTML不受XSS的攻击。
在这种情况下, 具有Aidan更改的1.7.0版本尚未发布, 因此直到你可以从以下软件包下载parsedown的安全版本之日:
composer require aidantwoods/secureparsedown
使用此版本的优点是它将使用Parsedown的最新版本, 但也会创建安全模式。或者, 如果愿意, 请手动修改composer.json文件, 然后运行composer install:
{
"require": {
"aidantwoods/secureparsedown": "^1.0"
}
}
安装完成后, 像平常一样使用Parsedown, 不要忘记使用setMarkupEscaped和setSafeMode方法来提供安全的HTML来呈现:
<?php
use Aidantwoods\SecureParsedown\SecureParsedown;
$markdown = "# Title <script>alert('XSS Attack ...');</script>";
$Parsedown = new SecureParsedown;
// Escape the input markdown to prevent any html from being and enable parsedown in safe mode
$Parsedown->setSafeMode(true);
// Secure HTML
echo $Parsedown->text($markdown);
这很方便, 因为Markdown内部所有解释为HTML的文本都将转换为其无害的html实体表示形式(这可以防止XSS攻击)。但是, 此功能仅在该库中可用。如果要防止出现某些特定标签, 请也从其他解析器库中实施解决方案。
其他解析器库的解决方案
如果你在PHP中使用其他Markdown解析器, 则它可能不会具有Parsedown的相同功能。在这种情况下, 你将需要安装htmlpurifier库。 HTML Purifier是用PHP编写的符合标准的HTML过滤器库。 HTML Purifier不仅会使用经过全面审核, 安全且允许的白名单删除所有恶意代码(更名为XSS), 还将确保你的文档符合标准, 这只有在全面了解W3C规范的情况下才能实现。
要使用Composer在项目中安装htmlpurifier, 请在终端上执行以下命令:
composer require "ezyang/htmlpurifier":"dev-master"
使用Composer将库安装到项目中之后, 你将可以轻松使用它。通过从解析器处理的markdown生成的HTML中删除脚本标签来实现目标的最简单方法是, 通过使用选项HTML.ForbiddenElements禁止特定标签(每个标签都是参数数组的一项):
<?php
// The source of your markdown
$markdown = "# Title <script>alert('Super unsafe markdown ...');</script>";
// Create an instance of your parser if available ...
$parser = new YourFavoriteMarkdownParserExample();
// This contains the generated HTML from your markdown
$parsedMarkdown = $parser->parse($markdown);
// Initialize a config object of html purifier
$config = HTMLPurifier_Config::createDefault();
// The HTML nodes that you want to prevent from being rendered
// as second argument within an array
$config->set('HTML.ForbiddenElements', array('script', 'applet'));
// Initialize html purifier
$purifier = new HTMLPurifier($config);
// Purify the generated HTML and
// Use this safe HTML to display in the browser !
$HTMLWithoutForbiddenTags = $purifier->purify($parsedMarkdown);
另外, 如果你希望完全控制将要呈现的标签, 则可以决定可以呈现哪些HTML标签以及哪些属性:
<?php
// The source of your markdown
$markdown = "# Title <script>alert('Super unsafe markdown ...');</script>";
$parser = new YourFavoriteMarkdownParserExample();
$config = \HTMLPurifier_Config::createDefault();
// Allow Text without tag e.g P or DIV (plain text, obviously necessary for markdown)
$config->set('Core.LexerImpl', 'DirectLex');
// Define manually which elements can be rendered
// In this example, we allow (almost) all the basic elements that are converted with markdown
$config->set('HTML.Allowed', 'h1, h2, h3, h4, h5, h6, br, b, i, strong, em, a, pre, code, img, tt, div, ins, del, sup, sub, p, ol, ul, table, thead, tbody, tfoot, blockquote, dl, dt, dd, kbd, q, samp, var, hr, li, tr, td, th, s, strike');
// The attributes are up to you
$config->set('HTML.AllowedAttributes', 'img.src, *.style, *.class, code.class, a.href, *.target');
// Create an instance of the purifier with the configuration
$purifier = new \HTMLPurifier($config);
// Print the purified HTML
echo $purifier->purify($parser->text($markdown));
编码愉快!
评论前必须登录!
注册