About
密码破解是从计算机系统中存储或传输的数据中恢复密码的过程。一种常见的方法是反复尝试猜测密码。
用户通常选择弱密码。不安全选择的例子包括字典中的单个单词、姓氏、任何太短的密码(通常被认为少于6或7个字符)或可预测的模式(例如,交替使用元音和辅音,称为leetspeak,因此 “password” 变为p@55w0rd
).
创建针对目标的字典通常会获得最高的成功率。有一些公共工具可以根据公司网站、个人社交网络和其他常见信息(如生日或毕业年份)创建字典。
最后一种手段是尝试所有可能的密码,称为暴力攻击。理论上,如果尝试次数没有限制,暴力攻击总是会成功的,因为可接受密码的规则必须公开;但随着密码长度的增加,可能的密码数量也会增加,从而延长攻击时间。
Object
您的目标是通过暴力穷举获得管理员的密码。获得其他四个用户密码是一个加分项!
001 Low
本次的任务是入侵一个登陆页面:
我们先随便输入,比如admin:12345678
,然后得到一个错误提示:
我们打开 Burpsuite 的 Proxy,拦截页面请求,可以发现登陆请求用的是 GET 方法,参数通过 URL 传递,分别为username
和password
:
我们点击 Action → Send to Intruder 把数据包发送给攻击器。点击右侧的Clear §
,然后高亮password=12345678
,点击Add §
,攻击模式选择 Sniper:
四种暴力破解方式的区别:
- 一个字典,两个参数,先匹配第一项,再匹配第二项【sniper】
- 一个字典,两个参数,同用户名同密码【battering ram】
- 两个字典,两个参数,同行匹配,短的截止【pitch fork】
- 两个字典,两个参数,交叉匹配,所有可能【cluster bomb】
来到 Payload 页面,选择从文件加载,去 github 下载字典,然后载入字典:
现在我们点“开始攻击”,等待攻击器扫描完,把结果按长度排序,选择最长的那个:
第二种登陆的方法是使用 SQL 注入。我们观察源码:
页面从 GET 请求拿到参数后,直接使用 SQL 语句:
$query = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
查询,没有任何防护措施。所以,我们可以用简单的 SQL 注入登陆后台:
- Username:
admin' or '1'='1
- Password:随意
002 Medium
观察源代码:
<?php
if( isset( $_GET[ 'Login' ] ) ) {
// Sanitise username input
$user = $_GET[ 'username' ];
$user = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $user ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
// Sanitise password input
$pass = $_GET[ 'password' ];
$pass = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
$pass = md5( $pass );
// Check the database
$query = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '
<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
if( $result && mysqli_num_rows( $result ) == 1 ) {
// Get users details
// ...
}
else {
// Login failed
// ...
}
// ...
}
?>
该等级下代码增加了mysql_real_escape_string()
函数,它转义 SQL 语句中使用的字符串中的特殊字符,这抵挡大部分的 SQL 注入,但代码没有增加暴力破解的防护,所以可以和 Low 等级一样用 Brupsuite 穷举出弱口令。
003 High
观察源代码:
该级别的代码对用户输入增加了两个校验:
stripslashes()
函数:返回一个去除转义反斜线后的字符串(\'
转换为'
等等)。双反斜线(\\
)被转换为单个反斜线(\
)。mysql_real_escape_string()
函数:转义 SQL 语句中使用的字符串中的特殊字符,并考虑到连接的当前字符集。
抓包后我们发现这里多了一个参数user_token
:
把它转发给 Repeater(重放器),发送第一次请求会返回状态码为 200 的页面:
第二次发送请求则会返回状态码为 302 的页面:
这是由于每次user_token
的值会随着请求包的变化而变化,我们根据重定向,发现是 CSRF 错误:
对于这种情况,我们需要同时爆破password
和user_token
,攻击模式选用 Pitchfork:
Payload 1 和之前一样,使用 Simple List,载入密码字典。Payload 2 使用 Recursive Grep。选择 Option,把 Grep - Match 项清空,添加incorrect
:
然后到 Grep - Extract 里添加一个项,如页面没出来就 Fetch response:
由于我们会遇到 302 的页面,所以我们往下拉,把 Redirections 改为 Always:
开始攻击,注意 Brupsuite 会提示 Recursive Grep 无法用多线程,我们创建一个新的资源池,并发请求数为 1 就行了。
看图可知,上一个 Response 的user_toekn
会作为下一个 Request 的user_token
:
我们观察 incorrect 标志位可以区分出那个请求是成功了的。
References
- DVWA Brute Force (Low Level)
- DVWA——Brute Force(暴力破解) - 戚源
- DVWA系列(一)——使用Burpsuite进行Brute Force(暴力破解)_橘子女侠的博客
- 1 - Brute Force (low/med/high) - Damn Vulnerable Web Application (DVWA)