gpt4 book ai didi

json - 如何保护服务免受 gzip 炸弹的攻击?

转载 作者:IT王子 更新时间:2023-10-29 01:50:35 30 4
gpt4 key购买 nike

我有带有 json 的 test.gzip 文件

{"events": [
{"uuid":"56c1718c-8eb3-11e9-8157-e4b97a2c93d3",
"timestamp":"2019-06-14 14:47:31 +0000",
"number":732,
"user": {"full_name":"0"*1024*1024*1024}}]}

full_name 文件包含 1GB 的 0,压缩文件大小 ~1Mb

如何在解包时保护我的服务,使我的内存不至于结束?

func ReadGzFile(filename string) ([]byte, error) {
fi, err := os.Open(filename)
if err != nil {
return nil, err
}
defer fi.Close()

fz, err := gzip.NewReader(fi)
if err != nil {
return nil, err
}
defer fz.Close()

s, err := ioutil.ReadAll(fz)
if err != nil {
return nil, err
}
return s, nil
}

func main() {
b, err := ReadGzFile("test.gzip")
if err != nil {
log.Println(err)
}
var dat map[string]interface{}
if err := json.Unmarshal(b, &dat); err != nil {
panic(err)
}
fmt.Println(dat)
}

在这种情况下,输出会被 OOMKiller 杀死我的服务

最佳答案

可能具有欺骗性的是,压缩后的大小可能明显小于允许的大小(您可以或希望处理的大小)。在您的示例中,输入约为 1 MB,而未压缩的大小约为 1 GB。

在读取未压缩 数据时,您应该在达到合理限制后停止。要轻松做到这一点,您可以使用 io.LimitReader()您可以在其中指定要读取的最大字节数。是的,您必须包装解压缩 流,而不是原始压缩流。

这是一个示例:

limited := io.LimitReader(fz, 2*1024*1024)

s, err := ioutil.ReadAll(limited)

以上示例将可读数据限制为 2 MB。当解压缩的数据多于此时会发生什么? io.LimitReader()(顺便说一句 io.LimitedReader)返回的 io.Reader 将报告 io.EOF。这可以保护您的服务器免受攻击,但可能不是处理攻击的最佳方式。

既然你提到这是一个休息 API,一个更合适的解决方案是类似的 http.MaxBytesReader() .这会包装传递的读取器以读取直到给定限制,如果达到限制,它会返回一个错误,并将错误发送回 HTTP 客户端,并关闭底层的读取关闭器。如果http.MaxBytesReader() 的默认行为不适合你,查看它的来源,复制它并修改它,它相对简单。根据您的需要进行调整。

另请注意,您不应将所有内容(未压缩的数据)读入内存。您可以将“有限读者”传递给json.NewDecoder()它将在解码输入 JSON 时从给定的阅读器读取。当然如果通过的limited reader报错,则解码失败。

关于json - 如何保护服务免受 gzip 炸弹的攻击?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56629115/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com