【DVWA】Brute Force(暴力破解)通关教程

2023-03-12,,


日期:2019-08-01 14:49:47
更新:
作者:Bay0net
介绍:一直以为爆破很简单,直到学习了 Burp 的宏录制和匹配关键词,才发现 burp 能这么玩。。。


0x01、 漏洞介绍

利用大量的用户名和字典,去对账号进行暴力破解,人的问题(弱密码)可能是永远都无法防御的一个点吧。

DVWA 没模拟验证码缺陷的相关漏洞,在实战中,会遇到很多验证码无效的栗子。

0x02、Low Security Level

查看源码

<?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();
} ?>

分析源码

接受 usernamepassword 的值,然后传入数据库做比较,直接使用爆破即可。

万能密码

此处也可以使用万能密码进行登录。

admin'or '1'='1
admin' -- -
admin' #

0x03、Medium Security Level

查看源码

<?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、对传过来的值,使用了 mysql_real_escape_string() 函数,转义了以下字符:

\x00
\n
\r
\
'
"
\x1a

2、使用了 sleep(2) 函数,如果密码错误,则延时两秒响应。

如果爆破的话,还是可以直接进行爆破的,只不过速度慢了些而已。。

万能密码

因为过滤了单引号,我们无法闭合掉前面的单引号,所以此处无法再使用万能密码了。

0x04、High Security Level

查看源码

<?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(); ?>

分析源码

可以发现,每次发送的时候,都带上了一个 user_token,每次发送请求的时候 user_token 都是会变的,而 user_token 是来自于上一个数据包的。

使用 burp 爆破

依次选择【Project options】->【Sessions】->【add】-> 【add a Rule Description】-> 【Run a macro(宏)】

选择新建宏

添加的时候,选择配置

爆破成功。。挺费劲的,不如直接写 python 脚本。。

发现了一个问题,密码为 b 的 user_token,并不是密码 a 响应报文里面的 user_token,推测原理如下:

每次 burp 都会去访问之前宏里面的页面,然后获取 user_token,再给爆破数据包里面的 user_token 替换上,所以流程不是 a -> b -> c,而是 get_user_token -> a -> get_user_token -> b .....

0x05、Impossible Security Level

查看源码

<?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(); ?>

重点在于:

$total_failed_login = 3;
$lockout_time = 15;
$account_locked = false;

错误 3 次的话,就锁定 15 分钟,如果在实战中遇到这种情况,可以采用爆破用户名的方法来做。

0x06、burp 爆破匹配关键词

设置如下:

爆破成功会这样显示:

【DVWA】Brute Force(暴力破解)通关教程的相关教程结束。

《【DVWA】Brute Force(暴力破解)通关教程.doc》

下载本文的Word格式文档,以方便收藏与打印。