4

我收到以下golintci消息:

testdrive/utils.go:92:16: G110: Potential DoS vulnerability via decompression bomb (gosec)
    if _, err := io.Copy(targetFile, fileReader); err != nil {
                 ^

阅读相应的CWE,我不清楚如何纠正这一点。

请指点。

func unzip(archive, target string) error {
    reader, err := zip.OpenReader(archive)
    if err != nil {
        return err
    }

    for _, file := range reader.File {
        path := filepath.Join(target, file.Name) // nolint: gosec
        if file.FileInfo().IsDir() {
            if err := os.MkdirAll(path, file.Mode()); err != nil {
                return err
            }
            continue
        }

        fileReader, err := file.Open()
        if err != nil {
            return err
        }
        defer fileReader.Close() // nolint: errcheck

        targetFile, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode())
        if err != nil {
            return err
        }
        defer targetFile.Close() // nolint: errcheck

        if _, err := io.Copy(targetFile, fileReader); err != nil {
            return err
        }
    }

    return nil
}
4

3 回答 3

5

您收到的警告来自gosec中提供的规则。

该规则专门检测io.Copy文件解压缩的使用。

这是一个潜在问题,因为io.Copy

复制 from srctodst直到到达 EOFsrc或发生错误。

因此,恶意负载可能会导致您的程序解压缩大量数据并耗尽内存,从而导致警告消息中提到的拒绝服务。

特别是,gosec 将检查()您程序的 AST,并警告您使用以下任何一项io.Copyio.CopyBuffer与以下任何一项一起使用:

  • "compress/gzip".NewReader
  • "compress/zlib".NewReader或者NewReaderDict
  • "compress/bzip2".NewReader
  • "compress/flate".NewReader或者NewReaderDict
  • "compress/lzw".NewReader
  • "archive/tar".NewReader
  • "archive/zip".NewReader
  • "*archive/zip".File.Open

Usingio.CopyN删除了警告,因为(引用)它“将n 个字节(或直到出现错误)从 src 复制到 dst ”,从而使您(程序编写者)可以控制要复制的字节数。因此,您可以根据应用程序的可用资源设置任意大小n,或者以 chunks 的形式复制

于 2021-04-30T08:41:06.767 回答
2

基于提供的各种指针,替换

        if _, err := io.Copy(targetFile, fileReader); err != nil {
            return err
        }

        for {
            _, err := io.CopyN(targetFile, fileReader, 1024)
            if err != nil {
                if err == io.EOF {
                    break
                }
                return err
            }
        }

PS 虽然这有助于内存占用,但这无助于 DDOS 攻击复制非常长和/或无限的流......

于 2021-05-04T21:13:42.743 回答
0

假设您正在处理压缩数据,您需要使用io.CopyN.
您可以尝试使用--nocompress标志的解决方法。但这会导致数据未压缩。

请参阅以下 PR 和相关问题:https ://github.com/go-bindata/go-bindata/pull/50

于 2021-04-30T04:21:37.430 回答