如何防止XSS攻击并禁止PHP Markdown解析器生成的HTML中的特定标签

本文概述

  • Parsedown解决方案
  • 其他解析器库的解决方案
Markdown使用非常用户友好的格式语法来完成HTML或Rich Text Formatting的功能, 并且使用正确的工具在服务器端进行解析过程也非常容易。但是, 如果你最喜欢的Markdown解析器无法正确处理生成的HTML, 那么当有人发现你的应用程序容易受到XSS攻击时, 你将会遇到麻烦。 XSS攻击是指代码注入攻击, 攻击者可以在其中将恶意脚本执行到网站或Web应用程序中。关键是, 只有在攻击者插入的有效负载(恶意脚本)在受害者浏览器中被解析为HTML的情况下, 才可以利用XSS漏洞。
当然, 你已经听说过PHP函数htmlentities, htmlspecialchars等, 这些函数允许你对HTML上使用的符号进行编码和解码, 但是如果你没有太多时间, 则无法自行使用它。主要是, 解析器应提供正确的功能, 但是它们也必须灵活且有用, 但是有时由于项目的特性, 它可能无法100%正确地工作。例如, 以下降价促销:
# Hello WorldI 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来呈现:
< ?phpuse 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 HTMLecho $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));

【如何防止XSS攻击并禁止PHP Markdown解析器生成的HTML中的特定标签】编码愉快!

    推荐阅读