20232307 2025-2026-1 《网络与系统攻防技术》实验八实验报告
1.实验内容
(1)Web前端HTML
能正常安装、启停Apache。理解HTML,理解表单,理解GET与POST方法,编写一个含有表单的HTML。
(2)Web前端javascipt
理解JavaScript的基本功能,理解DOM。
在(1)的基础上,编写JavaScript验证用户名、密码的规则。在用户点击登陆按钮后回显“欢迎+输入的用户名”
尝试注入攻击:利用回显用户名注入HTML及JavaScript。
(3)Web后端:MySQL基础:正常安装、启动MySQL,建库、创建用户、修改密码、建表
(4)Web后端:编写PHP网页,连接数据库,进行用户认证
(5)最简单的SQL注入,XSS攻击测试
(6)安装DVWA或WebGoat平台,并完成SQL注入、XSS、CSRF攻击。
2.实验过程
2.1 Web前端HTML
能正常安装、启停Apache。理解HTML,理解表单,理解GET与POST方法,编写一个含有表单的HTML。
2.1.1 能正常安装、启停Apache
Apache(Apache HTTP Server)是世界上使用最广泛的开源Web服务器软件之一,Apache的核心功能是接收客户端,如浏览器的HTTP/HTTPS请求,处理并返回对应的资源。
命令systemctl stop apache2可关闭Apache服务。
使用如下命令启动Kali虚拟机中自带的Apache服务:
systemctl start apache2 #启动Apache服务
systemctl status apache2.service #确认服务状态

打开浏览器输入localhost,如果看到Apache的启动页面,说明安装成功。

