安全之路任重而道远,前端安全是众多安全中的一个分支。随着互联网的发达,各种WEB应用也变得越来越复杂,满足了用户的各种需求,但是随之而来的就是各种网络安全的问题。
一、安全关键词
先了解几个定义:域、脚本、授权、读写、资源、同源策略、信任、社工。
1. 域
同域要求两个站点:同协议、同域名、同端口。
下表展示了所列站点与http://www.mina.com是否同域的情况。
2. 脚本
主要指JavaScript和ActionScript,当然也包括VBScript(相对较孤立)。
3. 授权
如Ajax跨域,默认情况下是不允许跨域访问的,只有目标站点(假如是http://www.mina.com)明确返回http响应头 Access-Control-Allow-Origin:http://www.mine.com时,www.mine.com站点上的客户端脚本才能有权通过Ajax技术对www.mina.com上的数据进行读写操作。
4. 读写权限
Web上的资源有很多,有的只有读权限,有的同时拥有读和写的权限。比如:http请求头里的Referer只可读,而document.cookie则具备读写权限。
5. 资源
同源策略里的资源是指web客户端的资源。一般来说,包括:http消息头、整个DOM树、浏览器存储(Cookies、FlashCookies、localStorage等)。
6. 同源策略
不同域的客户端脚本在未经授权的情况下不能读写对方的资源。
如果没有同源策略,Web世界会发生什么?
当你登录邮箱,并打开另一个站点e时,e站点上的JavaScript就可以跨域读取你的邮箱数据,导致隐私泄露。
7. 信任
安全问题从某种程度上讲就是信任问题。同源策略也是信任的一种表现,默认情况下,不同源则不信任。
以下两个场景有利于小伙伴们理解:
场景一:
一个Web服务器上有两个网站A和B,黑客入侵目标是A,但是直接入侵A遇到了巨大困难,而入侵B却成功了。由于A与B之间过于信任(在同一个文件系统里,且没有有效的文件权限配置),未能做很好的分离,黑客就可以轻松地攻克网站A。
场景二:
网站本身是很安全的,由于嵌入了第三方内容(如统计脚本),建立了信任关系,如果第三方的统计脚本被黑客挂马,将导致网站不安全。虽然这样不会导致你的网站直接被入侵,但却危害到了访问你网站的广大用户。
8. 社工
社会工程学,简称社工。百度定义,为某些非容易的获取讯息,利用社会科学(此指其中的社会常识)尤其心理学,语言学,欺诈学将其进行综合,有效的利用(如人性的弱点),并最终获得信息为最终目的学科称为“社会工程学”。
二、漏洞利用
了解了基础定义,还需要了解安全定义。
1. Cookie安全
Cookie是一小段文本信息,只能保存字符串,伴随着用户请求和页面在Web服务器和浏览器间传递,用来保持Web中的回话状态和缓存信息,记录用户的状态。Cookie的使用方便了人们的网上生活,但同时对用户的许多隐私信息构成了威胁。cookie在http协议中是明文传输的,并且直接附在http报文的前面,所以只要在网络中加个嗅探工具,获取http包,就可以分析并获得cookie的值。
当我们获取到别人的cookie的值,就产生了一种攻击漏洞,即cookie欺骗。我们将获取到的cookie值加在http请求前,服务器就会把我们当作是该cookie的用户,我们就成功的冒充了其他用户,可以使用其他用户在服务器的资源等。
Cookie欺骗是攻击者登录的是受害者的身份。而Cookie 注入是认证为攻击者的攻击方式,受害者登录的是攻击者的身份。
Cookie注入简单来说就是利用Cookie而发起的注入攻击。从本质上来讲,Cookie注入与一般的注入(例如,传统的SQL注入)并无不同,两者都是针对数据库的注入,只是表现形式上略有不同。Cookie 注入就是将提交的参数以cookie的方式提交。而一般的注入是使用get和post方式提交。Get方式提交就是直接在网址之后加需注入的内容,而post 是经过表单提取的方式。Post和get不同就在于,get方式我们可以在ie地址栏看到我们提交的参数,而post 不能。
Cookie 注入从技术手段来讲,比较有技术含量。如果只是简单的注入,例如,让受害者登录攻击者的邮箱,那么只要攻击者查看邮箱的信件就会发现异常,容易被发现。那么这种情况下,就需要进行精准的攻击。例如攻击”一个网页“中的一个组成界面,替换“一次http行为”中的某些阶段行为。精确攻击将在下文cookie惯性思维中细讲,这里不多做描述。精确攻击就很难被发现,极为隐蔽。
我们通常认为cookie服务器颁发的,所以很可能认为cookie是安全的。但是cookie是从客户端向服务器提交的,所以严格来说,服务器接收到的cookie很可能是来自第三方的。攻击者窃取了他人的cookie然后提交给主机的。我们如果能够进行复杂的验证,例如过滤等,就会有效降低cookie的威胁。但是这个验证,本身存在一定的技术困难。
2. Flash安全
跨站Flash也称为CrossSite Flash(XSF)问题,主要是使用ActionScript脚本产生的xss问题,主要有两种方式:加载第三方资源和与javascript通信引发。以下几个不安全的ActionScript函数,若是对这些控制不好的话就很容易产生安全问题。
Flash的安全性在flash的开发过程中很少人会注意到,除了flash引发的xss问题,flash引发的csrf问题,代码很简单,也很好利用的,重要是隐藏性比较好,还有一些在flash游戏中的破解问题等。
3. 钓鱼安全
钓鱼也是一种非常古老的攻击方式了,其实并不太算前端攻击。可毕竟是页面级别的攻击,我们也来一起聊一聊。我相信很多人会有这样的经历,QQ群里面有人发什么兼职啦、什么自己要去国外了房子车子甩卖了,详情在QQ空间里啦,之类的连接。打开之后发现一个QQ登录框,其实一看域名就知道不是QQ,不过做得非常像QQ登录,不明就里的用户们,就真的把用户名和密码输入了进去,结果没登录到QQ,用户名和密码却给人发过去了。
其实这种方式,在前端也有利用。
常见的钓鱼方式有:
- 黑客通过钓鱼网站设下陷阱,大量收集用户个人隐私信息,贩卖个人信息或敲诈用户;
- 黑客通过钓鱼网站收集、记录用户网上银行账号、密码,盗窃用户的网银资金;
- 黑客假冒网上购物、在线支付网站、欺骗用户直接将钱打入黑客账户;
- 通过假冒产品和广告宣传获取用户信任,骗取用户钱财;
- 恶意团购网站或购物网站,假借“限时抢购”、“秒杀”、“团购”等,让用户不假思索地提供个人信息和银行账号,这些黑心网站主可直接获取用户的个人资料和网银账号密码信息,进而获利。
下面,我们就来试试如果利用前端进行一次逼真的钓鱼。
首先,我们在xx空间里分享一篇文章,然后吸引别人去点击。
接着,我们在cheat.php这个网站上面,将跳转过来的源网页地址悄悄的进行修改。
于是,在用户访问了我们的欺骗网站后,之前的tab已经悄然发生了变化,我们将其悄悄的替换为了钓鱼的网站,欺骗用户输入用户名、密码等。
钓鱼网站,伪装成XX空间,让用户输入用户名与密码。
这种钓鱼方式比较有意思,重点在于我们比较难防住这种攻击,我们并不能将所有的页面链接都使用js打开。所以,要么就将外链跳转的连接改为当前页面跳转,要么就在页面unload的时候给用户加以提示,要么就将页面所有的跳转均改为window.open,在打开时,跟大多数钓鱼防治殊途同归的一点是,我们需要网民们的安全意识提高。
前端安全三大类:
Web前端安全主要包括跨站脚本(XSS)、跨站请求伪造(CSRF)、界面操作劫持这三大类。
4. 跨站脚本(XSS)
XSS(cross-site scripting跨域脚本攻击)攻击也是最常见的WEB攻击之一,其重点是“跨域”和“客户端执行”。
XSS发生在目标网站中目标用户的浏览器层面上,当用户浏览器渲染整个html文档的过程中出现了不被预期的脚本指令并执行时,XSS就会发生。
也可以通俗地总结XSS为:想尽一切办法将你的脚本内容在目标网站中目标用户的浏览器上解析执行即可。
输入x的值未经任何过滤就直接输出,可以提交:
http://www.a.com/xss/reflect.php?x=
服务器端解析时,echo就会完整地输出 到响应体中,然后浏览器解析执行触发。
攻击过程:
- 客户端收集用户数据(如留言、发布文章功能)
- 攻击者将留言内容写入了可执行的JavaScript代码
- 将上面的数据未经处理直接存入数据库
- 其他用户查看该网站,看了上面包含了可执行的JavaScript代码的文章和评论
其他用户就会在浏览器客户端执行攻击者注入的JavaScript代码
XSS有几种不同的分类办法,例如按照恶意输入的脚本是否在应用中存储,XSS被划分为“存储型XSS”和“反射型XSS”,如果按照是否和服务器有交互,又可以划分为“Server Side XSS”和“DOM based XSS”。
无论怎么分类,XSS漏洞始终是威胁用户的一个安全隐患。攻击者可以利用XSS漏洞来窃取包括用户身份信息在内的各种敏感信息、修改Web页面以欺骗用户,甚至控制受害者浏览器,或者和其他漏洞结合起来形成蠕虫攻击,等等。总之,关于XSS漏洞的利用,只有想不到没有做不到。
5. 跨站请求伪造(CSRF)
CSRF(cross-site request forgery),翻译为跨站请求伪造,与XSS非常相似,但XSS是利用用户对当前网站的信任来发起攻击,而CSRF是利用网站对用户的信任来发起攻击。
对于CSRF来说,它的请求有两个关键点:跨站点的请求与请求是伪造的。
跨站点请求的来源是其他站点,比如,目标网站的删除文章功能接收到来自恶意网站客户端(JavaScript、Flash、HTML等)发出的删除文章的请求,这个请求就是跨站点的请求,目标网站应该区分请求来源。
如果请求的发出不是用户的意愿,那么这个请求就是伪造的。
场景:
- 目标网站A:www.a.com
- 目标网站B:www.b.com
目标网站A上有一个删除文章的功能,通常是用户单击“删除链接”时才会删除文章,这个链接是www.a.com/blog/del?id=1,id代表不同的文章。
CSRF思路,步骤如下:
在恶意网站B上编写一个CSRF页面(www.b.com/csrf.htm),
考虑用代码:
- img src=http://www.a.com/blog/del?id=1/>
向目标网站A发出一个GET请求的方法。
然后欺骗已经登录目标网站A的用户访问www.b.com/csfr.htm页面,攻击发生。
这里攻击过程有三个关键点:跨域发出了一个GET请求、可以无JavaScript参与、请求是身份认证后的。
6. 界面操作劫持
有个词叫做防不胜防,我们在通过iframe使用别人提供的内容时,我们自己的页面也可能正在被不法分子放到他们精心构造的iframe或者frame当中,进行点击劫持攻击。
界面操作劫持是一种通过在可见输入控件上覆盖一层不可见的框(iframe),使得用户误以为在操作可见控件,而实际上操作行为被不可见框劫持,执行不可见框的恶意支持代码,从而导致用户在不知情的情况下被窃取敏感信息、篡改数据等。
下面是一个点击劫持的简单例子,clickjacking.htm代码如下:
嵌入的inner.htm代码如下:
- <input style=”width:100px;” value=”Login” type=”button” onclick=”alert(‘test’)”/>
攻击过程:
- 攻击者精心构造一个诱导用户点击的内容,比如Web页面小游戏
- 将我们的页面放入到iframe当中
- 利用z-index等CSS样式将这个iframe叠加到小游戏的垂直方向的正上方
- 把iframe设置为100%透明度
- 受害者访问到这个页面后,肉眼看到的是一个小游戏,如果受到诱导进行了点击的话,实际上点击到的却是iframe中的我们的页面
点击劫持的危害在于,攻击利用了受害者的用户身份,在其不知情的情况下进行一些操作。如果只是迫使用户关注某个账号的话,看上去仿佛还可以承受,但是如果是删除某个重要文件记录,或者窃取敏感信息,那么造成的危害可就难以承受了。
三、防御思路
在大局势下,安全总是相对的,不安全却是绝对的。
1. 关于Cookie防御
最佳的防御应该是优化网站本身,设置复杂而周全的规则策略使攻击者不能获取到有效信息,从而来堵住cookie漏洞,同时也经常给站点打补丁,进行分析。
- 清理cookie;
- 不在 Cookies 中存放敏感信息;
- 严格保护数据库不泄露,在数据库足够安全的情况下,即使产生cookie注入,cookie 注入的危害也会被极大的减小;
- 严格堵住脚本系统中可能提交盗取Cookies的代码,把好验证关;
- 使用Session和Cookies双重验证;
- 加防篡改验证码,加个登录随机验证码;
- 运用HSTS平台,对于特定的域名强制进行HTTPS访问;
2. 关于Flash防御
Flash的安全性在Flash的开发过程中很少人会注意到,除了Flash引发的xss问题,Flash引发的csrf问题,代码很简单,也很好利用的,重要是隐藏性比较好,还有一些在Flash游戏中的破解问题等。在Flash编程中如果需要通过参数接收外部传入的数据,一定要对数据进行严格的检查,这样才能保证其安全性。
3. 关于钓鱼防御
最好的防御措施之一就是尽可能地实施双因子身份认证。如果登录证书被盗用,攻击者在利用这些证书之前还需要第二个认证因素。这种措施无法阻止攻击者窃取登录凭证,但是能够有效地阻止攻击者成功利用这些获取到的凭证。
另一个重要的防御措施就是对用户进行安全培训。对用户进行培训能够加深用户对网络钓鱼技能的认知,以便识别钓鱼行为。此外,还能使安全团队从用户行为(可能被技术人员认为是理所当然的行为)中学习到有价值的见解。
例如,用户可能会习惯假设组织已经对电子邮件进行了过滤,以防止任何恶意邮件通过,但是这种假设是错误的。无论多么高质量的电子邮件保护措施,都可能会无法避免地“放过”一些恶意电子邮件。对于恶意网站也是如此。用户可能会理所当然地认为有保护措施已经对恶意网站进行了过滤,但是即便是最好的网页过滤工具也可能会漏过少数的恶意网站。一旦用户能够了解到,任何安全工具无法完全保障百分百地阻止所有的恶意电子邮件或站点,他们才有可能形成一种高度的责任感,来帮助维护组织的网络安全。此外,用户能够了解攻击者可以轻松地建立一个钓鱼网站也是非常重要的。
4. 关于XSS防御
防御XSS最佳的做法就是对数据进行严格的输出编码,使得攻击者提供的数据不再被浏览器认为是脚本而被误执行。例如<script>在进行HTML编码后变成了<script>,而这段数据就会被浏览器认为只是一段普通的字符串,而不会被当做脚本执行了。其他的防御措施,例如设置CSP HTTP Header、输入验证、开启浏览器XSS防御等等都是可选项,原因在于这些措施都存在被绕过的可能,并不能完全保证能防御XSS攻击。不过它们和输出编码却可以共同协作实施纵深防御策略。
5. 关于CSRF防御
CSRF攻击是攻击者利用用户的身份操作用户帐户的一种攻击方式,通常使用Anti CSRF Token来防御CSRF攻击,同时要注意Token的保密性和随机性。
- 可以使用对cookie的限制,进行解决CSRF攻击的问题,它可以让其他的网站无法拿到自己的cookie。主要是通过设置 sameSite: ‘strict’ 的方式进行。缺点:目前这样的方式,有那个兼容性的问题。
- 可以使用图形验证码的方式,进行对我们的接口进行验证,原理就是每次提交我们的接口的时候,我们还要提交自己的图形验证码进行验证。缺点:就是用户体验不够好!
- 使用token的方式,也就是说,每次我们进行接口请求的时候,我们要在自己的数据请求中携带一个token,然后服务端通过读取token,然后验证这个token。最终我们能够保证接口的安全性。缺点:在前后端分离的情况下,还是无法实时的更新。
- 使用referer的方式,进行验证你的接口请求地址的来源,如果这个来源是自己的客户端的地址,那么就可以继续操作相应的东西,如果这个来源不是自己的客户端的请求,直接拦截住。
6. 关于劫持防御
有多种防御措施都可以防止页面遭到点击劫持攻击,例如Frame Breaking方案。一个推荐的防御方案是,使用X-Frame-Options:DENY这个HTTP Header来明确的告知浏览器,不要把当前HTTP响应中的内容在HTML Frame中显示出来。
开发人员关注:
- 开发时要提防用户产生的内容,要对用户输入的信息进行层层检测;
- 要注意对用户的输出内容进行过滤(进行转义等);
- 重要的内容记得要加密传输(无论是利用https也好,自己加密也好);
- get请求与post请求,要严格遵守规范,不要混用,不要将一些危险的提交使用jsonp完成;
- 对于URL上携带的信息,要谨慎使用;
- 心中时刻记着,网站哪里可能有危险,加强安全意识。
维护人员关注:
- 永远不要相信客户端传来的任何信息,对这些信息都应先进行编码或过滤处理;
- 谨慎返回用户输入的信息;
- 使用黑名单和白名单处理(即“不允许哪些敏感信息”或“只允许哪些信息”,白名单的效果更好但局限性高);
- 检查、验证请求来源,对每一个重要的操作都进行重新验证;
- 使用SSL防止第三方监听通信(但无法阻止XSS、CSRF、SQL注入攻击);
- 不要将重要文件、备份文件存放在公众可访问到的地方;
- 会话ID无序化;
- 对用户上传的文件进行验证(不单单是格式验证,比方一张gif图片还应将其转为二进制并验证其每帧颜色值<无符号8位>和宽高值<无符号16位>);
- WSDL文档应当要求用户注册后才能获取;
- 在报头定义CSP(Content Security Policy)。