注意,这里需要使用字典,点我下载字典top100

这里的防护等级是逐级加高的,最明显的出现防护等级提升的是对于SQL语句防护的提升。

Low

源码分析

<?php

if( isset( $_GET[ 'Login' ] ) ) {
// 获取get传参
$user = $_GET[ 'username' ];
$pass = $_GET[ 'password' ];

// md5加密
$pass = md5( $pass );

// 数据库查询语句
$query = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
// 查询,查到就返回正确结果,查不到报错结果
$result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );

// 基本识别,正确就返回Welcome,错误就返回Username
if( $result && mysql_num_rows( $result ) == 1 ) {
$avatar = mysql_result( $result, 0, "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>";
}
mysql_close();
}
?>

破解

破解的思路:

1.暴力破解,直接调用字典进行破解

// 因为没有任何认证,直接破解无需顾忌什么。
// 尝试进行登录,截取到下面的URL:
http://127.0.0.1/vulnerabilities/brute/?username=name&password=123456&Login=Login
// 其中,出现关键变量,也即是账户信息:
username=name&password=123456
能更迭的是俩个变量:username和password
// 尝试使用BP进行暴力破解

Burp操作
Burp操作
Burp操作
Burp操作

Medium

源码

<?php

if( isset( $_GET[ 'Login' ] ) ) {
// Sanitise username input
$user = $_GET[ 'username' ];
$pass = $_GET[ 'password' ];
// 将传入的特殊字符进行转义处理,例如加斜杠
$user = mysql_real_escape_string( $user );
$pass = mysql_real_escape_string( $pass );

// 加密
$pass = md5( $pass );

$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 ) {
$avatar = mysql_result( $result, 0, "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>";
}
mysql_close();
}
?>

解题

思路:
和上面相比,多了一个转义语句,这道题目相当与加了一个屏障
防止特殊语句的注入,单仍然无法防止暴力破解
解题思路和LOW相同,使用字典破解即可
具体步骤不赘述

height

源码

<?php

if( isset( $_GET[ 'Login' ] ) ) {
// Token唯一身份认证(目前最大麻烦)
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

// Sanitise username input
$user = $_GET[ 'username' ];
$pass = $_GET[ 'password' ];
// 去除反斜杠、转义字符
$user = stripslashes( $user );
$pass = stripslashes( $pass );
// 转义掉特殊字符,防止sql注入
$user = mysql_real_escape_string( $user );
$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();

?>

解题

针对Token的解决思路:实时捕获Token并且加入信息提交
Token本身是随机生成的,用于防止直接的暴力破解

=>使用BP解决Token的动态捕获和返还问题

新版BP貌似没有带单线程攻击,使用旧版BP即可

难度等级3的BP攻击
难度等级3的BP攻击
难度等级3的BP攻击
难度等级3的BP攻击
难度等级3的BP攻击
难度等级3的BP攻击

Impossible

源码

<?php
if( isset( $_POST[ 'Login' ] ) ) {
// Token唯一身份认证
//检查反CSRF令牌
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

// 清理用户名和密码输入
$user = $_POST[ 'username' ];
$pass = $_POST[ 'password' ];
$user = stripslashes( $user );
$pass = stripslashes( $pass );
$user = mysql_real_escape_string( $user );
$pass = mysql_real_escape_string( $pass );

$pass = md5( $pass );

//默认值
# 登录失败总数
$total_failed_login = 3;
# 锁定时间
$lockout_time = 15;
# 账户锁定
$account_locked = false;

//检查数据库(检查用户信息)
# 准备SQL查询语句,:user是占位符
$data = $db->prepare( 'SELECT failed_login, last_login FROM users WHERE user = (:user) LIMIT 1;' );
# 用参数绑定将变量 $user 与 :user 占位符进行关联
$data->bindParam( ':user', $user, PDO::PARAM_STR );
# 上两句合起来就是一句完整的sql语句
# 执行查询语句
$data->execute();
# 默认从执行方法取出一行数据
$row = $data->fetch();


//检查用户是否已被锁定。
# 判断用户是否被锁定
# 如果被锁定:阻止其登录

# # $data->rowCount() == 1
# ==> 判断用户是否存在
# - 判断之前查询的结果中是否返回一行数据

# # $row[ 'failed_login' ] >= $total_failed_login
# => 获取之前用户尝试登录的失败次数
# - 判断 $row 变量中的 failed_login 字段的值是否大于等于 $total_failed_login 变量的值
# - 这句就是限制访问次数的,限定3次锁定
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>";
//用户被锁定。请注意,使用此方法将允许用户枚举!
//echo"<pre><br/>由于登录错误太多,此帐户已被锁定。</pre>";


//计算何时允许用户再次登录
# 计算阻止登陆的时间
$last_login = $row[ 'last_login' ];
$last_login = strtotime( $last_login );
$timeout = strtotime( "{$last_login} +{$lockout_time} minutes" );
$timenow = strtotime( "now" );

//检查是否已经过了足够的时间,是否还没有锁定帐户
# 检测当前用户登录的时间是否大于阻止登录的时间
if( $timenow > $timeout )
$account_locked = true;
}

# 从用户表当中检测登录的用户名和密码是否正确
$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
// 生成反CSRF令牌
generateSessionToken();

?>

解题

难度有点大,暂时不做。