关于DVWA的学习-Brute Force
low
随便试了一下,账号密码和登录dvwa的一样,登陆成功会显示avatar
看了一下PHP源码
没有对SQL注入进行防范,本来直接输入 ’ or 1=1#,但应该是由于返回的行数超过1,也不能显示avatar,加一个LIMIT 1即可。
medium
和low一样,试了一下就登进去了,确实没太懂想考察啥。
打开源码看了一下:
首先应该是对sql注入进行了一些防范,给引号啥的加了转义字符。
比较重要的是,fail的情况多了个sleep函数,应该是防止爆破的一种手段(不过感觉也没啥用。。)
high
多了一个user_token,每轮爆破之前要先得到这个令牌,就在网页的html代码里:
用python的requests先获得token,在加入username和password进行爆破即可,不赘述了,没啥意思-.-
impossible
直接代码审计:
<?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; //登录尝试次数超过这个值会提示和:存在attacker
$lockout_time = 15; //lock out时间为15min
$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!
//$html .= "<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 ) //看当前时间是否达到封锁15min
$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
$html .= "<p>Welcome to the password protected area <em>{$user}</em></p>";
$html .= "<img src=\"{$avatar}\" />";
// Had the account been locked out since last login?
if( $failed_login >= $total_failed_login ) { //判断是否超过最大登录次数3次
$html .= "<p><em>Warning</em>: Someone might of been brute forcing your account.</p>";
$html .= "<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
$html .= "<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();
?>
登录失败提示的那个15min,在尝试三次以内时候并不是真的需要等十五分钟,写的不清不楚的啊。。。建议好好看看源码。
总结一下:
- PDO和mysql_real_escape_string,stripslashes共同防范了sql注入问题
- 尝试次数+lock out机制使得爆破攻击成功的概率几乎为0。