欢迎光临散文网 会员登陆 & 注册

一个隐藏在Go语言标准库中的目录穿越漏洞 CVE-2022-29804

2023-05-30 21:14 作者:白帽酱  | 我要投稿

前言

这是半年前我在 Go 语言中发现的一个目录穿越漏洞(虽然被人抢先发现了)。
Go 语言支持非常方便的交叉编译,但是在不同平台下,操作系统对某些功能的实现有所差异。这些差异可能会导致一些安全问题。

一天,我看完了番剧后,闲着无聊审计了一下我用来做内网共享的小工具——“Go HTTP File Server”。
这是一个跨平台的文件服务器,它可以快速搭建一个简单的HTTP服务器来共享文件。
它的默认共享路径为当前路径(./)

代码审计

非常安全的代码?

这个工具默认是没有鉴权的  所以我们直接看文件浏览的部分

乍一看上去,这段代码好像没有什么问题。它使用了 Go 标准库中的 filepath.Clean (去除 ..) 和 filepath.Join(合并路径) 函数,来防止目录穿越。

标准库中的漏洞

我刚好还有些空余时间,所以我又开始检查 Go 标准库中的函数实现。

filepath.Clean

调试了一遍后,我发现 filepath.Clean 对路径处理非常完美。这个函数可以将路径中的冗余部分去除,同时可以处理不同操作系统下的路径分隔符问题.

filepath.Join

但是 filepath.Join 函数就不太一样了,这个函数在 Plan9、Unix 和 Windows 三个操作系统类型下有着不同的实现。

在 Unix 系统下,filepath.Join 非常简单,它会在Clean之后直接拼接路径,没有任何问题。

在 Windows 系统下,filepath.Join 函数的实现要复杂得多,因为需要处理路径分隔符和 UNC 路径等特殊情况。
到这里就变得有趣了一些 filepath.Join 的输入不完全是用户控制的  Clean函数会把用户输入和固定路径一起处理
这个工具刚好出现了一个非常特殊的情况
文件服务器本来想要限制访问当前目录下的文件
filepath.Join("./",'已经处理后的用户输入')
如果输入的路径是./ abc/1.txt
Clean处理后会变成 abc/1.txt Clean去除了开头的设定的./
这个处理在linux系统下没有问题
但是在windows 系统下 如果我们构造路径组./ c:/1.txt
Clean处理后会变成 c:/1.txt
显然从Clean处理后把当前目录下的路径变为了c盘根目录
在这里,filepath.Clean 函数的处理并没有避免目录穿越问题,反而造成了一个安全漏洞。
最终在http server 上复现成功

小插曲

提交给go 官方之后才发现这洞3个月前就被修复了. 我电脑上的go版本一直没更新 23333

漏洞issue
https://github.com/golang/go/issues/52476

漏洞影响&利用条件

  1. 使用 filepath.Clean/filepath.Join 处理路径

  2. 左侧被拼接路径为./

  3. 右侧路径可完全控制

  4. Go编译Windows二进制文件使用  Go 1.18 <1.18.3  Go 1.17 <1.17.11 (不在维护的版本应该不会修复)

  5. 目标二进制部署在windows 操作系统

标准库的漏洞会影响编译分发出的二进制文件

解决方法

更新go到最新版本 重新编译发布二进制文件



一个隐藏在Go语言标准库中的目录穿越漏洞 CVE-2022-29804的评论 (共 条)

分享到微博请遵守国家法律