2.1.2 理解HTML,理解表单,理解GET与POST方法
HTML:
HTML是超文本标记语言,是用于构建网页结构的标准标记语言,它通过一系列标签定义网页的内容和布局。HTML的核心是标记,用预定义标签包裹内容,让浏览器能解析并渲染出文本、图片、链接、表单等元素。
表单:
HTML 表单是网页中用于收集用户输入并提交到服务器的核心组件,是用户与网站交互的关键入口,如登录、注册、搜索、提交数据等场景。表单通过各类表单控件接收用户输入,常见控件包括文本框、密码框、提交按钮等。表单的核心属性包括指定数据提交的服务器地址和指定提交方式,如 GET/POST,当用户点击提交按钮时,表单会将控件中的数据封装后发送到action指定的地址,由后端处理。
GET与POST方法:
GET方法:数据会附加在URL末尾,格式为?key1=value1&key2=value2,可见性高;传输数据量有限;常用于获取数据,请求可被缓存、收藏,安全性较低,不适合传输敏感数据。
POST方法:数据会被封装在HTTP请求的请求体中,不在URL中显示,隐蔽性好,传输数据量无明确限制,可传输大文件或敏感数据;常用于提交、修改数据,请求不会被缓存,安全性更高。
2.1.3 编写一个含有表单的HTML
进入var/www/html/目录,创建一个HTML文件:
cd /var/www/html/
vim 20232307my.html
我们创建一个用户登录页面,包含用户名、密码两个必填输入框,并通过POST方法将数据提交至login.php后端处理,但是目前还没有后端,样式上通过CSS重置统一默认样式,具备基础的表单交互与数据提交功能。
代码如下:
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>用户登录</title><style>* {margin: 0;padding: 0;box-sizing: border-box;font-family: Arial, sans-serif;}body {background-color: #f5f5f5;display: flex;justify-content: center;align-items: center;min-height: 100vh;}.login-container {background-color: white;padding: 2rem;border-radius: 8px;box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);width: 100%;max-width: 400px;}.login-container h2 {text-align: center;margin-bottom: 1.5rem;color: #333;}.form-group {margin-bottom: 1rem;}.form-group label {display: block;margin-bottom: 0.5rem;color: #555;}.form-group input {width: 100%;padding: 0.8rem;border: 1px solid #ddd;border-radius: 4px;font-size: 1rem;}.form-group input:focus {outline: none;border-color: #007bff;box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25);}.submit-btn {width: 100%;padding: 0.8rem;background-color: #007bff;color: white;border: none;border-radius: 4px;font-size: 1rem;cursor: pointer;transition: background-color 0.3s;}.submit-btn:hover {background-color: #0056b3;}</style>
</head>
<body><div class="login-container"><h2>用户登录</h2><!-- POST方式提交的表单 --><form action="login.php" method="POST"><div class="form-group"><label for="username">用户名:</label><input type="text" id="username" name="username" required placeholder="请输入用户名"></div><div class="form-group"><label for="password">密码:</label><input type="password" id="password" name="password" required placeholder="请输入密码"></div><button type="submit" class="submit-btn">登录</button></form></div>
</body>
</html>
打开浏览器,输入网址http://localhost/20232307my.html访问网站
网站界面如下图所示:

输入账号密码,可以看到使用POST实现安全的数据提交,URL中不显示提交的数据。

2.2 Web前端javascipt
理解JavaScript的基本功能,理解DOM。在2.1的基础上,编写JavaScript验证用户名、密码的规则。在用户点击登陆按钮后回显“欢迎+输入的用户名”,尝试注入攻击:利用回显用户名注入HTML及JavaScript。
2.2.1 理解JavaScript的基本功能,理解DOM
JavaScript的基本功能:
①动态修改网页内容和样式:实时更新文本、切换元素显示状态
②响应用户交互:处理点击、输入、鼠标移动等事件
③数据处理与计算:执行算术运算、字符串操作、数组处理等逻辑
④异步网络请求:通过AJAX/fetch与后端交互获取数据,实现无刷新更新页面
⑤客户端存储:利用localStorage/sessionStorage保存用户数据
⑥控制浏览器行为:跳转页面、操作Cookie、实现定时器等
DOM:
DOM(Document Object Model,文档对象模型)是W3C制定的标准接口,它将HTML/XML文档转换为树形结构的对象模型,把文档中的每个元素、属性和文本都封装成可被脚本操作的对象。通过DOM,JavaScript可以访问、修改、添加或删除网页中的任何节点,例如获取元素内容、修改样式、创建新节点,实现网页内容的动态更新。DOM本质是连接HTML结构与JavaScript行为的桥梁,使静态的网页文档具备可交互的动态特性。
2.2.2 编写JavaScript验证用户名、密码的规则
验证的规则是:用户名不能为空,密码需6-20位且包含字母+数字。
- 用户名验证:通过validateUsername函数检查用户名是否为空,若为空则显示 “用户名不能为空” 的错误提示。
- 密码验证:通过validatePassword函数结合正则表达式/^(?=.[a-zA-Z])(?=.\d).{6,20}$/校验,要求密码长度在6-20位之间,且必须同时包含字母和数字,不符合则显示对应错误提示。
表单提交时会先执行验证逻辑,只有两项输入均符合规则时,才会展示欢迎信息,否则阻止表单提交并显示错误。
完整的HTML文件代码:
点击查看代码
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>用户登录</title><style>* {margin: 0;padding: 0;box-sizing: border-box;font-family: Arial, sans-serif;}body {background-color: #f5f5f5;display: flex;justify-content: center;align-items: center;min-height: 100vh;}.login-container {background-color: white;padding: 2rem;border-radius: 8px;box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);width: 100%;max-width: 400px;}.login-container h2 {text-align: center;margin-bottom: 1.5rem;color: #333;}.form-group {margin-bottom: 1rem;}.form-group label {display: block;margin-bottom: 0.5rem;color: #555;}.form-group input {width: 100%;padding: 0.8rem;border: 1px solid #ddd;border-radius: 4px;font-size: 1rem;}.form-group input:focus {outline: none;border-color: #007bff;box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25);}.submit-btn {width: 100%;padding: 0.8rem;background-color: #007bff;color: white;border: none;border-radius: 4px;font-size: 1rem;cursor: pointer;transition: background-color 0.3s;}.submit-btn:hover {background-color: #0056b3;}.error-message {color: #dc3545;font-size: 0.875rem;margin-top: 0.25rem;display: none;}/* 放大欢迎信息区域,让注入内容更显眼 */.success-message {font-size: 1.5rem;text-align: center;margin-top: 1.5rem;padding: 1rem;border-radius: 4px;background-color: #f8f9fa;display: none;}</style>
</head>
<body><div class="login-container"><h2>用户登录</h2><form id="loginForm" action="#" method="POST"><div class="form-group"><label for="username">用户名:</label><input type="text" id="username" name="username" placeholder="输入任意内容"><div class="error-message" id="usernameError">用户名不能为空</div></div><div class="form-group"><label for="password">密码:</label><input type="password" id="password" name="password" placeholder="请输入密码"><div class="error-message" id="passwordError">密码长度需在6-20位之间,且至少包含字母和数字</div></div><button type="submit" class="submit-btn">登录</button><!-- 欢迎信息区域(使用innerHTML渲染) --><div class="success-message" id="welcomeMessage"></div></form></div><script>const loginForm = document.getElementById('loginForm');const usernameInput = document.getElementById('username');const passwordInput = document.getElementById('password');const usernameError = document.getElementById('usernameError');const passwordError = document.getElementById('passwordError');const welcomeMessage = document.getElementById('welcomeMessage');function validateUsername(username) {return username.trim() !== '';}function validatePassword(password) {const regex = /^(?=.*[a-zA-Z])(?=.*\d).{6,20}$/;return regex.test(password);}loginForm.addEventListener('submit', function(e) {e.preventDefault();let isValid = true;usernameError.style.display = 'none';passwordError.style.display = 'none';welcomeMessage.style.display = 'none';if (!validateUsername(usernameInput.value)) {usernameError.style.display = 'block';isValid = false;}if (!validatePassword(passwordInput.value)) {passwordError.style.display = 'block';isValid = false;}if (isValid) {const username = usernameInput.value;// 关键修改:使用innerHTML替代textContent,允许解析HTML/JSwelcomeMessage.innerHTML = `欢迎您:${username}`;welcomeMessage.style.display = 'block';}});</script>
</body>
</html>
进入浏览器打开用户登录网页:
按要求输入用户名和密码:

如上图所示,通过规则验证,显示“欢迎您:my2307”。
当用户名为空时:

如上图所示,用户名未通过规则验证,显示提示“用户名不能为空”。
当密码不符合要求时:

如上图所示,密码未通过规则验证,显示提示“密码长度需在6-20位之间,且至少包含字母和数字”。
2.2.3 尝试注入攻击,利用回显用户名注入HTML及JavaScript
由于代码中使用innerHTML而非textContent处理用户输入,textContent仅渲染纯文本,会将<、>等符号转义,无法解析HTML/JS;而innerHTML会解析HTML结构并执行内嵌的JavaScript,直接将用户输入作为代码执行,从而导致注入攻击。
(1)注入 HTML
在用户名中输入:
<h1 style="color:red">攻击测试</h1>
攻击者将恶意代码注入到Web页面,当其他用户访问该页面时,代码被浏览器解析执行,当用户输入
<h1 style="color:red">攻击测试</h1>,Web应用未对用户输入做HTML转义,导致攻击者输入的HTML代码被浏览器解析执行,浏览器解析到这段HTML时,会按照<h1>标签的样式渲染 “攻击测试”。
页面会显示红色大标题的 “攻击测试”,如下图所示:

(2)注入JavaScript
在用户名中输入:
<img src='x' onerror='document.body.innerHTML = "JavaScript攻击注入成功!"'>
<img src='x'>是一个图片标签,但src='x'是无效的图片地址,因此浏览器加载图片时会触发标签的onerror事件,onerror事件中嵌入了JavaScript 代码:document.body.innerHTML = "JavaScript injection succeed.",该代码会将整个页面的内容替换为指定文本,实现对页面的篡改。

跳转显示JavaScript攻击注入成功!

2.3 Web后端:MySQL基础
正常安装、启动MySQL,建库、创建用户、修改密码、建表
2.3.1 安装、启动MySQL
systemctl start mysql #启动MySQL
systemctl status mysql #查看MySQL运行状态

2.3.2 建库、创建用户、修改密码、建表
①输入mysql进入数据库管理系统:

②建库、创建用户:
使用以下命令,创建了一个名为db2307的数据库,创建了一个用户,用户名为usermy,初设密码为my123456,授予该用户所有权限,刷新权限。
CREATE DATABASE db2307;#建库
CREATE USER 'usermy' IDENTIFIED BY 'my123456'; #创建用户
GRANT ALL PRIVILEGES ON db2307.* TO 'usermy'; #授予用户所有权限
FLUSH PRIVILEGES; #刷新权限
运行命令如下图所示:

③修改密码:
修改usermy用户密码为my20232307。
ALTER USER 'usermy' IDENTIFIED BY 'my20232307'; #修改用户密码
FLUSH PRIVILEGES; #刷新权限
运行命令如下图所示:

④创建表:
创建一个为test的用户信息表,包含id(主键)、username(50字符非空字符串)、password(100字符非空字符串)三个字段;表通过自增主键确保记录唯一性,用户名和密码字段设为非空保证数据完整性。
CREATE TABLE test (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
password VARCHAR(100) NOT NULL
); #创建表
SHOW TABLES; #查看当前数据库中所有的数据表名称
DESCRIBE test; #查看名为`test`的数据表的详细结构
运行命令如下图所示:

⑤插入数据:
向test表中插入了两条用户记录,具体数据如下:
第一条记录:id为1,username为user1,password为user123
第二条记录:id为2,username为user2,password为user231
INSERT INTO test VALUES (1,'user1', 'user123'),(2,'user2', 'user231'); #插入数据
SELECT * FROM test; #查看表中所有内容
运行命令如下图所示:

2.4 Web后端:编写PHP网页,连接数据库,进行用户认证
还是在var/www/html/目录下,我们新建一个PHP文件,用于接收前端输入的用户名和密码,将输入的信息与数据库中的信息进行比对,验证是否匹配。
PHP代码如下:
<?php
// 设置响应为JSON格式
header('Content-Type: application/json');// 数据库配置
$db_host = 'localhost';
$db_name = 'db2307';
$db_user = 'usermy';
$db_pass = 'my20232307';// 初始化响应数据
$response = ['success' => false,'message' => '','data' => []
];// 仅允许POST请求
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {$response['message'] = '请使用POST请求';echo json_encode($response);exit;
}// 获取用户输入(不进行过滤)
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';// 基本输入验证(但不过滤特殊字符)
if (empty($username)) {$response['message'] = '用户名不能为空';echo json_encode($response);exit;
}if (empty($password)) {$response['message'] = '密码不能为空';echo json_encode($response);exit;
}try {// 连接数据库$pdo = new PDO("mysql:host=$db_host;dbname=$db_name;charset=utf8mb4", $db_user, $db_pass);$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);// 直接拼接SQL语句$sql = "SELECT id, username, password FROM test WHERE username = '$username' AND password = '$password' LIMIT 1";// 执行SQL查询$stmt = $pdo->query($sql);$user = $stmt->fetch(PDO::FETCH_ASSOC);if ($user) {// 登录成功 - 直接输出用户输入(存在XSS漏洞)$response['success'] = true;$response['message'] = '登录成功';$response['data'] = ['user_id' => $user['id'],'username' => $username, // 直接输出,不进行HTML编码'raw_username' => $username, // 再次直接输出'sql_query' => $sql // 泄露SQL查询信息];} else {// 登录失败 - 也直接输出用户输入$response['message'] = '用户名或密码错误';$response['data'] = ['attempted_username' => $username, // 直接输出'attempted_password' => $password, // 直接输出密码(信息泄露)'sql_query' => $sql];}} catch(PDOException $e) {// 向用户暴露详细错误信息(信息泄露)$response['message'] = '数据库错误:' . $e->getMessage();$response['data'] = ['error_details' => $e->getMessage(),'sql_query' => $sql ?? '未执行'];
}// 返回结果 - 不进行任何输出编码
echo json_encode($response, JSON_UNESCAPED_UNICODE);?>
HTML文件稍做修改,完整代码如下:
点击查看代码
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>用户登录</title><style>* {margin: 0;padding: 0;box-sizing: border-box;font-family: Arial, sans-serif;}body {background-color: #f5f5f5;display: flex;justify-content: center;align-items: center;min-height: 100vh;}.login-container {background-color: white;padding: 2rem;border-radius: 8px;box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);width: 100%;max-width: 400px;}.login-container h2 {text-align: center;margin-bottom: 1.5rem;color: #333;}.form-group {margin-bottom: 1rem;}.form-group label {display: block;margin-bottom: 0.5rem;color: #555;}.form-group input {width: 100%;padding: 0.8rem;border: 1px solid #ddd;border-radius: 4px;font-size: 1rem;}.form-group input:focus {outline: none;border-color: #007bff;box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25);}.submit-btn {width: 100%;padding: 0.8rem;background-color: #007bff;color: white;border: none;border-radius: 4px;font-size: 1rem;cursor: pointer;transition: background-color 0.3s;}.submit-btn:hover {background-color: #0056b3;}.error-message {color: #dc3545;font-size: 0.875rem;margin-top: 0.25rem;display: none;}.server-error {color: #dc3545;background-color: #f8d7da;padding: 0.75rem;border-radius: 4px;margin-bottom: 1rem;text-align: center;display: none;}/* 保持原有欢迎信息样式,但使用innerHTML渲染 */.success-message {font-size: 1.5rem;text-align: center;margin-top: 1.5rem;padding: 1rem;border-radius: 4px;background-color: #f8f9fa;display: none;}</style>
</head>
<body><div class="login-container"><h2>用户登录</h2><div class="server-error" id="serverError"></div><form id="loginForm"><div class="form-group"><label for="username">用户名:</label><input type="text" id="username" name="username" placeholder="输入任意内容"><div class="error-message" id="usernameError">用户名不能为空</div></div><div class="form-group"><label for="password">密码:</label><input type="password" id="password" name="password" placeholder="请输入密码"><div class="error-message" id="passwordError">密码长度需在6-20位之间,且至少包含字母和数字</div></div><button type="submit" class="submit-btn">登录</button><!-- 使用innerHTML渲染欢迎信息 --><div class="success-message" id="welcomeMessage"></div></form></div><script>const loginForm = document.getElementById('loginForm');const usernameInput = document.getElementById('username');const passwordInput = document.getElementById('password');const usernameError = document.getElementById('usernameError');const passwordError = document.getElementById('passwordError');const welcomeMessage = document.getElementById('welcomeMessage');const serverError = document.getElementById('serverError');function validateUsername(username) {return username.trim() !== '';}function validatePassword(password) {// 放宽密码验证,方便测试return true;}function hideAllMessages() {usernameError.style.display = 'none';passwordError.style.display = 'none';welcomeMessage.style.display = 'none';serverError.style.display = 'none';}loginForm.addEventListener('submit', function(e) {e.preventDefault();let isValid = true;hideAllMessages();if (!validateUsername(usernameInput.value)) {usernameError.style.display = 'block';isValid = false;}if (!validatePassword(passwordInput.value)) {passwordError.style.display = 'block';isValid = false;}if (isValid) {const formData = new FormData(this);fetch('20232307.php', {method: 'POST',body: formData}).then(res => res.json()).then(data => {if (data.success) {// 使用innerHTML渲染,确保XSS代码执行welcomeMessage.innerHTML = `欢迎您:${data.data.username}`;welcomeMessage.style.display = 'block';// 兼容处理:如果是script标签,确保执行const scripts = welcomeMessage.querySelectorAll('script');scripts.forEach(script => {const newScript = document.createElement('script');newScript.textContent = script.textContent;document.body.appendChild(newScript).parentNode.removeChild(newScript);});} else {serverError.textContent = data.message;serverError.style.display = 'block';}}).catch(err => {serverError.textContent = '网络错误,请重试';serverError.style.display = 'block';});}});</script>
</body>
</html>
打开浏览器,输入网址http://localhost/20232307my.html访问网站进行测试,先输入数据库中已有的数据,输入用户名“use1”,密码“user123”,如下图所示:

如上图所示,验证通过,显示“欢迎您:user1”。
当用户名正确,密码错误时

如上图所示,输入的信息错误,提示:用户名或密码错误。
当输入不存在的用户名时:

如上图所示,输入的信息内容不存在,提示:用户名或密码错误。
2.5 最简单的SQL注入,XSS攻击测试
2.5.1 SQL注入
用户名输入:
' OR '1'='1' --
使用最经典的基于布尔盲注的SQL注入payload,当我在用户名输入框填入 ' OR '1'='1' -- 、密码填任意值时,拼接后的SQL会变成:SELECT * FROM users WHERE username = '' OR '1'='1' -- ' AND password = '任意值';密码验证被完全跳过。
密码输入任意,结果如下图所示,可以看到显示欢迎' OR '1'='1' -- ,说明SQL注入成功。

2.5.2 XSS攻击
用户名输入:
<img src=x onerror=alert("XSS攻击成功!")>
攻击者在输入框提交
<img src=x onerror=alert("XSS攻击成功!")>,后台未对输入做任何处理,直接将这段代码作为HTML内容输出到页面,浏览器渲染页面时,解析到标签,尝试加载src=x的图片,但是图片不存在,必然失败,图片加载失败触发onerror事件,浏览器立即执行onerror属性内的alert("XSS攻击成功!");
最终弹出弹窗,证明XSS漏洞存在且可执行任意JS代码。
密码输入任意,结果如下图所示,可以看到跳出一个弹窗,显示XSS攻击成功!

2.6 安装DVWA或WebGoat平台,并完成SQL注入、XSS、CSRF攻击。
2.6.1 环境准备
我使用的是DVWA平台,在kali虚拟机中安装DVWA平台,然后执行以下命令:
sudo service apache2 start # 1. 启动 Apache2 Web 服务
sudo service mysql start # 2. 启动 MySQL 数据库服务
接着在浏览器中输入http://localhost/dvwa/setup.php网址,即可进入DVWA平台,点击创建数据库,然后进入登陆界面,初始默认的用户名是admin,密码是password,点击登录,就进入DVWA平台了,在做实验之前记得选择难度为low.

2.6.2 SQL注入
1.输入User ID为1,显示了对应的name,并且输入的ID值在URL栏中,也说明了是get方法传递参数

输入User ID为1',可以看到出现了一些错误:

由此猜测,存在诸如点,且为字符型注入,单引号闭合。
2.判断字段数
先使用1' order by 1#来尝试一下:
使用列数探测语句, 1'闭合SQL语句中的单引号,触发注入漏洞,order by 1是按第1列排序,#是MySQL 数据库的注释符,注释掉语句后面的所有内容,避免原SQL的剩余字符破坏注入语句的语法。

页面反馈是正常的,接着尝试1' order by 2#

页面反馈依旧是正常的,接着尝试1' order by 3#

页面报错,即可确定表的列数,第三列是不存在的,数据库的表只有两列。
3.查看表中的相关字段
(1)查看当前数据库的版本号,及当前数据库名
使用以下注入语句来查看数据库的版本号及当前数据库名,结果如下图所示:
1' union select version(),database() --

可以当前数据库版本是11.8.3-MariaDB-1+b1 from Debian;当前数据库名是dvwa
(2)查看当前数据库下的所有表名
使用以下注入语句来查看当前数据库下的所有表名:
1' union select version(),group_concat(table_name) from information_schema.tables where table_schema=database() --
结果如下图所示:

可以看到dvwa 数据库有两个数据表:guestbook和users;
(3)查询users表下面的所有字段名
使用以下注入语句来查询users表下面的所有字段名
1' union select version(),group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users' --
结果如下图所示:

查询到users表的列名:user_id,first_name,last_name,user,password,avatar,last_login,failed_login
(4)查询users表中的user、password字段数据:
使用注入语句:1' union select user,password from users # 查询users表中的user、password字段数据,结果如下图所示:

如上图所示,查询到了用户名及其密码,返回的密码是MD5哈希值,攻击者可通过哈希破解工具还原为明文,例如查询一下5f4dcc3b5aa765d61d8327deb882cf99对应的明文,查询网站使用了MD5在线解密,解密结果如下图所示:

2.6.2 XSS攻击
(1)XSS(DOM)
观察界面,当选择不同的标签时,URL栏中的default也会发生变化:

default有可能是个传参点,修改default=后面的参数为20232307my,结果如下图所示:

传入xss代码:
<script>alert(20232307)</script>
结果如下图所示:

由上图所示,XSS(DOM)攻击成功。
(2)XSS Reflected
尝试输入值2307:

发现无论我们输入什么值,在页面中都会显示输入的信息,并且url的name传参值就是我们输入的值。
对URL中的name传入xss代码:
<script>alert(20232307)</script>

由上图所示,XSS Reflected攻击成功。
(3)XSS Stored
先尝试输入学号2307,可以看到信息被存储了:

输入xss代码:
<script>alert(2307)</script>
结果如下图所示:

发现name处存在字符限制,使用F12查看前端的代码:

将10个字符的限制修改为100个字符,修改后的代码如下:

重新输入XSS攻击代码<script>alert(2307)</script>

由上图所示,XSS Stored攻击成功。
2.6.2 CSRF攻击
由于这一步骤需要使用Burp Suite工具,我的Burp Suite工具安装在windows主机上面了,所以这一步我是在Windows系统中打开的DVWA平台和Burp Suite工具。
尝试修改密码为12345,

但是能够主要到当我们更改密码成功后url栏的参数是这样的
http://127.0.0.1/DVWA/vulnerabilities/csrf/?password_new=12345&password_conf=12345&Change=Change#
可以分析出password_new是我输入的密码,password_conf是我确认的密码,说明我们在网站上输入的信息是会在url栏这里进行一个传输执行,
使用Burp Suite抓包,如下图所示:

发现url栏的信息和请求的信息是一致的,大胆猜测如果我能控制url栏里传入的参数,就能够不在网站内执行更改密码的操作。
更改url的参数:
http://127.0.0.1/DVWA/vulnerabilities/csrf/?password_new=123456&password_conf=123456&Change=Change#
只需要在原来的url基础上该新密码和确认密码的参数即可。

如上图所示,页面跳转到了dvwa的更改密码界面,csrf攻击成功。
但是在真实CSRF攻击中,攻击者为了隐藏自己的攻击手段,可能构造一个假的页面,然后放在公网上,诱导受害者访问这个页面,如果受害者访问了这个页面,那么受害者就会在不知情的情况下完成了CSRF攻击。自己测试可以写一个本地页面,也可以利用burpsuit直接生成攻击页面代码。方法如下:
抓取更改密码的数据包,利用engagement tools生成CDRF PoC,访问点击提交之后就可以更改密码。CDRF PoC生成器生成的代码如下图所示:

我最开始在DVWA网站想修改密码为12345,但是在CDRF PoC生成的代码中,我把密码改为了123456,点击用浏览器测试:

复制网址到浏览器中:

点击send request以后发现密码成功修改:

进入DVWA平台的初始登陆界面,使用我刚刚修改的密码123456登录:

可以看到登陆成功:

3.问题及解决方案
- 问题1:在2.4编写PHP网页,连接数据库,进行用户认证的过程中,前端的数据信息并没有传到后端。
- 问题1解决方案:经过检查,发现创建PHP文件时,没有和HTML文件放在同一个目录下,更改到同一个目录下之后运行成功。
- 问题2:windows平台中尝试使用Burp Suite工具,但是Burp Suite工具抓不到DVWA平台的包。
- 问题2解决方案:原因是Firefox默认不代理本地地址(localhost/127.0.0.1)的流量,需要修改配置:在Firefox地址栏输入 about:config,点击 “接受风险并继续”;搜索network.proxy.allow_hijacking_localhost,双击将其值改为True。
4.学习感悟、思考等
通过本次实验我进一步理解了Web安全和相应的攻击手段,在实现一个虽然简单但是完整的前端、数据库、后端处理的整体连接后成就感满满,“实践是检验真理的唯一标准”,通过实践不仅加深了我对知识的理解,更是增强了对代码的理解和整体框架的搭建能力。
在DVWA平台的实践让我觉得十分有趣,通过SQL注入、XSS、CSRF攻击的实践,我进一步理解了攻击的原理和目的,同时也意识到网络攻击不可忽视,不要随意点击陌生链接。
本学期的实验到这里就结束了,经过一学期的网络攻防课程的学习,我对我的专业有了更深刻的认知,非常感谢这一学期以来老师和同学们对我的帮助,未来我将继续精进我的专业能力,继续努力!
参考资料
- 搭建DVWA靶场保姆级教程(超详细)
- 如何搭建Pikachu靶场保姆级教程(附链接)
- DVWA通关攻略零到一【全】