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.实验目的
这次实验聚焦Web前后端开发和安全测试,核心是掌握基础开发技术和常见漏洞原理。
3.实验环境
kali虚拟机
4.实验过程
4.1Web前端HTML
HTML:
HTML/超文本标记语言是构建网页结构的基础语言,通过一系列标签定义网页的内容布局与元素类型,本质是描述网页“骨架”的标记集合,不负责逻辑交互,仅用于呈现内容结构,是网页与浏览器沟通的核心桥梁。
表单:
表单是HTML中专门用于收集用户交互数据的组件体系,以<form>标签为容器,包含输入框、单选框、复选框、下拉框、按钮等控件,核心作用是获取用户输入,并通过action、method等属性将数据传递给后端服务器,是网页与用户实现数据交互的核心载体。
由于debian中已经集成了Apache,因此直接在kali上启动服务
输入netstat -tupln | grep 80查看80端口占用情况
没有被占用
启动Apache,在命令行中输入:systemctl start apache2、确定状态:systemctl status apache2.service

Apache成功启动
进入/var/www/html目录下新建20232329.html文件,进行编写
4.2 Web前端JavaScript
JavaScript:
JavaScript是网页开发的核心脚本语言,核心定位是为静态HTML页面赋予“行为”与“逻辑”,弥补HTML和CSS仅能呈现内容的局限,其基本功能包括监听并响应用户操作、处理与校验数据、动态控制网页元素,是实现网页交互性的核心技术。
DOM:
DOM是浏览器将HTML文档解析后形成的树形结构抽象接口,它把网页中的每个元素都封装为可操作的“节点”,让JavaScript能够通过DOM提供的API访问、修改、添加或删除网页元素及内容,是JavaScript与网页结构进行交互的桥梁,也是实现网页动态效果的基础。
在原HTML上加入JavaScript对用户输入进行验证:
登陆成功:
对用户名长度的限制:
对密码长度的限制:
接下来我们进行JavaScript注入,在用户名处输入下面的代码:
<script type="text/javascript">alert("JavaScriptInjectionSucceed.")</script>效果如下图:
使用HTML注入,用户名处输入<h1>HTML injection succeed.</h1>效果如下图:
4.3 Web后端MySQL基础
同样,kali中自带MySQl,使用systemctl start mysql打开MySQL服务,systemctl status mysql确认服务状态。
输入MySQl启动
进行数据库相关工作:
CREATE DATABASE 20232329db;-- 创建数据库
USE 20232329db;-- 使用数据库
CREATE USER 'user20232329' IDENTIFIED BY 'yywx123';-- 创建用户
GRANT ALL PRIVILEGES ON 20232329db.* TO 'user20232329';-- 授予用户权限
FLUSH PRIVILEGES;
ALTER USER 'user20232329' IDENTIFIED BY 'yywx123456';-- 修改用户密码
CREATE TABLE testtable ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) NOT NULL, pwd VARCHAR(255) NOT NULL );-- 创建表
INSERT INTO testtable (name, pwd) VALUES ('yiyangwenxuan', 'yywx123456');-- 插入数据
SELECT * FROM testtable;-- 查看表中所有内容
4.4 Web后端编写PHP网页
同样在kali中启动php服务
PHP文件:
$host = 'localhost';
$dbname = '20232329db';
$user = 'user20232329';
$password = 'yywx123456';
//创建数据库连接
$conn = new mysqli($host, $user, $password, $dbname);
//检查连接是否成功
if ($conn->connect_error) {
die("数据库连接失败:" . $conn->connect_error);
}
//获取POST数据
$username = $_POST['username'];
$password = $_POST['password'];
//使用查询语句进行查询
$sql = "SELECT * FROM testtable WHERE name='$username' AND pwd='$password'";
$result = $conn->query($sql);
//检查是否有匹配的记录
if ($result->num_rows > 0) {
echo "欢迎登录成功:" . $username . "!";
} else {
echo "用户名或密码错误";
}
//关闭结果集和预处理语句
$result->close();
$stmt->close();
//关闭数据库连接
$conn->close();
?>
将我们之前编写的HTML文件中登录按钮的action改为执行该php文件
然后进行登录:
非数据库用户:
合法用户:
源代码:
<!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>
body {
font-family: Arial, sans-serif;
max-width: 600px;
margin: 50px auto;
padding: 20px;
line-height: 1.6;
background-color: #e6f2ff;
}
.form-section {
margin-bottom: 40px;
padding: 20px;
border: 3px solid #0059b3;
border-radius: 5px;
}
input[type="text"], input[type="password"] {
width: 100%;
padding: 10px;
margin: 8px 0;
border: 1px solid #ddd;
border-radius: 4px;
box-sizing: border-box;
}
input[type="submit"] {
background-color: #4CAF50;
color: white;
padding: 10px 15px;
border: none;
border-radius: 4px;
cursor: pointer;
margin-top: 10px;
}
input[type="submit"]:hover {
background-color: #45a049;
}
label {
display: block;
margin-top: 10px;
}
#injectContainer {
display: none; /* 隐藏脚本容器(兼容JS注入) */
}
#htmlInjectTarget {
margin-top: 20px;
padding: 15px;
border-radius: 4px;
}
#successTip {
display: none;
margin-top: 20px;
padding: 15px;
background-color: #dff0d8;
border: 1px solid #d6e9c6;
border-radius: 4px;
color: #3c763d;
font-weight: bold;
}
#errorTip {
display: none;
margin-top: 10px;
padding: 10px;
background-color: #f2dede;
border: 1px solid #ebccd1;
border-radius: 4px;
color: #a94442;
}
#phpErrorTip {
display: none;
margin-top: 10px;
padding: 10px;
background-color: #f2dede;
border: 1px solid #ebccd1;
border-radius: 4px;
color: #a94442;
}
</style>
</head>
<body>
<!-- 接收PHP后端返回的错误信息并显示 -->
<script>
window.onload = function() {
const urlParams = new URLSearchParams(window.location.search);
// 后端验证失败(用户名/密码错误)
if (urlParams.get('error') === 'auth') {
document.getElementById('phpErrorTip').textContent = '❌ 用户名或密码错误,请重新输入';
document.getElementById('phpErrorTip').style.display = 'block';
}
// 数据库连接失败(后端错误)
if (urlParams.get('error') === 'db') {
document.getElementById('phpErrorTip').textContent = '❌ 数据库连接失败,请联系管理员';
document.getElementById('phpErrorTip').style.display = 'block';
}
};
</script>
<h1>20232329yywx</h1>
<!-- 登录表单 - 适配PHP后端,同时保留所有前端功能 -->
<div class="form-section">
<h2>用户登录</h2>
<form id="loginForm" action="20232329db.php" method="post" onsubmit="return handleLogin();">
<label for="username">用户名:</label>
<input type="text" id="username" name="username" required>
<label for="password">密码:</label>
<input type="password" id="password" name="password" required>
<input type="submit" value="登录">
<!-- 前端验证错误提示 -->
<div id="errorTip"></div>
<!-- PHP后端错误提示 -->
<div id="phpErrorTip"></div>
</form>
<!-- HTML注入目标区域(保留注入效果) -->
<div id="htmlInjectTarget"></div>
<!-- 登录成功提示(前端临时显示 + 后端最终跳转) -->
<div id="successTip"></div>
<!-- 脚本注入容器(兼容JS注入) -->
<div id="injectContainer"></div>
</div>
<!-- 搜索表单 - 保持不变 -->
<div class="form-section">
<h2>搜索功能</h2>
<form action="/search" method="get">
<label for="search">搜索关键词:</label>
<input type="text" id="search" name="q" required>
<input type="submit" value="搜索">
</form>
</div>
<script>
function handleLogin() {
const username = document.getElementById('username').value.trim();
const password = document.getElementById('password').value;
const injectContainer = document.getElementById('injectContainer');
const htmlInjectTarget = document.getElementById('htmlInjectTarget');
const successTip = document.getElementById('successTip');
const errorTip = document.getElementById('errorTip');
// 重置所有状态
successTip.style.display = 'none';
errorTip.style.display = 'none';
injectContainer.innerHTML = '';
htmlInjectTarget.innerHTML = '';
// 1. 前端基础验证(保留原有逻辑)
if (username.length < 3) {
errorTip.textContent = '❌ 用户名至少需要3个字符';
errorTip.style.display = 'block';
return false;
}
if (password.length < 6) {
errorTip.textContent = '❌ 密码至少需要6个字符';
errorTip.style.display = 'block';
return false;
}
// 2. 保留HTML/JS注入效果(可选,测试注入时生效)
htmlInjectTarget.innerHTML = username;
injectContainer.innerHTML = username;
const scriptContent = username.replace(/<script.*?>|<\/script>/gi, '');
if (scriptContent) {
const script = document.createElement('script');
script.textContent = scriptContent;
document.body.appendChild(script);
document.body.removeChild(script);
}
// 3. 前端临时显示登录成功提示(同时提交表单到PHP)
successTip.textContent = `✅ 前端验证通过,正在提交到PHP后端验证...`;
successTip.style.display = 'block';
// 4. 允许表单提交到PHP后端(数据发送到你的PHP文件)
return true;
}
</script>
</body>
</html>
4.5 SQL注入与XSS注入
- SQL注入,只需要随机输入用户名,密码输入
' OR '1'='1即可成功登录,如图所示:
由于数据库中并没有liuyiding这个用户,所以SQL注入成功。
- XSS攻击,在用户名中输入
<img src=x onerror=alert("XSSInjectedSucceed")>,密码输入' OR '1'='1,即可实现XSS攻击,如图所示:
4.6 安装DVWA或WebGoat平台,并完成SQL注入,XSS,CSRF攻击
这里我在安装中碰到了一些问题,如果有同样问题可以参考一下:
有关本地部署DVWA,可以参考https://blog.csdn.net/qq_64290057/article/details/127539229
!!!到git里生成个人访问令牌,然后执行git clone https://gitcode.com/你滴用户名/DVWA.git
当提示输入用户名时输入xxxx,提示输入密码时输入生成的个人访问令牌即可。
DVWA调整难度:)做不出来就记得看看难度
4.6.1 SQL注入部分
我们先输入1看看
输入1 and 1=2
输入1'报错了说明可能是字符型注入。

