一、Brute Force(暴力破解)
1.LOW
2. Medium
3.High
4.impossible级别
查看源码 发现代码并没有对账号密码进行过滤
' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
' );
if( $result && mysqli_num_rows( $result ) == 1 ) {
// Get users details
$row = mysqli_fetch_assoc( $result );
$avatar = $row["avatar"];
// Login successful
echo "Welcome to the password protected area {$user}
"; echo ""; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?>
Username and/or password incorrect.
两种方法:sql注入 和 bp抓包
sql注入
发现查询语句,只要传入参数即为真即可,所以我们考虑进行一个sql注入:admin’ or ‘1’='1
$query = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
$query = "SELECT * FROM `users` WHERE user = 'admin' or '1'='1' AND password = 'd41d8cd98f00b204e9800998ecf8427e';";
bp抓包暴力破解
添加字典
start attack 开始爆破
长度不一样的就是正确密码 password
登录成功
源码
' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
' );
if( $result && mysqli_num_rows( $result ) == 1 ) {
// Get users details
$row = mysqli_fetch_assoc( $result );
$avatar = $row["avatar"];
// Login successful
echo "Welcome to the password protected area {$user}
"; echo ""; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?>
Username and/or password incorrect.
发现比low多了这行代码
$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)) ? "" : ""));
若变量不存在则返回 FALSE(错误)
若变量存在且其值为NULL(无效),也返回 FALSE
若变量存在且值不为NULL,则返回 TURE(真)
同时检查多个变量时,每个单项都符合上一条要求时才返回 TRUE,否则结果为 FALSE
由于mysqli_real_escape_string()对字符串进行了转义,所以sql注入将不能运用。
我们用bp抓包就可以 和low抓包一样
我们这次抓账号和密码
clear$清除 add$添加 攻击模式选pitchfork
2个字典
' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
' );
if( $result && mysqli_num_rows( $result ) == 1 ) {
// Get users details
$row = mysqli_fetch_assoc( $result );
$avatar = $row["avatar"];
// Login successful
echo "Welcome to the password protected area {$user}
"; echo ""; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } // Generate Anti-CSRF token generateSessionToken(); ?>
Username and/or password incorrect.
使用了stripslashes函数和mysqli_real_esacpe_string来抵御SQL注入和XSS的攻击。
代码增加了token机制
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。
bp直接抓包
抓包可见,登录验证时提交了四个参数:username、password、Login以及user_token。
爆破模式Attack type选用Pitchfork,各自使用各自的互不影响.
请求包与自己的响应包有对应顺序,需要单线程,在Resource pool中添加一个单线程,线程数量修改为1。
在Options选项中,找到Grep Extract栏,添加一个从响应包中的提取规则。点击Add,并从响应报文中找到对应的token信息位置,选中之后会自动生成匹配规则,然后点击OK确定。确定之后会在Grep-Extract列表中出现这一规则。
一定要快,不然 就这样找不到了。被刷新了
设置字典
账号密码字典
因为token刷新的机制太快了,必须在1分钟之内完成爆破的设置。这也算是爆破成功了。
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 "
This account has been locked due to too many incorrect logins.
";
// Calculate when the user would be allowed to login again
$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) . "
";
print "The timenow is: " . date ("h:i:s", $timenow) . "
";
print "The timeout is: " . date ("h:i:s", $timeout) . "
";
*/
// Check to see if enough time has passed, if it hasn't locked the account
if( $timenow < $timeout ) {
$account_locked = true;
// print "The account is locked
";
}
}
// 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 "Welcome to the password protected area {$user}
";
echo "
";
// Had the account been locked out since last login?
if( $failed_login >= $total_failed_login ) {
echo "Warning: Someone might of been brute forcing your account.
";
echo "Number of login attempts: {$failed_login}.
Last login attempt was at: ${last_login}.
";
}
// 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 "
Username and/or password incorrect.
Alternative, the account has been locked because of too many failed logins.
If this is the case, please try again in {$lockout_time} minutes.
";
// 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();
?>
Impossible级别是难度最高的,其代码加入了可靠的防爆破机制,当检测到错误登录3次后将会锁定账户15s,系统会将账户锁定,爆破也就无法继续同时采用了更为安全的PDO(PHP Data Object)机制。简单来说输入错误会进入等待时间。这样是达到相对安全的密码验证。