DVWA简介

DVWA(Damn Vulnerable Web Application)是一个用来进行安全脆弱性鉴定的PHP/MySQL Web应用,旨在为安全专业人员测试自己的专业技能和工具提供合法的环境,帮助web开发者更好的理解web应用安全防范的过程。

DVWA共有十个模块,分别是Brute Force(暴力破解)、Command Injection(命令行注入)、CSRF(跨站请求伪造)、File Inclusion(文件包含)、File Upload(文件上传)、Insecure CAPTCHA(不安全的验证码)、SQL Injection(SQL注入)、SQL Injection(Blind)(SQL盲注)、XSS(Reflected)(反射型跨站脚本)、XSS(Stored)(存储型跨站脚本)。

DVWA作为一个专门的测试靶场,具备从低级到高级三种等级,并提供源代码。初学者可以通过比较不同难度的代码,接触到PHP代码审计的内容,这里我是用靶机Metasploitable2内置的DVWA环境。

Brute Force

Brute Force,即暴力破解,是指黑客利用密码字典,使用穷举法猜解出用户口令,是现在最为广泛使用的攻击手法之一。例如常说的“撞库”便是黑客通过收集信息来制作密码字典来进行对用户密码的爆破攻击。

下面介绍如何对DVWA上面的暴力破解漏洞进行利用并针对三个等级的源代码进行分析;

LOW

源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 <?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();

}

?>

可以看到,服务器的PHP代码只是用到isset函数来对获取到的用户名和密码进行验证(isset函数在php中用来检测变量是否设置,该函数返回的是布尔类型的值,即true/false),并没有任何的防爆破机制,并且并没有对username和password的sql查询进行过滤,存在明显的sql注入漏洞。

1
SELECT * FROM `users` WHERE user='$user' AND password='$pass';

这是php源码中使用的sql语句,查询之前并没有设置任何白名单与黑名单进行字符过滤,所以我们可以构造这样一条sql语句进行绕过:

1
SELECT * FROM `users` WHERE user='admin'or'1'='1' AND password='$pass';

将$user变量写为admin’or’1’=’1’可以形成一个形成一个or判断语句,并且’1‘=’1‘与后面的密码变量**$pass构成一个and判断语句,根据or语句一真即真的原则,用户名admin是正确的,密码不管是什么都可以将sql**语句执行成功。

还有一种注入方式是以注释#的方式将密码验证给注释掉,构造后代码如下:

1
SELECT * FROM `users` WHERE user='admin'# 'AND password='$pass';

使用#号注释后便把admin后面的密码注释掉,所以只需保证用户名的正确性便可以实现绕过。

Medium

源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?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级别的代码多了一个PHP语句

1
$pass = mysql_real_escape_string( $pass );

可以在网上查到mysql_real_escape_string函数可以转义特殊字符,包括\x00、\n、\r、\、’、”、\x1a字符,于是这次我们无法进行sql注入,所以我们直接回归主题进行爆破,我们使用的工具是burpsuite进行爆破。下面讲解详细步骤,我们使用火狐浏览器的代理服务器设为127.0.0.1,并将burpsuite也设置好端口,进行抓包。效果如下

ctrl+I将包复制到intruder模块,因为要对password参数进行爆破,所以在password参数的内容两边加$,可以点击右边的clear清除所有参数变量,然后选中顶部password后面的变量点击右边的add添加参数变量

选中Payloads,载入字典(kali自带字典的存放目录为/usr/share/wordlists/),点击Start attack进行爆破

可以看到password后面的长度与其他不同可以判断其为密码,这样我们就完成了暴力破解的工作

High

源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 <?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();
}
?>

我们与Medium级别的源代码比较发现只是增加了一个stripslashes函数(去除字符串中的反斜线字符,如果有两个连续的反斜线,则只去掉一个)增加了对参数username,password的过滤及转义。但是并没有对暴力破解进行限制,所以依旧可以使用burpsuite进行爆破这里我就不多赘述了。