Gitea Stacks Overflow

1@ 前言

Golang 是一个内存安全的语言,其运行栈是动态增长的。

Go 语言实现了可变长度的栈,栈的大小会随着使用而增长,可达到 1GB 左右的上下。所以 Go 可以放心安全的使用深度递归不用担心一般的栈溢出问题。

但是如果出现代码上函数相关的死循环的话,还是会出现栈溢出的,譬如 Gitea 的这次栈溢出。

2@ 漏洞分析

受影响版本 :

v1.9.0 <= Gitea Version <= v1.13.1 (截止发现漏洞最新版本)

漏洞定位很简单,在/routers/repo/editor.go 文件当中,代码问题存在于 690 行左右的函数GetClosestParentWithFiles() 当中。函数作用是在删除仓库文件后,寻找与其最近的一个文件夹是否有内容,如果有则保留,如果无则空文件夹也将被删除(github gitee 都采用了这样的仓库目录管理方法)。

使用函数 filepath.Dir() 进行上级目录的回溯。

1.png

这里的问题就在于有一种入参使得 fiilepath.Dir() 递归返回的一直不为空,这种参数就是 windows 下带盘符的路径。譬如 e:/, 回溯到尽头也只能是e:\。 所以代码在 697 行会死循环(e:\ 也无法寻找的 entry),由于是函数返回,递归下去会一直增长运行栈,虽然 Golang 的运行栈会动态增长,但是也有上限,最终会造成栈溢出,导致服务崩溃

3@ 漏洞修复

代码中处理符号 : ,回溯到尽头也和 ./ 等路径一样返回,或者不允许这类输入的出现。

官方修复使用 path.Dir() 替换了 filepath.Dir(), 解决了递归的问题。

4@ 漏洞小结

此漏洞是在复现文件删除漏洞时发现的,值得注意的是,某些版本的文件删除类漏洞修复存在绕过。

refence:

https://github.com/go-gitea/gitea/pull/14390

查看评论