LOW
源代码如下:
<?php
if( isset( $_GET['Login'] ) ) {
$user = $_GET['username'];
$pass = $_GET['password'];
$pass = md5($pass);
$qry = "SELECT * FROM `users` WHERE user='$user' AND password='$pass';";
$result = mysql_query( $qry ) or die( '<pre>' . mysql_error() . '</pre>' );
if( $result && mysql_num_rows( $result ) == 1 ) {
// Get users details
$i=0; // Bug fix.
$avatar = mysql_result( $result, $i, "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>";
}
mysql_close();
}
?>
这里我们可以看到,首先通过GET传参,判断是否设置登录参数。但是sql语句是直接插入数据库执行,因此可以进行暴力破解。同时,没有过滤参数,可以进行sql注入。
直接使用burpsuite进行抓包拦截,然后进行破解即可。
将拦截的内容“send to intruder”进行破解
然后需要在intruder模块中设置相关参数,在target中设置需要破解的地址IP及端口号
在positions中设置需要破解的参数,因为要对password参数进行爆破,所以在password参数的内容两边加$
在paylads中导入密码字典,然后进行爆破
破解完成后,返回长度和其他不一样的就是破解成功了
Medium
源代码如下:
<?php
if( isset( $_GET[ 'Login' ] ) ) {
// Sanitise username input
$user = $_GET[ 'username' ];
$user = mysql_real_escape_string( $user );
// Sanitise password input
$pass = $_GET[ 'password' ];
$pass = mysql_real_escape_string( $pass );
$pass = md5( $pass );
$qry = "SELECT * FROM `users` WHERE user='$user' AND password='$pass';";
$result = mysql_query( $qry ) or die( '<pre>' . mysql_error() . '</pre>' );
if( $result && mysql_num_rows($result) == 1 ) {
// Get users details
$i=0; // Bug fix.
$avatar = mysql_result( $result, $i, "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>";
}
mysql_close();
}
?>
相比Low级别的代码,Medium级别的代码主要增加了mysql_real_escape_string函数,这个函数会对字符串中的特殊符号进行转义,基本上能够抵御sql注入攻击,说基本上是因为查到说 MySQL5.5.37以下版本如果设置编码为GBK,能够构造编码绕过mysql_real_escape_string 对单引号的转义(因实验环境的MySQL版本较新,所以并未做相应验证);同时,$pass做了MD5校验,杜绝了通过参数password进行sql注入的可能性。但是,依然没有加入有效的防爆破机制。所以依然使用burpsuite进行爆破即可,步骤和上面的一直,不再赘述。
High
源代码如下:
<?php
if( isset( $_GET[ 'Login' ] ) ) {
// Sanitise username input
$user = $_GET[ 'username' ];
$user = stripslashes( $user );
$user = mysql_real_escape_string( $user );
// Sanitise password input
$pass = $_GET[ 'password' ];
$pass = stripslashes( $pass );
$pass = mysql_real_escape_string( $pass );
$pass = md5( $pass );
$qry = "SELECT * FROM `users` WHERE user='$user' AND password='$pass';";
$result = mysql_query($qry) or die('<pre>' . mysql_error() . '</pre>' );
if( $result && mysql_num_rows( $result ) == 1 ) {
// Get users details
$i=0; // Bug fix.
$avatar = mysql_result( $result, $i, "avatar" );
// Login Successful
echo "<p>Welcome to the password protected area " . $user . "</p>";
echo '<img src="' . $avatar . '" />';
} else {
// Login failed
sleep(3);
echo "<pre><br>Username and/or password incorrect.</pre>";
}
mysql_close();
}
?>
High级别的代码加入了stripslashes函数,过滤了反斜杠。但依然没有防止暴力破解。继续使用burpsuite破解即可。
修复建议
转载自红日安全《DVWA 漏洞测试平台分析》:
- 对于修改数据和登陆表单提交使用 POST 方式,同时数据通过 POST 方式读取
- 添加随机 token 预防 csrf 攻击
- 针对登陆功能可添加图形验证码,每提交一次数据,验证码改变一次,验证功能在服务
端进行 - 针对登陆次数进行限制,可使用登陆远程 IP 或用户名两种方式进行锁定,登录错误次5 分钟之内超过 3 次锁定 1-3 小时
- 对于管理类系统配置登陆用户允许的 IP 范围
- 可使用短信验证和邮箱验证方式实现双因子认证,注意对短信轰炸和邮件轰炸的防御
- 密码等敏感字段进行加密后传输,例如密码使用加盐 hash 算法等加密