20222420 2024-2025-1 《网络与系统攻防技术》实验八实验报告
1.实验内容
1.1 近期学习内容简述
(1)学习了Web前后端的语言的简介
(2)学习了SQL注入的多个实例,知道了SQL注入的原理
(3)学习了XSS跨站脚本攻击的原理和示例
(4)了解了CSRF的原理和防范方法
(5)了解了Burpsuite等工具
1.2 实验内容简述
- (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)
(1)正常安装、启停Apache
-
使用
sudo apt install apache2
命令自动安装配置Apache(由于kali自带,这里就不展示了) -
使用
sudo systemctl start apache2
命令启动Apache,使用sudo systemctl status apache2
命令查看Apache状态
可知已经启动
-
浏览器浏览
localhost
可再次确定Apache启动成功
-
使用
sudo systemctl stop apache2
命令关闭Apache,使用sudo systemctl status apache2
命令查看Apache状态
可知已经关闭
(2)理解HTML,理解表单,理解GET与POST方法,编写一个含有表单的HTML
-
在
/var/www/html/
创建文件Get_method.html
- 创建一个html文件在桌面,然后使用命令
sudo mv Get_method.html /var/www/html/Get_method.html
将其移动到/var/www/html/
- Get_method.html中写入Get方法的html代码
- 访问
http://localhost/Get_method.html
并提交数据
可知,Get方法提交后,数据在URL中可见
- 创建一个html文件在桌面,然后使用命令
-
在
/var/www/html/
创建文件Post_method.html
-
创建一个html文件在桌面,然后使用命令
sudo mv Post_method.html /var/www/html/Post_method.html
将其移动到/var/www/html/
-
Post_method.html中写入Post方法的html代码
-
访问
http://localhost/Post_method.html
并提交数据
可知,Post方法提交后,数据在URL中不可见,因为数据放在HTTP请求的主体部分(body),不会显示在URL中。
-
但是抓包还是能抓到明文数据,使用https就会安全很多
-
(3)总结 GET 方法和 POST 方法
区别 | GET 方法 | POST 方法 |
---|---|---|
请求目的 | 从指定的资源请求数据 | 向指定的资源提交数据以进行处理(例如,创建/更新资源) |
请求参数位置 | 参数附加在URL的末尾(查询字符串) | 参数包含在HTTP请求的主体中 |
数据可见性 | 参数在URL中可见,可能会被缓存和记录在服务器日志中 | 参数在HTTP请求主体中,相对不那么容易被直接访问或记录 |
数据大小限制 | 通常受限于URL长度和服务器配置(较短) | 无严格限制,取决于服务器配置(较长) |
安全性 | 不太安全,因为参数在URL中可见 | 相对更安全,因为参数不在URL中,但需要使用HTTPS来确保数据传输的安全性 |
浏览器书签 | 可以将请求URL书签化 | 无法直接书签化POST请求的URL |
缓存 | 浏览器和某些中间件可能会缓存GET请求的响应 | POST请求的响应通常不会被缓存 |
使用场景 | 适用于请求数据而不改变服务器状态的操作(例如,搜索查询) | 适用于提交数据以改变服务器状态的操作(例如,表单提交) |
2.2 Web前端javascipt(理解JavaScript的基本功能,理解DOM;在(1)的基础上,编写JavaScript验证用户名、密码的规则。在用户点击登陆按钮后回显“欢迎+输入的用户名”;尝试注入攻击:利用回显用户名注入HTML及JavaScript)
-
在
/var/www/html/
创建文件Post_JS.html
-
Post_JS.html中写入Post方法的html代码
点击查看代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Register: POST JS 20222420</title>
<style>
/* 简单的样式,用于显示欢迎信息 */
#welcomeMessage {
color: green;
font-weight: bold;
margin-top: 20px;
}
</style>
</head>
<body>
<h1>Register: POST JS 20222420 </h1>
<form id="myForm" action="/submit" method="post">
<label for="username">Username:</label>
<input type="text" id="username" name="username" required>
<br><br>
<label for="password">Password:</label>
<input type="password" id="password" name="password" required>
<br><br>
<button type="submit">Submit</button>
</form>
<p id="welcomeMessage"></p> <!-- 用于显示欢迎信息的元素 -->
<script>
// 获取表单元素
const form = document.getElementById('myForm');
const usernameInput = document.getElementById('username');
const passwordInput = document.getElementById('password');
// 添加事件监听器
form.addEventListener('submit', function(event) {
// 阻止表单的默认提交行为
event.preventDefault();
// 获取用户输入
const username = usernameInput.value.trim();
const password = passwordInput.value.trim();
// 验证用户名和密码
const usernameValid = username.length >= 5;
const passwordValid = password.length >= 8 && /\d/.test(password);
// 如果验证通过
if (usernameValid && passwordValid) {
// 显示欢迎信息
document.write('欢迎' + username);
} else {
// 如果验证失败
alert('用户名必须至少包含5个字符,密码必须至少包含8个字符且包含至少一个数字。');
}
});
</script>
</body>
</html>
-
验证“JavaScript验证用户名、密码格式”的功能。验证在用户点击按钮后回显“欢迎+输入的用户名”的功能。
- 用户名符合,但密码未含数字
我只设置了一个提示信息,所以用户名和密码均提醒了
- 用户名长度不够,密码符合
我只设置了一个提示信息,所以用户名和密码均提醒了
- 用户名、密码格式均符合,回显“欢迎+输入的用户名”
- 用户名符合,但密码未含数字
-
注入攻击:利用回显用户名注入HTML及JavaScript
用户名输入<script>alert('你被20222420攻击了!')</script> <h1>你被20222420攻击了</h1>
- JavaScript效果
- HTML效果
- JavaScript效果
2.3 Web后端(MySQL基础:正常安装、启动MySQL,建库、创建用户、修改密码、建表)
(1)安装
使用sudo apt install mariadb-server
命令自动安装配置即可,mariadb-server适用于需要存储和管理大量数据的场景。由于kali自带了mariadb,这里就不展示了
(2)启动并验证,并登录
-
使用
systemctl start mysql
启动,systemctl status mysql
验证
disable是指未设置开机自启动,但其是启动了的、在运行的
-
登录,使用
sudo mysql -uroot -p
,输入mysql的密码时直接输入“回车”
(3)建库并验证
使用create database test;
创建名为test的数据库实例,然后使用show databases;
验证
(4)创建用户并验证
使用CREATE USER 'test'@'%' IDENTIFIED BY 'test';
,还可以将test数据库实例的权限授予test用户
(5)修改密码
使用ALTER USER 'test'@'%' IDENTIFIED BY 'change';
(6)建表并使用、验证
-
使用
CREATE TABLE testTable (id INT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(255) NOT NULL);
可以创建一个表并设置了主键
-
添加数据到表,只需要添加到
name
,主键会自动递增添加
INSERT INTO testTable (name) VALUES ('Alice');
`INSERT INTO testTable (name) VALUES ('Bob');``
-
查看、验证表
使用select * from testTable;
,可知表创建成功并成功添加了数据
2.4 Web后端:编写PHP网页,连接数据库,进行用户认证
-
root用户创建
user_auth
数据库实例,并创建表users
、插入数据-
创建
user_auth
数据库实例
-
进入实例,创建表
users
,CREATE TABLE users (id INT AUTO_INCREMENT PRIMARY KEY,username VARCHAR(50) NOT NULL,password VARCHAR(50) NOT NULL);
-
修改root密码,使其不为空(否则后续连不上),并给予其user_auth的权限(虽然默认root创建者有权限)
-
插入数据,
INSERT INTO users (username, password) VALUES ('testuser', 'testpassword');
-
-
编写PHP网页
点击查看代码
<?php
session_start();
// 数据库连接参数
$servername = "localhost";
$dbusername = "root";
$dbpassword = "root";
$dbname = "user_auth";
// 创建数据库连接
$conn = new mysqli($servername, $dbusername, $dbpassword, $dbname);
// 检查连接是否成功
if ($conn->connect_error) {
die("连接失败: " . $conn->connect_error);
}
// 如果表单已提交
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$inputUsername = $_POST['username'];
$inputPassword = $_POST['password'];
// 查询数据库中的用户
$result = $conn->query("SELECT * FROM users WHERE username = '$inputUsername' AND password = '$inputPassword'");
if ($result->num_rows > 0) {
// 如果用户存在,获取其信息
$row = $result->fetch_assoc();
$_SESSION['loggedin'] = true;
$_SESSION['username'] = $inputUsername;
echo "登录成功!";
// 这里可以重定向到其他页面
// header("Location: protected_page.php");
// exit();
} else {
echo "用户名不存在,或密码错误。";
}
// 关闭结果集
$result->close();
}
// 关闭数据库连接
$conn->close();
?>
<!DOCTYPE html>
<html>
<head>
<title>用户登录</title>
</head>
<body>
<h2>登录 made by 20222420</h2>
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">
用户名: <input type="text" name="username" required><br>
密码: <input type="password" name="password" required><br>
<input type="submit" value="登录">
</form>
</body>
</html>
- 登录,验证“用户认证”功能
-
用户不存在或密码错误示例
我没有区分具体是用户不存在还是密码错误
-
验证,登录成功示例
-
2.5 最简单的SQL注入,XSS攻击测试
使用2.4中的数据库和php网页
-
SQL注入
使用' or 1=1; --
作为用户名,注意一定要在--
后添加空格否则会卡死在相关语句。密码可以随便填
这样sql语句变为SELECT * FROM users WHERE username = '' or 1=1; -- AND password = '$inputPassword'
。WHERE中一定为真,并且--
后的语句被注释掉了导致不需要密码
-
XSS攻击
-
首先需要修改一下php网页,使其可以回显用户输入的账户名,否则攻击语句无法执行
如图,修改代码,使其可以在登录失败时回显输入的用户名
-
验证,输入
<script>alert("20222420XSS")</script>
如图,利用网站没有对用户提交数据进行转义处理或者过滤的缺点,添加了html代码,嵌入到web页面中去
-
2.6 安装DVWA或WebGoat平台,并完成SQL注入、XSS、CSRF攻击
(1)DVWA平台
-
完成SQL注入
- 首先输入
' or 1=1; --
进行测试
可以,SQL注入已经成功,输出了全表的内容。还可知显示的id并不是表中的id而是直接返回了我输入的内容。
- 进一步进行SQL注入,获取更多信息
使用' or 1=1 union select version(),database(); --
如下图,可知,不仅显示了人名,还通过union显示了数据库的版本号为“5.7.26”,及当前数据库名“dvwa”
- 首先输入
-
完成XSS攻击
-
题目如图
-
这一题中,只能选择语言并提交。通过仔细观察和反复尝试,可知点击提交后会在URL中出现
default=
并显示所选择的语言。
可以分析出,该网页使用的是GET来传递参数
-
改变
default=
后的内容,实现XSS攻击
改为<script>alert("20222420XSS")</script>
,由下图可知成功
-
-
完成CSRF攻击
-
分析该题
该题可以更改自己的密码,然后可以验证修改后的密码
-
测试后发现,参数直接通过URL传递
-
准备CSRF攻击
通过burp拦截,我就得到了一个发送的包,然后通过burp中的工具直接便捷得生成CSRF攻击用的html
-
修改一下生成的html中的密码的值,使其变为我想要攻击他人时使其密码改变为的值,如
6666
,然后复制生成的URL
-
这样,当他人在登陆着
http://127.0.0.1/DVWA-master/vulnerabilities/csrf/
时,若点击了我的危险网站(即上面生成的URL,或包含该URL的其他看似正常的网站),他的密码就会被我改变
如下图所示
-
测试
由下图可知,成功了
-
(2)WebGoat平台
-
完成SQL注入
-
在
Login_Count
输入1 or 1=1; --
进行测试
但显示无法解析我的输入到一个数字
-
查看题目得知,只有一个空对于SQL注入是脆弱的,看来应该是下面一个空
在User_Id
输入1 or 1=1
,在Login_Count
输入正常的数字。如下可知注入成功。
-
-
完成XSS攻击
直接输入<script>alert("20222420XSS")</script>
-
完成CSRF攻击
-
这道题需要从发送评论,但必须从其他地方发送
只需要用burp拦截获取包的格式,然后生成CSRF的html,再修改一下生成的html即可,如下图,我想发送的评论是test
星级为4
-
复制得到的URL
-
验证
当登陆着http://127.0.0.1:8080/WebGoat/csrf/review
的人点击了该URL,就会发送该评论(test
,星级为4
)
验证过程如下面三图,可知我(即被攻击者)已经成功从其他位置发送了该评论
-
3.问题及解决方案
- 问题1:无法将创建的文件放入/var/www/html/
- 问题1解决方案:利用sudo mv命令就有权限了
- 问题2:SQL注入时一直不成功
- 问题2解决方案:询问AI,本来AI是不会给相关的答案的。但换一种方式问,问我这样能否通过,AI就给出了回答。然后我就得知原来--后需要空格才能起到注释的效果,这样我就解决了问题。
- 问题3:我写的网页先用SQL语句验证了用户名,然后用$row['password'] === $inputPassword验证密码。但只有用户名能使用SQL注入,这导致我无法用SQL注入登录。
- 问题3解决方案:更改代码,像课件里的一样用SQL语句同时验证用户名和密码即可直接通过SQL注入登录。
- 问题4:php连接不上数据库
- 问题4解决方案:经过检查,代码是没问题的,数据库也没问题。可能是因为数据库的root用户没有设置密码,且$dbpassword = "";不代表没有密码,导致连接不上数据库。设置密码后便解决了。
4.学习感悟、思考等
在这次实验中,我体会了Web开发中的前端与后端技术是如何协同工作的。通过安装和配置Apache服务器以及MySQL数据库,我学会了如何在服务器端搭建一个Web环境。编写HTML表单和JavaScript验证逻辑,让我对前端技术有了更深入的理解,特别是在处理用户输入和表单提交方面。同时,我也认识到了前端验证的重要性,但它并不能替代后端验证,因为前端验证可以被绕过。此外,通过编写PHP网页和进行用户认证,我进一步了解前端和后端mysql的协同。在测试SQL注入、XSS攻击、CSRF攻击的过程中,我也深刻认识到了Web安全的复杂性。