目录
Low
Medium
High
Impossible
Brute force主要是通过爆破达到渗透目的:
Low
查看源代码:
<?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 = 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
$row = mysqli_fetch_assoc( $result );
$avatar = $row["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>";
}
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
?>
以上代码的含义是:
这段 PHP 代码是一个处理登录请求的脚本,
if (isset($_GET['Login'])):判断是否通过 GET 方法传递了名为 Login 的参数,如果有,则执行后续的登录逻辑。
从 $_GET 中获取用户名 $user 和密码 $pass,并对密码使用 md5 进行哈希处理。
构建一个 SQL 查询语句 $query,从 users 表中查找用户名和密码匹配的记录。
使用 mysqli_query 执行查询,如果查询失败则输出错误信息并终止脚本。
如果查询结果存在且只有一行匹配,说明登录成功:
获取用户的头像信息 $avatar。
输出欢迎信息和显示头像。
如果查询结果不存在或匹配行数不为 1,则登录失败,输出错误提示。
最后使用 mysqli_close 关闭数据库连接。
接下来使用BP抓包:
空白处右键选择:发送给intruder
测试器-标签-位置,选择右侧清除
清除变量引用后,双击username跟password的变量值,并分别添加变量引用符号。
攻击类型选择:
集束炸弹(clusterbomb),可以对多个选定参数,这样我们可以同时对用户名跟密码互相组合发动爆破。
(拓展:狙击手(Sniper):仅指定单个爆破参数,定点爆破;
攻城锤/冲击夯(Battering Ram):指定一个文件对多个位置参数实施爆破,所有参数位置都一样;
音叉/鱼叉(Pitchfork):加入两个变量值)
选择“有效载荷-有效载荷集”,选择1,有效载荷类型:“简单清单”。用户名爆破用例随意输入
“有效载荷-有效载荷集”,选择2,有效载荷类型:“简单清单”。密码爆破用例同样随意输入:
点击右上角:发动攻击
我们发现,其中有一个长度比较异常(最长),尝试登录,
登录成功,结论:用户名:admin,密码:password
low通关。
Medium
调整靶场难度为: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
$row = mysqli_fetch_assoc( $result );
$avatar = $row["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>";
}
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
?>
代码含义:
首先,通过 isset($_GET['Login'])
判断是否接收到了登录请求。然后对用户名 $user
和密码 $pass
进行了一些处理和净化:
- 使用
mysqli_real_escape_string
函数来处理可能存在的特殊字符,以防止 SQL 注入。 - 对密码进行了
md5
哈希处理。
接着执行一个 SQL 查询从 users
表中查找匹配的用户和密码。如果查询成功并且返回的行数为 1,表示登录成功:
- 获取用户的头像信息
$avatar
。 - 输出欢迎信息和头像。
如果查询结果为空或者行数不为 1,表示登录失败:
- 程序会暂停 2 秒。
- 输出登录失败的提示信息。
最后,关闭了与数据库的连接。
Medium级别比上一个级别多了一个sleep(),即登录失败后会有两秒的静默延迟。但我们同样可以使用LOW级的爆破方式做测试,但是时间会长一点。(参考low方法)
High
代码分析:
<?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 = ((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 = stripslashes( $pass );
$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 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
$row = mysqli_fetch_assoc( $result );
$avatar = $row["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>";
}
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
// Generate Anti-CSRF token
generateSessionToken();
?>
主要加入了token校验,抓包看下:
此时若盲目爆破则会比较困难,每次请求页面都会重新生成新的token,这里我们使用BP工具生成token,使得每一次爆破都会主动携带token。
右键发送Intruder:
清除变量符:
双击负载的变量值并一次添加变量符,攻击方式选择集束炸弹(Clusterbomb):
配置有效载荷:
针对 账户名:
针对 密码:
针对token:
重定向选择:
选项-线程数thread为“1”,
复制之后要点击“ok”,切记不要“叉掉”,选择有效载荷(payloads)
点击攻击:
最长字节为爆破结果。
(这里建议仅针对 password和token 的变量值爆破,这样速度比较快,结果也会比较直观)。
Impossible
加入了一些防爆破的手段,限制登录次数,并做了登错时间静默与锁定。