![](/img/trans.png)
[英]How to send string compressed with GZIP from Java App to PHP web service
[英]How to protect service from gzip bomb?
我有帶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.Reader
通過返回io.LimitReader()
這是由一種方式io.LimitedReader
)將報告io.EOF
。 這樣可以保護您的服務器免受攻擊,但是可能不是處理它的最佳方法。
既然您提到這是針對其余API的,那么更適合的解決方案將是類似的http.MaxBytesReader()
。 這會將通過的讀取器包裝起來,直到指定的限制為止,如果達到該限制,它將返回錯誤,還將錯誤發送回HTTP客戶端,並關閉基礎的讀取器。 如果http.MaxBytesReader()
的默認行為不適合您,請檢查其源代碼,對其進行復制和修改,這相對簡單。 根據您的需要進行調整。
另請注意,您不應將所有內容(未壓縮的數據)讀入內存。 您可以將“受限閱讀器”傳遞給json.NewDecoder()
,在解碼輸入JSON時,該閱讀器將從給定閱讀器讀取。 當然,如果通過的受限閱讀器報告錯誤,則解碼將失敗。
不要將所有內容讀入內存。 如果可能,在流上進行操作。 在您的示例中,這是100%可能的:
func ReadGzFile(filename string) (io.ReadCloser, error) {
fi, err := os.Open(filename)
if err != nil {
return nil, err
}
return gzip.NewReader(fi)
}
func main() {
b, err := ReadGzFile("test.gzip")
if err != nil {
log.Println(err)
}
defer b.Close()
var dat map[string]interface{}
if err := json.NewDecoder(b).Decode(&dat); err != nil {
panic(err)
}
fmt.Println(dat)
}
這種Decode
方法具有副作用(可能會或可能不會理想),即忽略第一個有效JSON對象之后的流中的任何垃圾。 對於您而言,這似乎是一種好處。 在某些情況下,可能並非如此。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.