2008-09-04 337 views
16

這與another question I asked相關。總之,我有一個URL的特例,當一個表單發佈給它時,我不能依靠Cookie來進行身份驗證或維護用戶的會話,但我需要知道他們是誰,而且我需要知道他們已經登錄!如何防止重播攻擊?

我想我想出了一個解決我的問題,但它需要充實。這就是我的想法。我創建了一個名爲「username」的隱藏表單域,並在其中放置用戶的用戶名,加密。然後,當表單POST時,即使我沒有收到來自瀏覽器的任何cookies,我知道他們已經登錄,因爲我可以解密隱藏的表單字段並獲取用戶名。

我能看到的主要安全漏洞是重播攻擊。如何阻止某人獲取該加密字符串,並以該用戶的身份進行發佈?我知道我可以使用SSL來竊取該字符串,也許我可以定期旋轉加密密鑰,以限制字符串適合的時間長度,但我真的很想找到防彈解。任何人有任何想法? ASP.Net ViewState是否阻止重放?如果是這樣,他們是如何做到的?

編輯:我希望有一個解決方案,不需要存儲在數據庫中的任何東西。應用程序狀態是可以的,除非它不能在IIS重新啓動或在Web場或花園場景中工作。現在我接受克里斯的回答,因爲我不相信甚至可以在沒有數據庫的情況下保證這一點。但如果有人想出一個不涉及數據庫的答案,我會接受它!

回答

13

如果哈希與用戶名和密碼的時間標記,你可以關閉的重放攻擊窗口幾秒鐘之內。我不知道這是否符合您的需求,但至少是部分解決方案。

+0

我問這個問題後,我實際上決定做這件事。偉大的思想家都認爲一樣:) – 2008-09-21 02:55:54

+0

請注意,如果時間戳/ cookie未加密或者在用戶代理層可以進行欺騙,那麼這對黑客只會操縱時間戳值無效。 – 2014-07-21 18:37:04

4

您可以使用某種與用戶名一起使用的隨機挑戰字符串來創建散列。如果您將挑戰字符串存儲在服務器上的數據庫中,那麼您可以確保它僅使用一次,並且僅限於一個特定用戶。

0

如果您只接受一次每個密鑰(例如,將密鑰設爲GUID,然後檢查它何時返回),則會阻止重放。當然,如果攻擊者回應第一個,那麼你有一個新問題...

0

這是WebForms還是MVC?如果是MVC,則可以使用AntiForgery令牌。這看起來與您提到的方法類似,只是它基本上使用了一個GUID並使用該帖子的guid值設置了一個cookie。有關更多信息,請參閱Steve Sanderson的博客:http://blog.codeville.net/2008/09/01/prevent-cross-site-request-forgery-csrf-using-aspnet-mvcs-antiforgerytoken-helper/

另一件事,您是否考慮在回發中檢查引用鏈接?這不是防彈的,但可能有幫助。

+0

該問題指出,他不能依靠cookie進行身份驗證。 MVC Anti-Forgery令牌實際上依賴於cookie,因此這不太可能適用於問題的場景。此外,我們應該小心「重播攻擊」的含義 - 防僞令牌旨在防止CSRF攻擊。重播攻擊可能以各種方式出現 - 包括來自初始用戶的攻擊 - 在這種情況下,防僞標記將毫無用處。 – Nathan 2009-05-06 22:18:32

1

你可以使用內存或數據庫來維護關於用戶或請求的任何信息嗎?

如果是這樣,那麼在請求表單時,我會包含一個隱藏表單域,其內容是一個隨機生成的數字。請求呈現時,將此令牌保存到應用程序上下文或某種存儲(數據庫,平面文件等)中。提交表單時,檢查應用程序上下文或數據庫以查看該隨機生成的數字是否仍然有效(但是,您定義的有效 - 也許它可能會在X分鐘後過期)。如果是這樣,請從「允許令牌」列表中刪除此令牌。

因此,任何重播的請求都會包含此服務器上不再認爲有效的相同令牌。

1

我對網絡編程的某些方面很陌生,但前幾天我正在閱讀。我相信你需要使用Nonce

13

如果你真的不想存儲任何狀態,我認爲你可以做的最好的事情是通過使用時間戳和短的到期時間來限制重放攻擊。例如,服務器發送:

{TS,U,HMAC({TS,U},KS)}

Ts是時間戳,U是用戶名,和KS是服務器的密鑰。用戶將其發送回服務器,服務器通過在提供的值上重新計算HMAC來驗證它。如果它是有效的,你知道它何時發佈,並且如果它比5分鐘更早,可以選擇忽略它。

一個很好的資源,這種類型的開發The Do's and Don'ts of Client Authentication on the Web

2

在我的一個停止「重放」攻擊的應用程序中,我已將IP信息插入到會話對象中。每次我在代碼中訪問會話對象時,都要確保通過Request.UserHostAddress,然後比較以確保IP匹配。如果他們不這樣做,那麼顯然有人提出這個請求,所以我返回null。這不是最好的解決方案,但它至少是阻止重播攻擊的另一個障礙。

1

(重放攻擊可以很容易地將所有關於IP/MAC欺騙,再加上你所遇到的挑戰在動態IP)

它不僅是重播你是這裏後,在隔離是沒有意義的。只需使用SSL,並避免手工製作任何東西..

ASP.Net ViewState是一團糟,避免它。儘管PKI重量級和臃腫,但至少它沒有發明自己的安全「方案」。所以如果可能的話,我會使用它,並始終爲相互認證。僅服務器驗證是無用的。

1

ViewState包含安全功能。有關ASP.NET中的某些內置安全功能,請參閱this article。它在服務器上的machine.config中對服務器machineKey進行驗證,確保每個回發都是有效的。

Further down in the article,您還會看到,如果要將值存儲在您自己的隱藏字段中,則可以使用LosFormatter類以與ViewState用於加密的相同方式對值進行編碼。

private string EncodeText(string text) { 
    StringWriter writer = new StringWriter(); 
    LosFormatter formatter = new LosFormatter(); 
    formatter.Serialize(writer, text); 
    return writer.ToString(); 
} 
11

這裏有幾個很好的答案,並把它們放在一起就是答案最終在於:

  1. 塊密碼加密(使用AES-256 +)和哈希(與SHA-2 +)發送給客戶端的所有狀態/隨機數相關信息。否則黑客只是操縱數據,查看它來學習模式並規避其他一切。記住......它只需要一個開放的窗口。

  2. 生成一次性隨機且唯一的隨機數,每個請求通過POST請求發回。這樣做有兩件事:它確保POST響應與THAT請求一致。它還允許跟蹤一組get/POST對的一次性使用(防止重播)。

  3. 使用時間戳使臨時池可管理。將時間戳存儲在上面#1的加密cookie中。拋出比應用程序的最大響應時間或會話更早的任何請求(例如,一個小時)。

  4. 將請求的機器的「合理唯一」的數字指紋與加密的時間戳數據一起存儲。這將防止攻擊者竊取客戶端cookie執行會話劫持的另一個竅門。這將確保該請求不僅會返回一次,而且會從機器返回(或者距離足夠近以使攻擊者幾乎不可能複製)。

有ASPNET和基於Java/J2EE安全過濾器的應用程序可以完成上述所有的零編碼。對於大型系統(如股票交易公司,銀行或大批量安全站點)來說,管理隨機池並不是一項微不足道的工作,只要性能至關重要。建議看看這些產品,而不是爲每個Web應用程序編寫這個程序。

0

使用https ...它具有內置的重播保護。