简体   繁体   English

G110:减压炸弹的潜在 DoS 漏洞 (gosec)

[英]G110: Potential DoS vulnerability via decompression bomb (gosec)

I'm getting the following golintci message:我收到以下golintci消息:

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

Read the corresponding CWE and I'm not clear on how this is expected to be corrected.阅读相应的CWE ,我不清楚如何纠正这一点。

Please offer pointers.请指点。

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
}

The warning you get comes from a rule provided in gosec .您收到的警告来自gosec中提供的规则。

The rule specifically detects usage of io.Copy on file decompression.该规则专门检测文件解压缩时io.Copy的使用情况。

This is a potential issue because io.Copy :这是一个潜在问题,因为io.Copy

copies from src to dst until either EOF is reached on src or an error occurs.src复制到dst直到在src上达到 EOF 或发生错误。

So, a malicious payload might cause your program to decompress an unexpectedly big amount of data and go out of memory, causing denial of service as mentioned in the warning message.因此,恶意负载可能会导致您的程序从 memory 中解压出意外的大量数据和 go,从而导致警告消息中提到的拒绝服务。

In particular, gosec will check ( source ) the AST of your program and warn you about usage of io.Copy or io.CopyBuffer together with any one of the following:特别是,gosec 将检查( source )您的程序的 AST 并警告您使用io.Copyio.CopyBuffer以及以下任何一项:

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

Using io.CopyN removes the warning because (quote) it " copies n bytes (or until an error) from src to dst ", thus giving you (the program writer) control of how many bytes to copy.使用io.CopyN删除警告,因为(引用)它“将n 个字节(或直到出现错误)从 src 复制到 dst ”,从而让您(程序编写者)控制要复制的字节数。 So you could pass an arbitrarily large n that you set based on the available resources of your application, or copy in chunks .因此,您可以根据应用程序的可用资源设置任意大的n ,或者复制 chunks

Based on various pointers provided, replaced基于提供的各种指针,替换

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

with

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

PS while this helps memory footprint, this wouldn't help a DDOS attack copying very long and/or infinite stream... PS 虽然这有助于 memory 占用空间,但这无助于 DDOS 攻击复制非常长和/或无限的 stream ...

Assuming that you're working on compressed data, you need to use io.CopyN .假设您正在处理压缩数据,则需要使用io.CopyN
You can try a workaround with --nocompress flag.您可以尝试使用--nocompress标志的解决方法。 But this will cause the data to be included uncompressed.但这会导致数据未压缩。

See the following PR and related issue: https://github.com/go-bindata/go-bindata/pull/50请参阅以下 PR 和相关问题: https://github.com/go-bindata/go-bindata/pull/50

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM