1.实验内容

1.1本周学习内容

(1)掌握基于html、php等编程工具实现简单前后端的编写
(2)理解apache在网站展示中的意义,认识到tomcat等web应用服务器工具的使用
(3)学习到以mysql为代表的数据库在网页项目中的具体使用
(4)通过webgoat、DWVA、pikachu等平台理解sql注入、xss、csrf等攻击的原理与其具体实现方法
(5)学会burpsuit的使用方法,掌握了口令爆破的基本方法

1.2实验具体任务

(1)Web前端HTML
能正常安装、启停Apache。理解HTML,理解表单,理解GET与POST方法,编写一个含有表单的HTML。

(2)编写Web前端javascipt,在理解DOM的基础上,实现用户点击登陆按钮后回显“欢迎+输入的用户名”,并利用回显用户名注入HTML及JavaScript。

(3)完成Web后端:MySQL基础:正常安装、启动MySQL,建库、创建用户、修改密码、建表

(4)完成Web后端:编写PHP网页,连接数据库,进行用户认证

(5)实现最简单的SQL注入,XSS攻击测试

(6)安装DVWA或WebGoat平台,并完成SQL注入、XSS、CSRF攻击。

2.实验过程

2.1Web前端HTML

首先什么是Apache?

Apache(音译为阿帕奇)是世界使用排名第一的Web服务器软件。它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛使用,是最流行的Web服务器端软件之一。在web网页设计课上我们就是使用其子工具tomcat实现将我们的项目部署在主机某服务器端口下

因此当我们要搭建一个网页时,必须保证apache是可用的,因此,在kali中,我们首先需要再命令行中输入systemctl start apache2以启动该服务。
同时我们可以通过输入systemctl status apache2以检查其状态。由下图我们可以看出,在启动后该服务的状态已经变成了active(running),即活跃状态。
当在kali浏览器里输入127.0.0.1返回如图界面时,也可以证明该服务已启动。

于是我们就可以开始尝试网页的编写
本实验中我所使用的网页代码为

点击查看代码
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8">
<title>EasyWeb</title>
<style>
    form {
        padding: 150px;
        width: 400px;
        margin: 100px auto;
    }

    label {
        display: block;
        margin-top: 10px;
    }

    input {
        width: 100%;
        padding: 5px;
        background-color:antiquewhite;
    }

    input[type = "submit"] {
        margin-top: 15px;
        background-color:ghostwhite;
        color:black;
        border: none;
        padding: 8px 15px;
    }
</style>
</head>

<body bgcolor="#faebd7">
    <form name="myForm" action = "20222319.php" method = "get" id="myForm" onsubmit="return check()">
        <hi>welcome to 20222319zzs's testweb</hi>
        <label for = "name">账号:</label>
        <input type = "text" id = "name">
        <label for = "password">密码:</label>
        <input type = "password" id = "password">
        <input type = "submit" value = "提交">
    </form>

</body>

在windows主机上其实现效果如图

于是我们将该文件放入kali虚拟机中/var/www/html的相应目录下,将该网页装载到服务器上
如果除了用管理员权限打开目标文件夹再将html拖入之外,我们也可以通过指令sudo cp 20222319.html /var/www/html/20222319.html 直接将文件复制进相应目录下,如图

此时我们可以在kali浏览器url中输入http://127.0.0.1/20222319.html即可访问我们装载上去的html,效果与主机上一致。

当我们随意输入一些信息,并点击提交后,我们可以看到输入的数据是直接在url中传输的,

http://127.0.0.1/20222319.php?name=20222319&password=zzs
当然,由于此时我设置跳转的php文件还没写好,因此其返回的是404,但确实成功展示了GET请求的特点,即数据明文传输

但当传输方式为POST时(在代码中修改),数据就不会再url中明文传输了,而是改为作post的一部分传输,如图。

所以简单来说,GET与POST最大的区别就是跳转url中会不会有明文数据

那什么是表单呢?
实际上,表单就是我们html代码中的<form>...</form>内容,因此我们的输入信息与输入框、跳转按钮在内的各种组件都在其中,
所以总的来说,就是
表单是由 HTML 表单标签 (

) 定义的,通过表单元素(如 <input>, <select>, <textarea> 等)收集数据,其数据提交到服务器通常通过 HTTP 方法(GET 或 POST)完成。

2.2Web前端javascript

首先,什么是javascript?

JavaScript 是一种脚本编程语言,它可以在网页上实现复杂的功能,让网页展现给你的不再是简单的静态信息,而是实时的动态的内容,比如交互式的地图、2D/3D 动画、滚动播放的视频等等

其次什么是DOM?

DOM定义了如何将HTML和XML文档表示为树形结构,以及如何通过编程方式访问和操作这些文档。DOM将文档呈现为一个由节点和对象(节点对象)组成的结构,允许程序和脚本动态地访问文档的内容、结构和样式。

具体来说,假设我们有如下的html

那么,DOM就是如图这样的树状结构,便于脚本语言的相关操作。

此处我修改了代码,添加了一个JavaScript 函数用于检查用户名和密码的合法性
具体如下

点击查看代码
<script>
    function check() {

        var name = document.getElementById('name').value;
        var password = document.getElementById('password').value;

        // 验证姓名不为空
        if (name === "") {
            alert('用户名不能为空');
            return false;
        }
        // 验证密码不为空
        if (password === "") {
            alert('密码不能为空');
            return false;
        }
        // 验证密码长度不小于8位
        if (password.length < 8) {
            alert('密码太短了,长一点吧');
            return false;
        }

        document.write('欢迎' + name);
        return true;
    }
</script>

此处javascript的逻辑为

check() 函数在表单提交时被触发。

首先获取用户名输入框(name)和密码输入框(password)的值。

然后验证用户名是否为空:如果用户名为空,则弹出警告框提示“用户名不能为空”,并返回 false 阻止表单提交。如果密码为空,则弹出警告框提示“密码不能为空”,并返回 false 阻止表单提交。

验证密码长度:如果密码长度小于8位,则弹出警告框提示“密码太短了,长一点吧”,并返回 false 阻止表单提交。

如果所有验证都通过,函数使用 document.write 将欢迎信息写入页面,并返回 true 允许表单提交。

错误输入返回如图

正确输入跳转到一个新页面,并输出欢迎+20222319zzs在网页左上角

此时我们尝试实现对表单的注入攻击
我们可以在账号一栏输入
<h1>你好,我是黑客,vo50解锁电脑</h1>
<script>alert('电脑已被封锁,请联系20222319解锁');</script>


可见,注入攻击成功了
就是要记得此处密码要输8位以上

2.3完成Web后端的mysql相关内容

在linux命令行中输入systemctl start mysql启动mysql服务
同时输入systemctl status mysql可以确认mysql的启动状态

于是我们依次输入如下内容:
mysql进入数据库操作界面
CREATE DATABASE zzsDB;创建数据库
use zzsDB;就进入创建好的数据库
CREATE USER '20222319zzs' IDENTIFIED BY '20222319zzs';创建用户
ALTER USER '20222319zzs' IDENTIFIED BY '20222319';修改用户密码
GRANT ALL PRIVILEGES ON zzsDB.* TO '20222319zzs';为刚创建好的用户赋予刚创建好的这一数据库的最高权限
FLUSH PRIVILEGES;刷新权限

CREATE TABLE test (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    pwd VARCHAR(255) NOT NULL
);

建立数据库表test,id作为主键且自增,用户名与密码以字符格式存储,不为空。

INSERT INTO test (name, pwd) VALUES ('zzs', '20222319');向表中插入数据
SELECT * FROM test;查询表中所有数据

结果如图所示,非常顺利!

2.4完成Web后端的php相关内容

此处我的后端php代码为

点击查看代码
<?php
$host = 'localhost';
$dbname = 'zzsDB';
$user = 'zzs';
$password = '20222319';

// 创建数据库连接
$conn = new mysqli($host, $user, $password, $dbname);

// 检查连接是否成功
if ($conn->connect_error) {
    die("连接失败: " . $conn->connect_error);
}

// 获取前端发来的数据
$name = $_POST['name'] ?? '';
$password = $_POST['password'] ?? '';

$sql = "select * from test where name = '$name' and pwd = '$password' ";
$result = $conn->query($sql);

 // 查询,判断用户是否在表中
