亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何保護服務免受 gzip 的侵害?

如何保護服務免受 gzip 的侵害?

Go
慕娘9325324 2023-06-26 16:37:38
我有test.gzipjson 文件{"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 終止我的服務
查看完整描述

2 回答

?
GCT1015

TA貢獻1827條經驗 獲得超4個贊

可能具有欺騙性的是,壓縮后的大小可能明顯小于允許的大小(您可以或您希望處理的大?。?。在您的示例中,輸入約為 1 MB,而未壓縮的大小約為 1 GB。

在讀取未壓縮的數據時,您應該在達到合理的限制后停止。為了輕松做到這一點,您可以使用io.LimitReader()可以指定要讀取的最大字節數的位置。是的,您必須包裝解壓縮的流,而不是原始的壓縮流。

這是一個示例:

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

s,?err?:=?ioutil.ReadAll(limited)

上面的示例將可讀數據限制為 2 MB。當解壓后的數據超過這個數時會發生什么?返回io.Readerio.LimitReader()(順便說一句io.LimitedReader)將報告io.EOF。這可以保護您的服務器免受攻擊,但可能不是處理攻擊的最佳方法。

由于您提到這是針對 REST API 的,因此更適合的解決方案是類似的http.MaxBytesReader().?這會包裝傳遞的讀取器以讀取直到給定的限制,如果達到了限制,它將返回一個錯誤,并將錯誤發送回 HTTP 客戶端,并關閉底層的讀取關閉器。如果默認行為http.MaxBytesReader()不適合你,檢查它的來源,復制它并修改它,相對簡單。根據您的需要進行調整。

另請注意,您不應將所有內容(未壓縮的數據)讀入內存。您可以傳遞“有限讀取器”,json.NewDecoder()在解碼輸入 JSON 時將從給定讀取器讀取數據。當然如果通過的受限閱讀器報錯,解碼就會失敗。


查看完整回答
反對 回復 2023-06-26
?
紅顏莎娜

TA貢獻1842條經驗 獲得超13個贊

不要將所有內容讀入內存。如果可能的話,對流進行操作。在您的示例中這是 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 對象之后流中的任何垃圾的副作用(可能需要也可能不需要)。就您而言,這似乎是一個好處。在某些情況下,可能并非如此。


查看完整回答
反對 回復 2023-06-26
  • 2 回答
  • 0 關注
  • 165 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號