PHP安全-暴力攻擊
暴力攻擊是一種不使用任何特殊手段而去窮盡各種可能性的攻擊方式。它的更正式的叫法是窮舉攻擊——窮舉各種可能性的攻擊。
對(duì)于訪問控制,典型的暴力攻擊表現(xiàn)為攻擊者通過大量的嘗試去試圖登錄系統(tǒng)。在多數(shù)情況下,用戶名是已知的,而只需要猜測(cè)密碼。
盡管暴力攻擊沒有技巧性可言,但詞典攻擊似乎有一定的技巧性。最大的區(qū)別是在進(jìn)行猜測(cè)時(shí)的智能化。詞典攻擊只會(huì)最可能的情況列表中進(jìn)行窮舉,而不像暴力攻擊一樣去窮舉所有的可能情況。
防止進(jìn)行驗(yàn)證嘗試或限制允許錯(cuò)誤的次數(shù)還算是一個(gè)比較有效的安全手段,但是這樣做的兩難之處在于如何在不影響合法用戶使用的情況下識(shí)別與阻止攻擊者。
在這種情況下,對(duì)一致性的判定可以幫助你區(qū)分二者。這個(gè)方法與第四章中所述的防止會(huì)話劫持的做法很相似,但區(qū)別是你要確定的是一個(gè)攻擊者而不是一個(gè)合法用戶。
考慮下面的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>
攻擊者會(huì)察看這個(gè)表單并建立一段腳本來POST合法的數(shù)據(jù)給http://example.org/login.php:
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.1rn';
$http_request .= 'Host: example.orgrn';
$http_request .= 'Content-Type: application/x-www-form-urlencodedrn';
$http_request .= 'Content-Length: $content_lengthrn';
$http_request .= 'Connection: closern';
$http_request .= 'rn';
$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 */
}
?>
使這段腳本,攻擊者還可以簡(jiǎn)單地加入一個(gè)循環(huán)來繼續(xù)嘗試不同的密碼,并在每次嘗試后檢查$http_response變量。一旦$http_response變量有變化,就可以認(rèn)為猜測(cè)到了正確的密碼。
你可以通過很多安全措施去防止此類攻擊。我們注意到,在暴力攻擊中每次的HTTP請(qǐng)求除了密碼是不同的,其他部分完全相同,這一點(diǎn)是很有價(jià)值的。
盡管在超過一定數(shù)量的失敗嘗試后臨時(shí)凍結(jié)帳號(hào)是一種有效的防范手段,但你可能會(huì)去考慮采用更確定的方式去凍結(jié)帳號(hào),以使攻擊者更少地影響合法用戶對(duì)你的應(yīng)用的正常使用。
還有一些流程也可以增大暴力攻擊的難度,使它不太可能成功。一個(gè)簡(jiǎn)單的遏制機(jī)制就能有效地做到這一點(diǎn):
CODE:
<?php
/* mysql_connect() */
/* mysql_select_db() */
$clean = array();
$mysql = array();
$now = time();
$max = $now - 15;
$salt = ’SHIFLETT’;
if (ctype_alnum($_POST[’username’]))
{
$clean[’username’] = $_POST[’username’];
}
else
{
/* ... */
}
$clean[’password’] = md5($salt . md5($_POST[’password’] . $salt));
$mysql[’username’] = mysql_real_escape_string($clean[’username’]);
$sql = 'SELECT last_failure, password
FROM users
WHERE username = ’{$mysql[’username’]}’';
if ($result = mysql_query($sql))
{
if (mysql_num_rows($result))
{
$record = mysql_fetch_assoc($result);
if ($record[’last_failure’]> $max)
{
/* Less than 15 seconds since last failure */
}
elseif ($record[’password’] == $clean[’password’])
{
/* Successful Login */
}
else
{
/* Failed Login */
$sql = 'UPDATE users
SET last_failure = ’$now’
WHERE username = ’{$mysql[’username’]}’';
mysql_query($sql);
}
}
else
{
/* Invalid Username */
}
}
else
{
/* Error */
}
?>
上例會(huì)限制在上次驗(yàn)證失敗后對(duì)同一用戶再試嘗試的頻率。如果在一次嘗試失敗后的15秒內(nèi)再次嘗試,不管密碼是否正確,驗(yàn)證都會(huì)失敗。這就是這個(gè)方案的關(guān)鍵點(diǎn)。但簡(jiǎn)單地在一次失敗嘗試后15秒內(nèi)阻止訪問還是不夠的——在此時(shí)不管輸入是什么,輸出也會(huì)是一致的,只有在登錄成功后才會(huì)不同。否則,攻擊者只要簡(jiǎn)單地檢查不一致的輸出即可確定登錄是否成功。
相關(guān)文章:
1. Python調(diào)用接口合并Excel表代碼實(shí)例2. ASP.NET MVC實(shí)現(xiàn)橫向展示購(gòu)物車3. ASP.Net Core(C#)創(chuàng)建Web站點(diǎn)的實(shí)現(xiàn)4. ASP.Net Core對(duì)USB攝像頭進(jìn)行截圖5. 通過CSS數(shù)學(xué)函數(shù)實(shí)現(xiàn)動(dòng)畫特效6. 一文透徹詳解.NET框架類型系統(tǒng)設(shè)計(jì)要點(diǎn)7. ASP.NET MVC使用Boostrap實(shí)現(xiàn)產(chǎn)品展示、查詢、排序、分頁(yè)8. ajax動(dòng)態(tài)加載json數(shù)據(jù)并詳細(xì)解析9. Python快速將ppt制作成配音視頻課件的操作方法10. .net如何優(yōu)雅的使用EFCore實(shí)例詳解
