CodeQL 文档

存档提取期间的任意文件访问(“Zip 压缩文件路径遍历漏洞”)

ID: go/zipslip
Kind: path-problem
Security severity: 7.5
Severity: error
Precision: high
Tags:
   - security
   - external/cwe/cwe-022
Query suites:
   - go-code-scanning.qls
   - go-security-extended.qls
   - go-security-and-quality.qls

点击查看 CodeQL 代码库中的查询

如果未正确验证存档中的文件名,则从恶意 zip 文件或类似类型的存档中提取文件时,可能会面临目录遍历攻击的风险。存档路径。

Zip 存档包含表示存档中每个文件的存档条目。这些条目包括条目的文件路径,但这些文件路径不受限制,并且可能包含意外的特殊元素,例如目录遍历元素 (..)。如果使用这些文件路径创建文件系统路径,则文件操作可能会在意外的位置发生。这可能会导致敏感信息被泄露或删除,或者攻击者能够通过修改意外文件来影响行为。

例如,如果 zip 文件包含文件条目 ..\sneaky-file,并且 zip 文件被提取到目录 c:\output 中,则简单地组合路径会导致输出文件路径为 c:\output\..\sneaky-file,这将导致文件被写入 c:\sneaky-file

建议

确保验证从 zip 存档条目构造的输出路径,以防止将文件写入意外的位置。

写入 zip 存档条目中的输出文件的建议方法是检查路径中是否出现“..”。

示例

在此示例中,提取存档时未验证文件路径。如果 archive.zip 包含相对路径(例如,如果它是通过类似 zip archive.zip ../file.txt 的命令创建的),则执行此代码可能会写入目标目录以外的位置。

package main

import (
	"archive/zip"
	"io/ioutil"
	"path/filepath"
)

func unzip(f string) {
	r, _ := zip.OpenReader(f)
	for _, f := range r.File {
		p, _ := filepath.Abs(f.Name)
		// BAD: This could overwrite any file on the file system
		ioutil.WriteFile(p, []byte("present"), 0666)
	}
}

要修复此漏洞,我们需要检查路径中是否包含任何“..”元素。

package main

import (
	"archive/zip"
	"io/ioutil"
	"path/filepath"
	"strings"
)

func unzipGood(f string) {
	r, _ := zip.OpenReader(f)
	for _, f := range r.File {
		p, _ := filepath.Abs(f.Name)
		// GOOD: Check that path does not contain ".." before using it
		if !strings.Contains(f.Name, "..") {
			ioutil.WriteFile(p, []byte("present"), 0666)
		}
	}
}

参考

  • ©GitHub, Inc.
  • 条款
  • 隐私