gomarkdown/markdown 项目的 XSS 漏洞产生与分析

VSole2021-08-24 17:02:02

前言

gomarkdown/markdown 是 Go 语言的一个流行模块,它旨在快速地将 Markdown 文档转化为 HTML 页面。而此次发现的漏洞,来源于作者在编写其语法树 Parser 的时候无意的一次 unescape。

漏洞复现

我们首先来看一段代码。

package mainimport (    "fmt"    "github.com/gomarkdown/markdown"    "html")func main() {    var textToRender = "```\"1;>```"    var middleware = html.EscapeString(textToRender)    var result = markdown.ToHTML([]byte(middleware), nil, nil)    fmt.Println(string(result))}

大部分人一眼看过来,发现有 html.EscapeString 方法进行过滤,可能就跟笔者一开始一样,认为这里一定没什么问题。其实不然,我们可以采用 v0.0.0-20210514010506-3b9f47219fe7,也就是笔者提交 issue 之前的最新版本来试一下,看结果会怎样。

可以发现我们原本使用 html.EscapeString 进行转义的字符不受影响地出现在了结果中,从而导致了 script 标签被单独完整地渲染到 HTML,从而引入了一个外部 js 文件。更进一步的说,为 XSS 提供了完美的条件。

漏洞分析

使用上述给出的代码进行调试,先看一个调用栈。

从 ToHTML 方法进来之后直接到 doc := Parse(markdown, p),从而进入了 Parse 这个方法。

然后就是调用到 block 方法对输入的 Markdown 字符串进行分块的处理。在逐一判断到代码块后进入了 fencedCodeBlock 方法。

在其中将代码块的内容分解填入对象之后,会进入 finalizeCodeBlock 进行一个收尾工作。

跟进去之后可以发现这个方法是这样的。

func finalizeCodeBlock(code *ast.CodeBlock) {    c := code.Content    if code.IsFenced {        newlinePos := bytes.IndexByte(c, '')        firstLine := c[:newlinePos]        rest := c[newlinePos+1:]        code.Info = unescapeString(bytes.Trim(firstLine, ""))        code.Literal = rest    } else {        code.Literal = c    }    code.Content = nil}

code.Info 的内容被 unescapeString 处理了一次,也就是最后得到意外结果的问题根源。接着往后跟踪,可以发现处理后的内容被放进对象 p 后直接利用语法树完成了渲染,最终得到 HTML 字符串,而被解码后的内容并没有被二次转义。

因此,最后得到的字符串就出现了上文的问题。

漏洞的修复

由于漏洞的产生是因为解码后没有再次编码,因此可以将其使用 html.EscapeString 重新处理一次,将原有的语句做如下替换。

- code.Info = unescapeString(bytes.Trim(firstLine, ""))+ code.Info = []byte(html.EscapeString(string(unescapeString(bytes.Trim(firstLine, "")))))

此时再重新运行一次文章开始时给出的代码,可以得到如下结果。

<pre><code class="language-"1;&gt;&lt;script/src="http://HOST/xss.js"&gt;&lt;/script&gt;">code>pre>

可以发现由于再次进行了 HTML 实体转义,script 标签没有被独立渲染,从而避免了 XSS 的产生。

xssmarkdown
本作品采用《CC 协议》,转载必须注明作者和本文链接
跨站脚本英文全称(Cross Site Scripting跨站脚本),为了不和css层叠样式表(英文全称:Cascading Style Sheets)混淆,因此将跨站脚本缩写为XSS。本期我们讲解一下XSS漏洞原理和利用检测。
gomarkdown/markdown 是 Go 语言的一个流行模块,它旨在快速地将 Markdown 文档转化为 HTML 页面。而此次发现的漏洞,来源于作者在编写其语法树 Parser 的时候无意的一次 unescape。
每个黑客都会遇到这个,第一个赏金。我实际上无法解释它的感觉,但我知道你们中的大多数人都能理解它的感觉。当我们开始在 Web 应用程序安全中进行漏洞赏金时,我们大多数人都会从 XSS开始,故事从这里开始。
存储空间的名称在 OSS 范围内必须是全局唯一的,一旦创建之后无法修改名称。和传统的文件系统不同,对象没有文件目录层级结构的关系。因此可以登录自己的阿里云账号,创建同样的 Bucket 即可。
存储空间的名称在 OSS 范围内必须是全局唯一的,一旦创建之后无法修改名称。和传统的文件系统不同,对象没有文件目录层级结构的关系。因此可以登录自己的阿里云账号,创建同样的 Bucket 即可。
为了提高安全服务项目的检测效率、规范性、全面性,Tide安全团队结合在渗透测试行业的经验和安全开发方面的积累,开发了一款自动化渗透测试工具。 该工具使用Golang开发为CS架构,集“资产探测-服务识别-爬虫-被动监测-漏洞扫描-POC检测-截屏-报告”于一体,适合甲方或乙方安服团队对目标系统进行全面的安全检测并输出报告。 本文主要介绍一下该工具的框架及部分实现思路。
Lodash 是一个 JavaScript 库,包含简化字符串、数字、数组、函数和对象编程的工具,可以帮助程序员更有效地编写和维护 JavaScript 代码。并且是一个流行的 npm 库,仅在GitHub 上就有超过 400 万个项目使用,Lodash的普及率非常高,每月的下载量超过 8000 万次。但是这个库中有几个严重的原型污染漏洞。
XSS 扫描工具 -- DalFox
2023-03-10 10:54:24
它配备了强大的测试引擎,为渗透测试提供了许多利基功能!
它的主要特性有:1、动态地语义分析网页中的JavaScript源码,Hook关键点,利用污点分析检出 Dom-Based XSS2、极低的误报率:通过监听浏览器对话框弹出事件等进行验证。--proxy value set proxy and all traffic will be routed from the proxy server through
XSS漏洞是Web应用程序中最常见的漏洞之一。如果您的站点没有预防XSS漏洞的固定方法,那么很可能就存在XSS漏洞。 这篇文章将带你通过代码层面去理解三个问题: 什么是XSS漏洞? XSS漏洞有哪些分类? 如何防范XSS漏洞?
VSole
网络安全专家