目录

Golang审计: 恶意 zip 文件导致目录穿越文件上传

目录

昨天在 Github 上找项目审计,找到了一个高星 Go 项目,发现里面使用到了 zip 解压的操作。记得很久之前看过一个文章,如果 zip 的文件名中包含 ../ 可以造成目录穿越。简单试了一下,发现确实存在漏洞,能够在系统任意目录创建任意文件。

这里我使用 mm-wiki 的代码进行解析(mm-wiki 虽然存在该漏洞,但并没有使用该漏洞函数)

https://cdn.bingbingzi.cn/blog/202204251659166.png

代码的大概意思我已经在上面标注了,注意漏洞点:他没有过滤 ../ 这样的字符,使得攻击者可以在 zip 文件内构造类似 ../../../../../../../../../etc/crontab 的计划任务文件,一旦执行该函数解析恶意 zip 文件,攻击者即可在目标服务器上任意命令执行。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//解压 第132行
func (z *zipx) DeCompress(zipFile, dest string) error {
  // 打开 zip 文件
	reader, err := zip.OpenReader(zipFile)
	if err != nil {
		return err
	}
	defer reader.Close()
  
  // 遍历每一个文件
	for _, file := range reader.File {
    // 打开文件
		rc, err := file.Open()
		if err != nil {
			return err
		}
		defer rc.Close()
    // 构造文件名(漏洞点)
		filename := dest + file.Name
    // 创建文件路径
		err = os.MkdirAll(z.getDir(filename), 0755)
		if err != nil {
			return err
		}
    // 创建文件
		w, err := os.Create(filename)
		if err != nil {
			return err
		}
		defer w.Close()
    // 将文件内容拷贝至目标文件路径
		_, err = io.Copy(w, rc)
		if err != nil {
			return err
		}
		w.Close()
		rc.Close()
	}
	return nil
}