2014-04-30 43 views
3

我目前正在編寫客戶端/服務器應用程序,使用Google協議緩衝區對基礎消息進行編碼。由於它是一個.NET程序,我正在使用protobuf-net庫:它快速,便攜且經過深思熟慮。防止來自惡意protobuf數據包的DoS攻擊

但是,我有點擔心潛在的DoS攻擊。服務器應用程序將直接面向互聯網,底層協議將被公開記錄。攻擊者可以很容易地製作一個數據包來耗盡內存。

一個簡單的例子:

鑑於以下原定義:

[ProtoContract] 
class Foo { 
    [ProtoMember(1)] 
    public string Bar { get; set; } 
} 

下面的代碼將嘗試分配一個2GB緩衝器爲Bar字符串:

byte[] bytes = { 0x0A, 0xFF, 0xFF, 0xFF, 0xFF, 0x07 }; 
Serializer.Deserialize<Foo>(new MemoryStream(bytes)); 

快來導致一個OutOfMemoryException。當然,這裏並不重要:運行時將無法分配它(至少在32位進程中)。現在製作多個數據包,每個數據包分配幾百MB的內存,並且由於內存不足而導致正常操作失敗。當然,如果攻擊者在字符串長度後沒有發送任何內容,內存將被GC快速回收,但它仍然很容易增加內存壓力。

我知道這個問題並不是特定於protobuf-net的:任何使用長度前綴數據的協議都可能會遇到同樣的問題。通常,它們使用任意配額來解決。但是,我沒有找到任何方法在protobuf-net中指定它們。例如,我想指定一個字符串不能超過N個字符,給定列表不能包含更多M元素等。

是否有任何簡單的解決方案可以防止我錯過的這個問題(而不是做我自己的實現或分叉)?

+0

我不知道是否有更好的方法,AFAIK肯定可以完成,如果你放棄_normal_解析,並且你用_reflection_(至少和早期驗證一樣):'reflection-> FieldSize(foo,描述符 - > FindFieldByName(「Bar」))<= 1024)'。 (對不起,這是C++的語法,我從來沒有使用.NET版本,但我想它非常相似)。 –

+0

我相信我們可以添加配額支持,如果它是一個需求...簡單地說:它還沒有。 –

+0

@Adriano:我不確定protobuf-net是否支持這個解析。 –

回答

0

我目前看到的唯一兩個選項就是潛入Protobuf-Nets代碼庫並找到它解析二進制數據的位置。如果你打算使用協議緩衝區,這並不是一個壞主意。

或者你可以爲靜態設置長度的字符串/列表/數組創建你自己的類,這樣你就不會在互聯網上發送長度前綴,這種類型會破壞使用高效系統的目的,比如Protobuf和混亂你的架構。