if ($result->num_rows > 0) {
    echo "欢迎登录成功: " . $username . "!";
} else {
    echo "用户名或密码错误";
}

$conn->close(); // 关闭连接


?>

主要功能是接收前端传过来的用户名与密码,将这两个参数放到sql语句
select * from test where name = '$name' and pwd = '$password'
中进行查询,如果能同时找到该用户名与相应密码对应的记录,那么就是验证通过,在当前界面返回成功提示,反之则返回失败提示

如图(当然,这时候也只有zzs这一个用户而已)

2.5实现简单的SQL注入和XSS攻击

直接在登录界面输入' OR '1'='1' --

结果还是

对于XSS,则需要我们账号输入
<script>alert('电脑已被封锁,请联系20222319解锁');</script>
密码输入
' OR '1'='1

即可实现在跳转php界面显示弹窗

2.6安装DVWA或WebGoat平台,并完成SQL注入、XSS、CSRF攻击。

本次实验我选择的靶场是WebGoat,因为只需要将相应的.jar文件(如webgoat-2023.8.jar)安装至kali中,并在对应目录命令行下输入java -jar webgoat-2023.8.jar,即可在本地启动webgoat的网站服务。如图

启动后,进入浏览器输入127.0.0.1:8080/webgoat即可进入webgoat登录界面,注册成功后即可登录。进入主界面。

2.6.1 SQL注入

首先选中主界面边栏上(A3)Injection选项,
如图选择SQL Injection(intro)进行sql注入测试

点击后会返回如上图所示界面,一共有13个关卡,其中前8个关卡都是对sql基础操作的教学,比如条件搜索什么的,
sql注入的教学是在第9关才展示出来。
因此我们这里直接进入第9关

第9关英文意思为

在代码中的查询构建了一个动态查询,如前一个例子中所见。这个查询是通过连接字符串构建的,这使得它容易受到字符串 SQL 注入攻击:
"SELECT * FROM user_data WHERE first_name = 'John' AND last_name = '" + lastName + "'";
尝试使用下面的表单来从用户表中检索所有用户。您不需要知道任何特定的用户名就可以获取完整的列表。

对于该sql语句,实际上是模拟现实情况的一个由前后端组合的sql查询语句,一般我们只在前端进行操作,能看到并输入的内容仅仅是该完整sql语句中lastname这一部分的这一变量。
理论上,对于该语句我们只需将where后的判断结果都设为真,即可实现对所有信息的搜索。

同时我们可以看出,该变量的开头与结尾都加上了'号,但并未对输入长度进行检查,对输入字符进行检查。
当直接点击默认选项测试注入攻击时,结果返回

显然,我们的注入语句被'号括起来了,注入语句成为了一个字符串,失去了本身的语法功能。

因此,我们需要在smith后加上一个',同时减去or之后的'1 = 1'的后一个'
使得最终语句为
SELECT * FROM user_data WHERE first_name = 'John' and last_name = 'Smith' or '1' = '1'
即可实现sql注入攻击。

下一关。
对于10我们的处理也是同理,所以我们首先尝试
第一个空1 or 1 = 1 --试图将where的值置为永真,且注释掉后面的所有内容,所以第二个空随意。
但结果返回

说明第一个空只能为数字,可能存在字符的检验。
所以我们把永真的判定放到第二空上,因此第一个空也就随意了。
即上面两空对调,如图,注入成功。

2.6.2 XSS

这里还是选择点击A3,但得进入另一个界面—— Cross Site Scripting
其中前6关也都是一些XSS基础知识的讲解,
所以我们直接来到第7关。

经测试,我们发现该输入框对于输入数据的大小几乎没有太大的限制,且不会过滤某些字符
因此我们直接在输入框中输入
<script>alert('电脑已被封锁,请联系20222319解锁');</script>
<h1>你好,我是黑客,vo50解锁电脑</h1>

结果返回

说明这一关还没有完全接受中文,因此我们可以将xss语句做适当改动,如
<script>alert('The computer has been blocked, please contact 20222319 to unlock it');</script>
<h5>hello, I'm hacker vo50 to open this computer</h5>

即可成功实现XSS攻击

2.6.3 CSRF攻击

这里则是点击A10,进入Cross-Site Request Forgeries界面