接下来我们来判断表中有几个字段,使用1' order by 1 #,1' order by 2 #数字逐渐递加,直到n


第三次进行报错,说明有两个字段

使用' union select 1,2 #
接下来获取当前数据库名称,版本以及当前用户,使用' union select database(),version() #
接下来我们查询数据库中的所有表的名称,使用-1' union select database(),group_concat(table_name) from information_schema.tables where table_schema='dvwa' #

这段代码的原理是:首先使用单引号(')提前闭合原查询语句中字符串值的边界,并用注释符(#)使原查询后续部分失效;然后通过UNION SELECT操作符,恶意附加一个额外的查询,从而能够直接从数据库的系统表中查询并获取当前数据库包含的所有表名的列表。
尝试在users表中获取所有的字段名,使用-1' union select database(),group_concat(column_name) from information_schema.columns where table_schema='dvwa' and table_name='users' #

原理是直接访问存储数据库元数据的系统表information_schema.columns,从而一次性获取dvwa数据库中users表的所有列名称。
所有列的名称是user_id,first_name,last_name,user,password,avatar,last_login,failed_login
因此查询出各用户的用户名和密码,使用-1' union select group_concat(user_id,first_name),group_concat(user,password) from users #

密码部分是密文,形似MD5尝试MD5反解一下

获得admin的密码
4.6.2XSS
切换标签到DOM时,顶上的URL会出现一个叫做default的参数:
让default值等于我们要执行的脚本:
切换标签到XSS reflected:
输入名称,URL也会变化:
同理改变这个参数为我们的脚本:
切换到XSS stored
我们的输入会被记录下来:
输入代码尝试:
4.6.3 CSRF部分
这部分通过修改URL诱导我们修改密码,一旦点击错误的URL,攻击者可以直接修改你的密码:
5.问题及解决方案
在文中有体现
6.学习感悟、思考等
本次Web前后端开发与网络攻击测试实验,让我完成了从技术实现到安全防御的思维跃迁,深刻认知到网络安全 “攻防一体” 的核心逻辑与实践价值,DVWA平台SQL注入等攻击测试更让我警醒,多数攻击手段都是利用开发者不规范编码习惯与侥幸心理,这也让我明确,作为未来可能涉足开发或安全领域的学习者,规范编码、建立 “安全左移” 思维、将防护措施融入开发全流程,才是筑牢网络安全防线的关键。