2009-09-13 52 views
3

我有一個Web應用程序,它具有基本身份驗證 - 用戶名,密碼,會話和內容。不過,我特別需要防止用戶欺騙POST請求(即使是登錄用戶)。在我的應用程序中,我正在驗證用戶的會話,然後才接受POST數據(還要照顧XSS和其他東西)。在web應用程序中保護POST數據

像:

if(user session exists) 
{ 
    // handle the data POSTed 
} 

else { 
    // ... 
} 

我在數據庫中存儲會話標識。還有什麼我應該注意防止虛假的POST請求,或者這是足夠的嗎?

回答

2

您可以嘗試爲每個帖子請求生成帖子密鑰。顯示發佈請求有效且從頁面上的表單執行的附加參數排序。

1

如果您正在用戶的瀏覽器中使用Javascript構建有效的POST請求,那麼可以避免確定的用戶向您的服務器提交僞造POST郵件。該用戶有一個有效的會話ID,可用於發出POST請求。他還可以訪問代碼有權訪問的所有代碼和所有其他數據以構建請求。

您不能依靠瀏覽器端代碼來保護您的系統。安全性必須在服務器上執行。例如,對象的所有操作都應該進行身份驗證和授權。

+0

+1表示「安全性必須在服務器上執行」。這不能說得太多。 – 2009-09-13 13:39:52

0

在我目前的應用程序中,我有一些代碼被髮送到瀏覽器,瀏覽器然後回發,並且不能修改它。我所做的就是向該值追加一個祕密字符串,獲取該完整字符串的SHA1校驗和,然後要求瀏覽器返回值和校驗和。我很確定這也是.NET的視圖狀態。

0

如果用戶會話很長,您仍然易受XSRF的影響。你也需要採取措施。

如果你是在.NET中,檢查出AntiForgeryToken,

http://msdn.microsoft.com/en-us/library/dd492767.aspx

+0

反篡改令牌僅僅意味着該頁面是從先前的GET發佈的,這限制了基本的欺詐性POST。各種屏幕錄像機都可以錄製/播放這些頁面。 – bryanbcook 2009-09-16 13:35:57

0

在接受用戶輸入,則需要在數據庫中存儲以前的事情要做,零級的事情是確保你通過mysql_real_escape_string($ MyPostData)函數運行數據。

另外,它對每個想要通過POST接受的變量/數據都有好處,可以根據其類型以及您打算如何使用它進行編程驗證。

這些是確保用戶沒有「有趣」業務的兩條主要規則:確保您使用有效變量並確保數據到達數據庫得到驗證並正確轉義。

1

使用CAPTCHA圖像。

該網站建立在REST上,它根據定義是從一個點向另一個點轉移狀態。有足夠時間的人可以製作模擬活動會話的POST請求。

與所有安全請求一樣,CAPTCHA在服務器端得到驗證。

0

對於您的模型(尤其是如果您使用整數作爲會話ID),攻擊者可以很容易地代表其他用戶提交請求。遞減你自己的會話ID,並且你已經有其他人提供了這個會話ID存在)。 您需要具有與每個會話ID關聯的唯一會話密鑰/ guid,並將其存儲在數據庫和客戶端中的Cookie中。每次您的客戶端提交請求時,您都應該讀取會話ID以及會話GUID,然後根據數據庫值驗證它們。 除此之外,您可能還需要考慮一些XSRF緩解策略。

3

我特別接受POST

前驗證用戶的會話。如果你的意思是「會話」通常意味着:存儲在識別用戶的cookie中的持久令牌和相關聯的會話數據,那麼不,這還不夠。即使POST請求被另一個(攻擊者)站點激發,該cookie也會被瀏覽器自動發送。

您在這裏尋找的關鍵字是跨站點請求僞造或XSRF,其中經過身份驗證的用戶可以由攻擊者(通過腳本或其他方法)向您的站點發出GET或POST請求。這些請求通常不會與合法請求區分開來。 (有些人通過檢查HTTP引用數據嘗試這樣做,但這是不可靠的。)

這些攻擊不像服務器端(SQL,命令)或客戶端(HTML,JavaScript)那樣立即造成損害,注射,但它們比兩者更普遍:不幸的是,很少有網絡程序員都採用適當的對策。直到他們的網站被XSRF漏洞攻陷。

有多種方法可以抵禦XSRF,但唯一真正有效的方法是在每個提交表單中包含第三方攻擊者不會知道的祕密值。正如Eimantas所提到的,這通常被稱爲郵政鑰匙。

有多種方式可以產生這樣的祕密信息。一種簡單的方法是爲每個用戶的帳戶詳細信息添加一個隨機生成的代碼,然後將其放在表單的隱藏字段中,並檢查其在提交中的存在。例如在PHP中:

<form method="post" action="delete.php"><div> 
    <input type="hidden" name="key" value="<?php echo(htmlspecialchars($user['key'])); ?>"/> 
    <input type="submit" value="Delete" /> 
</div></form> 

if ($_POST['key']!=$user['key']) 
    // error 

攻擊者不會知道該用戶的密鑰,因此無法創建包含該密鑰的鏈接/表單。

您也可以在服務器密鑰上對用戶的ID使用加密哈希函數,而不是保留單獨的代碼。使用散列,您還可以投入其他內容,例如到期時間,以便表單必須在特定時間範圍內提交。或者,您可以生成一次性交易密鑰,您也可以使用它來確保無法兩次提交相同的表單(用於停止重複發佈)。