直接进入第3关,直接点击Submit返回了一个错误提示

再点击Submit Query则进入了一个新的界面,
下图的提交按钮会发送一个请求,这题的要求是在webgoat用户登录的情况下,从其他网站触发这个请求,以获取flag,提交flag即可通关。

由于kali自带的burpsuit是社区版,因此不能使用poc功能,
但实际上我们仍然可以实现对第3题的攻击

首先按图中所示路径调出kali自带的burpsuit,

创建好项目进入操作界面后按下图所示顺序进入Proxy-> Intercept,
于是点击右上角Open browser启动burpsuit自带的浏览器,打开我们的webgoat进入csrf相应界面,

然后打开Intercept off,开始拦截

回到浏览器中点击Submit Query按钮
然后进入burpsuit的拦截界面,找到刚刚Submit Query对应的包,修改其中的refer路径,比如我这里就把ip改成了192.168.1.1

然后放行Forward,Submit Query对应的跳转界面就得到了如图所示结果,得到flag值为45761

于是回到webgoat的csrf第三关界面,输入该flag值,记得在burpsuit中放行Submit按钮的包


就成功实现了csrf攻击。

3.问题及解决方案

  • 问题1:手动实现csrf攻击情况下,得到的flag值一直不正确。
    以下这是我最初的操作流程:
    在主界面右键打开检查,在页面源代码中找到Submit Query按钮对应代码,如图

    将代码copy出来,并在action值的首部添加http://localhost:8080/WebGoat/
    使得跳转页面为http://localhost:8080/WebGoatcsrf/basic-get-flag

    将得到的代码写入一个html文件,直接本地打开,点击Submit Query按钮


    但flag值始终对不上。

  • 问题1解决方案:点击Submit Query后使用burpsuit修改相应post报文的refer数据然后放行,得到的flag界面的值就能拿来过关了。
    经资料搜集,我在实验中的操作主要是通过修改请求头中的referer字段,实现相当于从其他网站向目标请求发送请求的过程,因此能读到其他网站的flag值,但同时其他网站是我虚构的,因此不会与webgoat进行交互,因此就不会使flag值一直改变。

  • 问题2:php中数据库相关代码无反应,网页上其他部分正常显示,数据库相关部分一片空白,未显示报错。

  • 问题2解决方案:
    php除数据库外其他语句都能正常运行,但对于数据库相关的代码,比如有一句通过判断数据库连接成功与否决定向网页写入成功或失败的<h1提示信息的代码,不论怎么用都无反应,最简单测试连接的代码也不反应。
    且经phpinfo设置能确定mysqli成功装载、POD也成功装载,
    后面又在php.ini中设置mysqli与POD拓展启用
    最终又对数据库通过mysql_secure_installation 进行初始化了,
    还是不行。

结果只能是代码运行在同学的虚拟机中来解决这一问题。

4.学习感悟、思考等

其实本次实验很多内容都在平时的实践与作业中进行过测试与学习,比如三大靶场的训练,很多次网页前后端与数据库项目的搭建,因此本次实验对于我而言更像是一次复现的实现。
本次实验我最大的收获就是更进一步地理解了csrf的运行机理,本次实验之前我对于csrf的理解其实很大程度上仅限于明白怎么操作,怎么通过工具实现攻击,因此当我想尝试不通过poc手动实现攻击时,就会由于对攻击原理理解不到位而产生疏漏导致攻击失败。
同时csrf让我真正明白了点击不明链接的危害性,让我深刻认识到以后不能在访问涉及金钱的网站时随意地点击不明链接。
同时本次实验也让我对于自己搭建的哪些网页项目的安全性产生了思考。其实现在很多挂上公网的网站其一般都能防御一些简单的攻击了,比如在google hacking网页测试时我曾不小心对某一个老旧的地方公司网站输入过' OR '1'='1' --,该网站返回结果不是一般的登录成功跳转或登录失败提示,而是直接提示我这是黑客攻击行为,这让我明白我的项目若是要挂公网,我就必须得考虑对数据库对用户登录的安全性了,因为在互联网大量的随机或恶意扫描行为下,我的网站很难保证一直不被攻击。

参考资料

posted on 2024-12-19 21:08  20222319  阅读(5)  评论(0编辑  收藏  举报