• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

Parsedown 解析 Markdown 过滤 XSS 时应如何处理 html 转义

php 搞代码 4年前 (2022-01-25) 18次浏览 已收录 0个评论
文章目录[隐藏]

用 Parsedown 对 Markdown 进行解析的时候,遇到了一些 XSS 过滤方面的问题。

发现 Parsedown 会对 代码 区域内的 html 代码进行转义,代码区域外的却不进行转义,如以下代码所示

<code>PHP</code><code><?phpinclude 'Parsedown.php';$test = "```\n<script>alert('test')</script>\n```\n<script>alert('test')</script>";$Parsedown = new Parsedown();echo $Parsedown->text($test);/**  * 得到结果是:  * <pre class="prettyprint linenums"><code><script>alert('test')</script></code>

* <script>alert(‘test’)</script> * */

这样,<script>alert('test')</script>这句还是被成功执行了


既然如此,那我先自己给它转义一下

<code>PHP</code><code><?phpinclude 'Parsedown.php';include 'com.func.php';$test = "```\n<script>alert('test')</script>\n```\n<script>alert('test')</script>";$test = htmlspecialchars($test, ENT_QUOTES);$Parsedown = new Parsedown();echo $Parsedown->text($test);/**  * 得到结果是:  * <pre class="prettyprint linenums"><code>&lt;script&gt;alert('test')&lt;/script&gt;</code>

*

<script>alert('test')</script>

*/

虽然 XSS 是被过滤掉了,但是代码区域的内容就被转义了两次

然后我发现 SF 的 Markdown 好像是在后端就解析好的,例如这个页面,它的部分源码如下:

<code>html</code><code><br><br><p>我现在的代码是这样的<br><html><br><head><br><br>    <title>Untitled Document</title></p><pre class="prettyprint linenums"><code><script>    function test(){        <?php            $conn = mysql_connect("localhost", "username", "123123");            mysql_select_db("username", $conn);            mysql_query("INSERT INTO ChargerTogether (Chat) VALUES ('test')");            $result= mysql_query("SELECT *FROM ChargerTogether");            echo "<p> {$result} </p>>";        ?>    }</script></code>

</head>
<body>
<input type=”button” onClick=”javascript:test();”>

</body>
</html>

但这样是错误的
我该怎样做呢

这里的转义就做得很好。


我想到的解决方案是:先转义,再用 Parsedown 进行解析,接着正则匹配出解析后 内的代码,对其进行反转义(一次)。

不知道是不是还有别的更好的转义函数,或者说 有没有其他的能够过滤 XSS 的 Markdown 解析类

P.S. 我在 github 上面找到有个 markdown-js。用这个东西的话可以把经htmlspecialchars(()转义后的字符串直接输出到一个 textaera 里,它能够正确地解析。虽然我可以把那个文本框隐藏起来,但是如果需要输出很多段 Markdown (帖子有很多回复)的话,那可不是一个好的解决方案啊!

回复内容:

用 Parsedown 对 Markdown 进行解析的时候,遇到了一些 XSS 过滤方面的问题。

发现 Parsedown 会对 代码 区域内的 html 代码进行转义,代码区域外的却/本文来源gaodai#ma#com搞*!代#%^码网%搞代gaodaima码不进行转义,如以下代码所示

<code>PHP</code><code><?phpinclude 'Parsedown.php';$test = "```\n<script>alert('test')</script>\n```\n<script>alert('test')</script>";$Parsedown = new Parsedown();echo $Parsedown->text($test);/**  * 得到结果是:  * <pre class="prettyprint linenums"><code><script>alert('test')</script></code>

* <script>alert(‘test’)</script> * */

这样,<script>alert('test')</script>这句还是被成功执行了


既然如此,那我先自己给它转义一下

<code>PHP</code><code><?phpinclude 'Parsedown.php';include 'com.func.php';$test = "```\n<script>alert('test')</script>\n```\n<script>alert('test')</script>";$test = htmlspecialchars($test, ENT_QUOTES);$Parsedown = new Parsedown();echo $Parsedown->text($test);/**  * 得到结果是:  * <pre class="prettyprint linenums"><code>&lt;script&gt;alert('test')&lt;/script&gt;</code>

*

<script>alert('test')</script>

*/

虽然 XSS 是被过滤掉了,但是代码区域的内容就被转义了两次

然后我发现 SF 的 Markdown 好像是在后端就解析好的,例如这个页面,它的部分源码如下:

<code>html</code><code><br><br><p>我现在的代码是这样的<br><html><br><head><br><br>    <title>Untitled Document</title></p><pre class="prettyprint linenums"><code><script>    function test(){        <?php            $conn = mysql_connect("localhost", "username", "123123");            mysql_select_db("username", $conn);            mysql_query("INSERT INTO ChargerTogether (Chat) VALUES ('test')");            $result= mysql_query("SELECT *FROM ChargerTogether");            echo "<p> {$result} </p>>";        ?>    }</script></code>

</head>
<body>
<input type=”button” onClick=”javascript:test();”>

</body>
</html>

但这样是错误的
我该怎样做呢

这里的转义就做得很好。


我想到的解决方案是:先转义,再用 Parsedown 进行解析,接着正则匹配出解析后 内的代码,对其进行反转义(一次)。

不知道是不是还有别的更好的转义函数,或者说 有没有其他的能够过滤 XSS 的 Markdown 解析类

P.S. 我在 github 上面找到有个 markdown-js。用这个东西的话可以把经htmlspecialchars(()转义后的字符串直接输出到一个 textaera 里,它能够正确地解析。虽然我可以把那个文本框隐藏起来,但是如果需要输出很多段 Markdown (帖子有很多回复)的话,那可不是一个好的解决方案啊!

刚刚把 Parsedown 源码里所有(共三处)转义用的语句(如下所示)给注释掉,

<code>PHP</code><code>$text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8');</code>

这句出现在了以下三个方法中:
protected function blockCodeComplete($Block)protected function blockFencedCodeComplete($Block)protected function inlineCode($Excerpt)

然后再修改一下 function text($text)

<code>function text($text)    {        #添加下面这行        $text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8');        # Code...    }</code>

这么做虽然说是解决了,但是可能不是最完美的解决方案,还请各位大大继续提供更好的方案~

我也遇到这个问题了,后来发现,只要把代码块外面的 <script></script> 写成<script/>即可,这样就会转换成文字了。


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:Parsedown 解析 Markdown 过滤 XSS 时应如何处理 html 转义

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址