DVWA靶機-暴力破解
1.DVWA靶機的4個安全等級
DVWA Security分爲四個等級,low,medium,high,impossible,不同的安全等級對應了不同的漏洞等級。
1.low-最低安全等級,無任何安全措施,通過簡單毫無安全性的編碼展示了安全漏洞。
2.medium-中等安全等級,有安全措施的保護,但是安全性並不強。
3.high-高等安全等級,有安全措施保護,是中等安全等級的加深,這個等級下的安全漏洞可能不允許相同程度的攻擊。
4.impossible-最高(不可能)安全等級,存在相當強的安全保護措施,這個級別應能防止所有的漏洞,主要用於比較不同等級下的源代碼。
2.暴力破解(Brute Force)
暴力破解也稱爲窮舉法,是指未知用戶名和密碼的情況下,通過某些破解軟件+破解詞典(用戶可能設置的用戶名及密碼文件),來爆破出正確的用戶名及密碼,此過程技術成分低,其耗費時間多,成功機率小。
適用場景:適用於無驗證碼或者二次驗證登錄的WEB頁面
(1).DVWA-LOW等級下的暴力破解
首先我們在此處用的暴力破解工具爲Burp suite,此工具可以在截取WEB頁面POST提交的信息後,可以通過修改用戶名密碼方式來測試WEB頁面是否正確回顯,也就是修改之後的用戶名密碼是否正確
由於暴力破解及其耗費時間,此時爲了方便,我們在自定義詞典,在詞典中加入已知的用戶名,密碼,爲了更快速的查到結果。
username:admin
password:123
Low Brute Force Source
<?php
if( isset( $_GET[ 'Login' ] ) ) {
// Get username
$user = $_GET[ 'username' ];
// Get password
$pass = $_GET[ 'password' ];
$pass = md5( $pass );
// Check the database
$query = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
$result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );
if( $result && mysql_num_rows( $result ) == 1 ) {
// Get users details
$avatar = mysql_result( $result, 0, "avatar" );
// Login successful
echo "<p>Welcome to the password protected area {$user}</p>";
echo "<img src=\"{$avatar}\" />";
}
else {
// Login failed
echo "<pre><br />Username and/or password incorrect.</pre>";
}
mysql_close();
}
?>
1.截取HTTP報文
2.轉入Intruder-positions
Intruder默認針對於所有的變量,我們先將其原策略清除(clear),重新添加(Add)單選項針對於password,
攻擊類型(Attack type)選爲sniper
3.轉入Intruder-Payloads
Payload Sets:
Payload set:設置破解頁,當前只針對於密碼,爲1
Payload type 設置爲Simple list,單表模式
Payload Options[Simple list]
load:通過load可以載入常用用戶名及密碼詞典,文件形式
Add:添加單獨可能存在的密碼
常用的用戶名密碼詞典在網上都能下載,此處爲了方便,快速的達成效果,我們Add中添加已知的密碼
4.Start Attack
定義好詞典後,開始攻擊,我們可以發現當出現正確的密碼時回覆中,Length有不同的結果,此時正確的長度爲5317,這就是判斷密碼是否正確的方法,同時可以在Response Render中查看web頁面的回顯效果。
(2).DVWA-Medium等級下的暴力破解
同low等級下的暴力破解類似,爲了方便,我們在自定義詞典,在詞典中加入已知的用戶名,密碼,爲了更快速的查到結果。
username:admin
password:123
由於low等級下,不存在安全策略,無安全行可言,但是Medium等級下存在安全策略,爲了方便快速,我們此時可以先查看源碼再進行破解。
mysql_real_escape_string():此函數轉義了SQL語句中使用的字符串的特殊字符
也就是過濾了一些特殊字符,包括(\x00、\n、\r 、\、 '、 "、 \x1a),也意味着用戶名和密碼中不能存在這些特殊字符。
Medium Brute Force Source
<?php
if( isset( $_GET[ 'Login' ] ) ) {
// Sanitise username input
$user = $_GET[ 'username' ];
$user = mysql_real_escape_string( $user );
// Sanitise password input
$pass = $_GET[ 'password' ];
$pass = mysql_real_escape_string( $pass );
$pass = md5( $pass );
// Check the database
$query = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
$result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );
if( $result && mysql_num_rows( $result ) == 1 ) {
// Get users details
$avatar = mysql_result( $result, 0, "avatar" );
// Login successful
echo "<p>Welcome to the password protected area {$user}</p>";
echo "<img src=\"{$avatar}\" />";
}
else {
// Login failed
sleep( 2 );
echo "<pre><br />Username and/or password incorrect.</pre>";
}
mysql_close();
}
?>
1.截取HTTP報文
2.轉入Intruder-positions
Intruder默認針對於所有的變量,我們先將其原策略清除(clear),重新添加(Add)單選項針對於username&password,
攻擊類型(Attack type)選爲Cluster bomb
3.轉入Intruder-Payloads
Payload Sets:
Payload set:設置破解頁,當前於用戶名和密碼,爲2
Payload type 設置爲Simple list,單表模式
Payload Options[Simple list]
load:通過load可以載入常用用戶名及密碼詞典,文件形式
Add:添加單獨可能存在的用戶名及密碼
常用的用戶名密碼詞典在網上都能下載,此處爲了方便,快速的達成效果,我們Add中添加已知的用戶名及密碼
用戶名:
密碼:
4.Start Attack
定義好詞典後,開始攻擊,我們可以發現當出現正確的用戶名和密碼時回覆中,Length有不同的結果,此時正確的長度爲5326,這就是判斷密碼是否正確的方法,同時可以在Response Render中查看web頁面的回顯效果。
此時我定義了6個用戶名,7個密碼,其共有42中結果,這個過程花費大概1min,可想而知,如果用成千上萬個用戶名和密碼來測試,那需要的時間就相當的長,此時暴力破解的缺點也就顯露出來。
(3).DVWA-high等級下的暴力破解
在high等級中,存在更加強的安全策略
1.token機制(基於token的身份驗證)
2.stripslashes()函數,過濾字符串中的反斜槓’’,也就是說用戶名中和密碼不能存在
3.mysql_real_escape_string(),同medium等級一樣,過濾了一些特殊字符,包括(\x00、\n、\r 、\、 '、 "、 \x1a),也意味着用戶名和密碼中不能存在這些特殊字符。
由於token值,每次都是隨機的,客戶端和服務端都爲隨機值,無法使用burp suite進行暴力破解,但是可以通過python腳本,自動獲取token,後期會發布python相關腳本文件的暴力破解過程。
High Brute Force Source
<?php
if( isset( $_GET[ 'Login' ] ) ) {
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// Sanitise username input
$user = $_GET[ 'username' ];
$user = stripslashes( $user );
$user = mysql_real_escape_string( $user );
// Sanitise password input
$pass = $_GET[ 'password' ];
$pass = stripslashes( $pass );
$pass = mysql_real_escape_string( $pass );
$pass = md5( $pass );
// Check database
$query = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
$result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );
if( $result && mysql_num_rows( $result ) == 1 ) {
// Get users details
$avatar = mysql_result( $result, 0, "avatar" );
// Login successful
echo "<p>Welcome to the password protected area {$user}</p>";
echo "<img src=\"{$avatar}\" />";
}
else {
// Login failed
sleep( rand( 0, 3 ) );
echo "<pre><br />Username and/or password incorrect.</pre>";
}
mysql_close();
}
// Generate Anti-CSRF token
generateSessionToken();
?>
(4).impossiable
Impossible Brute Force Source
impossible等級的安全策略相當強大,應能防止所有的漏洞,用於比較不同等級下的源代碼。
相比於high等級,impossible等級,加上了登錄失敗策略,定義了3個變量
total_failed_login:總的登錄失敗次數,當前定義爲3次。
lockout_time:賬戶鎖定時間,當前定義爲15s
account_locked:創建用戶的時候鎖定用戶
bindparam:爲用戶名和密碼綁定參數PDOStatement::bindParam
時間函數:
last_login、timeout、timenow等組成了相當大的防禦體系
<?php
if( isset( $_POST[ 'Login' ] ) ) {
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// Sanitise username input
$user = $_POST[ 'username' ];
$user = stripslashes( $user );
$user = mysql_real_escape_string( $user );
// Sanitise password input
$pass = $_POST[ 'password' ];
$pass = stripslashes( $pass );
$pass = mysql_real_escape_string( $pass );
$pass = md5( $pass );
// Default values
$total_failed_login = 3;
$lockout_time = 15;
$account_locked = false;
// Check the database (Check user information)
$data = $db->prepare( 'SELECT failed_login, last_login FROM users WHERE user = (:user) LIMIT 1;' );
$data->bindParam( ':user', $user, PDO::PARAM_STR );
$data->execute();
$row = $data->fetch();
// Check to see if the user has been locked out.
if( ( $data->rowCount() == 1 ) && ( $row[ 'failed_login' ] >= $total_failed_login ) ) {
// User locked out. Note, using this method would allow for user enumeration!
//echo "<pre><br />This account has been locked due to too many incorrect logins.</pre>";
// Calculate when the user would be allowed to login again
$last_login = $row[ 'last_login' ];
$last_login = strtotime( $last_login );
$timeout = strtotime( "{$last_login} +{$lockout_time} minutes" );
$timenow = strtotime( "now" );
// Check to see if enough time has passed, if it hasn't locked the account
if( $timenow > $timeout )
$account_locked = true;
}
// Check the database (if username matches the password)
$data = $db->prepare( 'SELECT * FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' );
$data->bindParam( ':user', $user, PDO::PARAM_STR);
$data->bindParam( ':password', $pass, PDO::PARAM_STR );
$data->execute();
$row = $data->fetch();
// If its a valid login...
if( ( $data->rowCount() == 1 ) && ( $account_locked == false ) ) {
// Get users details
$avatar = $row[ 'avatar' ];
$failed_login = $row[ 'failed_login' ];
$last_login = $row[ 'last_login' ];
// Login successful
echo "<p>Welcome to the password protected area <em>{$user}</em></p>";
echo "<img src=\"{$avatar}\" />";
// Had the account been locked out since last login?
if( $failed_login >= $total_failed_login ) {
echo "<p><em>Warning</em>: Someone might of been brute forcing your account.</p>";
echo "<p>Number of login attempts: <em>{$failed_login}</em>.<br />Last login attempt was at: <em>${last_login}</em>.</p>";
}
// Reset bad login count
$data = $db->prepare( 'UPDATE users SET failed_login = "0" WHERE user = (:user) LIMIT 1;' );
$data->bindParam( ':user', $user, PDO::PARAM_STR );
$data->execute();
}
else {
// Login failed
sleep( rand( 2, 4 ) );
// Give the user some feedback
echo "<pre><br />Username and/or password incorrect.<br /><br/>Alternative, the account has been locked because of too many failed logins.<br />If this is the case, <em>please try again in {$lockout_time} minutes</em>.</pre>";
// Update bad login count
$data = $db->prepare( 'UPDATE users SET failed_login = (failed_login + 1) WHERE user = (:user) LIMIT 1;' );
$data->bindParam( ':user', $user, PDO::PARAM_STR );
$data->execute();
}
// Set the last login time
$data = $db->prepare( 'UPDATE users SET last_login = now() WHERE user = (:user) LIMIT 1;' );
$data->bindParam( ':user', $user, PDO::PARAM_STR );
$data->execute();
}
// Generate Anti-CSRF token
generateSessionToken();
?>