暴力攻擊是一種不使用任何特殊手段而去窮盡各種可能性的攻擊方式。它的更正式的叫法是窮舉攻擊——窮舉各種可能性的攻擊。
對於存取控制,典型的暴力攻擊表現為攻擊者透過大量的嘗試去試圖登入系統。在多數情況下,使用者名稱是已知的,只需要猜測密碼。
儘管暴力攻擊沒有技巧性可言,但字典攻擊似乎有一定的技巧性。最大的差別是在進行猜測時的智能化。字典攻擊只會在最可能的情況列表中進行窮舉,而不是像暴力攻擊一樣去窮舉所有的可能情況。
防止進行驗證嘗試或限制允許錯誤的次數還算是一個比較有效的安全手段,但是這樣做的兩難之處在於如何在不影響合法用戶使用的情況下識別與阻止攻擊者。
在這種情況下,一致性的判定可以幫助你區分二者。這個方法與第四章所述的防止會話劫持的做法很相似,但差異是你要確定的是一個攻擊者而不是一個合法使用者。
考慮下面的HTML表單:
CODE: <form action="http://example.org/login.php" method="POST"> <p>Username: <input type="text" name="username" /></p> <p>Password: <input type="password" name="password" /></p> <p><input type="submit" /></p> </form>
攻擊者會察看這個表單並建立一段腳本來POST
攻擊者會檢查這個表單並建立一段腳本來POST
使這段腳本,攻擊者還可以簡單地加入一個循環來繼續嘗試不同的密碼,並在每次嘗試後檢查$http_response變數。一旦$http_response變數有變化,就可以認為猜測到了正確的密碼。
你可以透過很多安全措施去防止此類攻擊。我們注意到,在暴力攻擊中每次的HTTP請求除了密碼是不同的,其他部分完全相同,這一點是很有價值的。
儘管在超過一定數量的失敗嘗試後臨時凍結帳號是一種有效的防範手段,但你可能會去考慮採用更確定的方式去凍結帳號,以使攻擊者更少地影響合法用戶對你的應用的正常使用。
還有一些流程也可以增加暴力攻擊的難度,使它不太可能成功。一個簡單的遏制機制就能有效地做到這一點:
CODE: <?php $username = 'victim'; $password = 'guess'; $content = "username=$username&password=$password"; $content_length = strlen($content); $http_request = ''; $http_response = ''; $http_request .= "POST /login.php HTTP/1.1\r\n"; $http_request .= "Host: example.org\r\n"; $http_request .= "Content-Type: application/x-www-form-urlencoded\r\n"; $http_request .= "Content-Length: $content_length\r\n"; $http_request .= "Connection: close\r\n"; $http_request .= "\r\n"; $http_request .= $content; if ($handle = fsockopen('example.org', 80)) { fputs($handle, $http_request); while (!feof($handle)) { $http_response .= fgets($handle, 1024); } fclose($handle); /* Check Response */ } else { /* Error */ } ?>
上例會限制在上次驗證失敗後對同一用戶再試嘗試的頻率。如果在一次嘗試失敗後的15秒內再嘗試,不管密碼是否正確,驗證都會失敗。這就是這個方案的關鍵點。但簡單地在一次失敗嘗試後15秒內阻止存取還是不夠的——在此時不管輸入是什麼,輸出也會是一致的,只有在登入成功後才會不同。否則,攻擊者只要簡單地檢查不一致的輸出即可確定登入是否成功。
以上就是PHP安全-暴力攻擊的內容,更多相關內容請關注PHP中文網(www.php.cn)!