常见前端安全问题及防护
常见前端安全问题及防护
一、xss与sql攻击
- xss-跨站脚本攻击(Cross-Site Scripting)
XSS是跨站脚本攻击(Cross-Site Scripting)的简称。XSS这类安全问题发生的本质原因在于:浏览器错误的将攻击者提供的用户输入数据当做JavaScript脚本给执行了。
XSS有几种不同的分类办法,例如按照恶意输入的脚本是否在应用中存储,XSS被划分为“存储型XSS”和“反射型XSS”,如果按照是否和服务器有交互,又可以划分为“Server Side XSS”和“DOM based XSS”。
无论怎么分类,XSS漏洞始终是威胁用户的一个安全隐患。攻击者可以利用XSS漏洞来窃取包括用户身份信息在内的各种敏感信息、修改Web页面以欺骗用户,甚至控制受害者浏览器,或者和其他漏洞结合起来形成蠕虫攻击,等等。总之,关于XSS漏洞的利用,只有想不到没有做不到。如何防御
对数据进行严格的输出编码,使得攻击者提供的数据不再被浏览器认为是脚本而被误执行。例如<script>在进行HTML编码后变成了<script>,这段数据就不会被当做脚本执行了。
需要根据输出数据所在的上下文来进行相应的编码。数据放置于HTML元素中,需进行HTML编码,放置于URL中,需要进行URL编码。此外,还有JavaScript编码、CSS编码、HTML属性编码、JSON编码等等。(一些主流前端开发框架基本上都默认提供了前端输出编码,这大大减轻了前端开发小伙伴们的工作负担)
其他的防御措施,例如设置CSP HTTP Header、输入验证、开启浏览器XSS防御等等都是可选项,原因在于这些措施都存在被绕过的可能,并不能完全保证能防御XSS攻击。不过它们和输出编码却可以共同协作实施纵深防御策略。二、csrf
- csrf
CSRF跨站点请求伪造(Cross—Site Request Forgery),跟XSS攻击一样,存在巨大的危害性,你可以这样来理解:
攻击者盗用了你的身份,以你的名义发送恶意请求,对服务器来说这个请求是完全合法的,但是却完成了攻击者所期望的一个操作,比如以你的名义发送邮件、发消息,盗取你的账号,添加系统管理员,甚至于购买商品、虚拟货币转账等。 如下:其中Web A为存在CSRF漏洞的网站,Web B为攻击者构建的恶意网站,User C为Web A网站的合法用户。
- CSRF攻击攻击原理及过程如下:
- 1.用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;
- 2.在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;
- 3.用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;
- 4.网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A;
- 5.浏览器在接收到这些攻击性代码后,根据网站 B 的请求,在用户不知情的情况下携带 Cookie 信息,向网站 A 发出请求。网站 A 并不知道该请求其实是由 B 发起的,所以会根据用户 C 的 Cookie 信息以 C 的权限处理该请求,导致来自网站 B 的恶意代码被执行。
- CSRF漏洞检测:
检测CSRF漏洞是一项比较繁琐的工作,最简单的方法就是抓取一个正常请求的数据包,去掉Referer字段后再重新提交,如果该提交还有效,那么基本上可以确定存在CSRF漏洞。
随着对CSRF漏洞研究的不断深入,不断涌现出一些专门针对CSRF漏洞进行检测的工具,如CSRFTester,CSRF Request Builder等。
以CSRFTester工具为例,CSRF漏洞检测工具的测试原理如下:使用CSRFTester进行测试时,首先需要抓取我们在浏览器中访问过的所有链接以及所有的表单等信息,然后通过在CSRFTester中修改相应的表单等信息,重新提交,这相当于一次伪造客户端请求。如果修改后的测试请求成功被网站服务器接受,则说明存在CSRF漏洞,当然此款工具也可以被用来进行CSRF攻击。
防御CSRF攻击:
目前防御 CSRF 攻击主要有三种策略:
- 验证 HTTP Referer 字段;
- 在请求地址中添加 token 并验证;
- 在 HTTP 头中自定义属性并验证。
- 验证 HTTP Referer 字段
根据 HTTP 协议,在 HTTP 头中有一个字段叫 Referer,它记录了该 HTTP 请求的来源地址。在通常情况下,访问一个安全受限页面的请求来自于同一个网站,比如需要访问 http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory,用户必须先登陆 bank.example,然后通过点击页面上的按钮来触发转账事件。这时,该转帐请求的 Referer 值就会是转账按钮所在的页面的 URL,通常是以 bank.example 域名开头的地址。而如果黑客要对银行网站实施 CSRF 攻击,他只能在他自己的网站构造请求,当用户通过黑客的网站发送请求到银行时,该请求的 Referer 是指向黑客自己的网站。因此,要防御 CSRF 攻击,银行网站只需要对于每一个转账请求验证其 Referer 值,如果是以 bank.example 开头的域名,则说明该请求是来自银行网站自己的请求,是合法的。如果 Referer 是其他网站的话,则有可能是黑客的 CSRF 攻击,拒绝该请求。
这种方法的显而易见的好处就是简单易行,网站的普通开发人员不需要操心 CSRF 的漏洞,只需要在最后给所有安全敏感的请求统一增加一个拦截器来检查 Referer 的值就可以。特别是对于当前现有的系统,不需要改变当前系统的任何已有代码和逻辑,没有风险,非常便捷。
然而,这种方法并非万无一失。Referer 的值是由浏览器提供的,虽然 HTTP 协议上有明确的要求,但是每个浏览器对于 Referer 的具体实现可能有差别,并不能保证浏览器自身没有安全漏洞。使用验证 Referer 值的方法,就是把安全性都依赖于第三方(即浏览器)来保障,从理论上来讲,这样并不安全。事实上,对于某些浏览器,比如 IE6 或 FF2,目前已经有一些方法可以篡改 Referer 值。如果 bank.example 网站支持 IE6 浏览器,黑客完全可以把用户浏览器的 Referer 值设为以 bank.example 域名开头的地址,这样就可以通过验证,从而进行 CSRF 攻击。
即便是使用最新的浏览器,黑客无法篡改 Referer 值,这种方法仍然有问题。因为 Referer 值会记录下用户的访问来源,有些用户认为这样会侵犯到他们自己的隐私权,特别是有些组织担心 Referer 值会把组织内网中的某些信息泄露到外网中。因此,用户自己可以设置浏览器使其在发送请求时不再提供 Referer。当他们正常访问银行网站时,网站会因为请求没有 Referer 值而认为是 CSRF 攻击,拒绝合法用户的访问。
- 在请求地址中添加 token 并验证
CSRF 攻击之所以能够成功,是因为黑客可以完全伪造用户的请求,该请求中所有的用户验证信息都是存在于 cookie 中,因此黑客可以在不知道这些验证信息的情况下直接利用用户自己的 cookie 来通过安全验证。要抵御 CSRF,关键在于在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中。可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。
这种方法要比检查 Referer 要安全一些,token 可以在用户登陆后产生并放于 session 之中,然后在每次请求时把 token 从 session 中拿出,与请求中的 token 进行比对,但这种方法的难点在于如何把 token 以参数的形式加入请求。对于 GET 请求,token 将附在请求地址之后,这样 URL 就变成 http://url?csrftoken=tokenvalue。 而对于 POST 请求来说,要在 form 的最后加上 ,这样就把 token 以参数的形式加入请求了。但是,在一个网站中,可以接受请求的地方非常多,要对于每一个请求都加上 token 是很麻烦的,并且很容易漏掉,通常使用的方法就是在每次页面加载时,使用 javascript 遍历整个 dom 树,对于 dom 中所有的 a 和 form 标签后加入 token。这样可以解决大部分的请求,但是对于在页面加载之后动态生成的 html 代码,这种方法就没有作用,还需要程序员在编码时手动添加 token。
该方法还有一个缺点是难以保证 token 本身的安全。特别是在一些论坛之类支持用户自己发表内容的网站,黑客可以在上面发布自己个人网站的地址。由于系统也会在这个地址后面加上 token,黑客可以在自己的网站上得到这个 token,并马上就可以发动 CSRF 攻击。为了避免这一点,系统可以在添加 token 的时候增加一个判断,如果这个链接是链到自己本站的,就在后面添加 token,如果是通向外网则不加。不过,即使这个 csrftoken 不以参数的形式附加在请求之中,黑客的网站也同样可以通过 Referer 来得到这个 token 值以发动 CSRF 攻击。这也是一些用户喜欢手动关闭浏览器 Referer 功能的原因。
- 在 HTTP 头中自定义属性并验证
这种方法也是使用 token 并进行验证,和上一种方法不同的是,这里并不是把 token 以参数的形式置于 HTTP 请求之中,而是把它放到 HTTP 头中自定义的属性里。通过 XMLHttpRequest 这个类,可以一次性给所有该类请求加上 csrftoken 这个 HTTP 头属性,并把 token 值放入其中。这样解决了上种方法在请求中加入 token 的不便,同时,通过 XMLHttpRequest 请求的地址不会被记录到浏览器的地址栏,也不用担心 token 会透过 Referer 泄露到其他网站中去。
然而这种方法的局限性非常大。XMLHttpRequest 请求通常用于 Ajax 方法中对于页面局部的异步刷新,并非所有的请求都适合用这个类来发起,而且通过该类请求得到的页面不能被浏览器所记录下,从而进行前进,后退,刷新,收藏等操作,给用户带来不便。另外,对于没有进行 CSRF 防护的遗留系统来说,要采用这种方法来进行防护,要把所有请求都改为 XMLHttpRequest 请求,这样几乎是要重写整个网站,这代价无疑是不能接受的。
三、请求劫持与HTTPS
1.请求劫持
现在主要分为两种,DNS劫持与HTTP劫持:
- DNS劫持
DNS劫持就是通过劫持了DNS服务器,通过某些手段取得某域名的解析记录控制权,进而修改此域名的解析结果,导致对该域名的访问由原IP地址转入到修改后的指定IP,其结果就是对特定的网址不能访问或访问的是假网址,从而实现窃取资料或者破坏原有正常服务的目的。
DNS劫持通过篡改DNS服务器上的数据返回给用户一个错误的查询结果来实现的。
DNS劫持症状:在某些地区的用户在成功连接宽带后,首次打开任何页面都指向ISP提供的“电信互联星空”、“网通黄页广告”等内容页面。还有就是曾经出现过用户访问Google域名的时候出现了百度的网站。这些都属于DNS劫持。 再说简单点,当你输入google.com这个网址的时候,你看到的网站却是百度的首页。- http劫持
在用户的客户端与其要访问的服务器经过网络协议协调后,二者之间建立了一条专用的数据通道,用户端程序在系统中开放指定网络端口用于接收数据报文,服务器端将全部数据按指定网络协议规则进行分解打包,形成连续数据报文。用户端接收到全部报文后,按照协议标准来解包组合获得完整的网络数据。其中传输过程中的每一个数据包都有特定的标签,表示其来源、携带的数据属性以及要到何处,所有的数据包经过网络路径中ISP的路由器传输接力后,最终到达目的地,也就是客户端。
HTTP劫持是在使用者与其目的网络服务所建立的专用数据通道中,监视特定数据信息,提示当满足设定的条件时,就会在正常的数据流中插入精心设计的网络数据报文,目的是让用户端程序解释“错误”的数据,并以弹出新窗口的形式在使用者界面展示宣传性广告或者直接显示某网站的内容。列入本地的fiddler为一种劫持如何防御
请求劫持唯一可行的预防方法就是尽量使用HTTPS协议访问。2.公钥和私钥
-
https 简单理解就是通过SSL(Secure Sockets Layer)层来加密http数据来进行安全传输。 那使用HTTPS是怎样进行加解密和安全数据传输的?
-
先看个有意思的问题:
A、B两个人分别在两个岛上,并且分别有一个箱子,一把锁,和打开这把锁的钥匙(A的钥匙打不开B手上的锁,B的钥匙也打不开A的锁)。此时A要跟B互通情报,此时需要借助C的船运输,C是一个不可靠的人,如果A直接把情报送给B或把情报放在箱子里给B,都可能会被C偷走;如果A把情报锁在箱子里,B没有打开A锁的钥匙无法获得情报内容。请问有什么办法可以尽可能快的让A和B互通情报。
这就是公钥和私钥的问题了,答案比较简单,也对应了公钥和私钥在https中的应用过程。
公钥(Public Key)与私钥(Private Key)是通过一种算法得到的一个密钥对(即一个公钥和一个私钥),公钥是密钥对中公开的部分,私钥则是非公开的部分。公钥通常用于加密会话密钥、验证数字签名,或加密可以用相应的私钥解密的数据。通过这种算法得到的密钥对能保证在世界范围内是唯一的。使用这个密钥对的时候,如果用其中一个密钥加密一段数据,必须用另一个密钥解密。比如用公钥加密数据就必须用私钥解密,如果用私钥加密也必须用公钥解密,否则解密将不会成功。---百度百科
3.Https的通信过程
- 1、客户端发送https请求,告诉服务器端将建立https连接
- 2、服务器将服务端生成的公钥返回给客户端,如果是第一次请求将告诉客户端需要验证链接
- 3、客户端接收到请求后’client finished’报文串通过获取到的服务器公钥加密发送给服务器,并将客户端生成的公钥也发送给服务器
- 4、服务器获取到加密的报文和客户端公钥,先使用服务器私钥解密报文,然后将报文通过客户端的公钥加密返回给客户端。
- 5、客户端通过私钥解密报文,判断是否为自己开始发送的报文串;如果正确,说明安全连接验证成功,将数据通过服务器公钥加密不断发送给服务器,服务器也不断解密获取报文,并通过客户端公钥加密返回给客户端验证。这样就建立了不断通信的连接。
四、浏览器web安全控制
http层面上浏览器设置的安全性控制较多,这里列几个典型的来看看:
- X-XSS-Protection
这个header主要是用来防止浏览器中的反射性xss。现在,只有IE,chrome和safari(webkit)支持这个header。
正确的设置:
X-XSS-Protection:1; mode=block 0 – 关闭对浏览器的xss防护 1 – 开启xss防护 mode=block – 开启xss防护并通知浏览器阻止而不是过滤用户注入的脚本 report=http://site.com/report – 这个只有chrome和webkit内核的浏览器支持,这种模式告诉浏览器当发现疑似xss攻击的时候就将这部分数据post到指定地址- X-Content-Type-Options
这个header主要用来防止在IE9、chrome和safari中的MIME类型混淆攻击。firefox目前对此还存在争议。通常浏览器可以通过嗅探内容本身的方法来决定它是什么类型,而不是看响应中的content-type值。通过设置 X-Content-Type-Options:如果content-type和期望的类型匹配,则不需要嗅探,只能从外部加载确定类型的资源。举个例子,如果加载了一个样式表,那么资源的MIME类型只能是text/css,对于IE中的脚本资源,以下的内容类型是有效的:
application/ecmascript application/javascript application/x-javascript text/ecmascript text/javascript text/jscript text/x-javascript text/vbs text/vbscript对于chrome,则支持下面的MIME 类型:
text/javascript text/ecmascript application/javascript application/ecmascript application/x-javascript text/javascript1.1 text/javascript1.2 text/javascript1.3 text/jscript text/live scriptnosniff – 这个是唯一正确的设置,必须这样。
- Strict-Transport-Security
Strict Transport Security (STS) 是用来配置浏览器和服务器之间安全的通信。它主要是用来防止中间人攻击,因为它强制所有的通信都走TLS。目前IE还不支持 STS头。需要注意的是,在普通的http请求中配置STS是没有作用的,因为攻击者很容易就能更改这些值。为了防止这样的现象发生,很多浏览器内置了一个配置了STS的站点list。
正确的设置: 注意下面的值必须在https中才有效,如果是在http中配置会没有效果。
max-age=31536000 – 告诉浏览器将域名缓存到STS list里面,时间是一年。 max-age=31536000; includeSubDomains – 告诉浏览器将域名缓存到STS list里面并且包含所有的子域名,时间是一年。max-age=0 – 告诉浏览器移除在STS缓存里的域名,或者不保存此域名判断一个主机是否在你的STS缓存中,chrome可以通过访问chrome://net-internals/#hsts,首先,通过域名请求选项来确认此域名是否在你的STS缓存中。然后,通过https访问这个网站,尝试再次请求返回的STS头,来决定是否添加正确。
- Content-Security-Policy
CSP是一种由开发者定义的安全性政策性申明,通过CSP所约束的的规责指定可信的内容来源(这里的内容可以指脚本、图片、iframe、fton、style等等可能的远程的资源)。通过CSP协定,让WEB能够加载指定安全域名下的资源文件,保证运行时处于一个安全的运行环境中。
正确配置
Content-Security-Policy:default-src *; base-uri 'self'; block-all-mixed-content; child-src 'self' render.githubusercontent.com; connect-src 'self' uploads.github.com status.github.com api.github.com www.google-analytics.com github-cloud.s3.amazonaws.com wss://live.github.com; font-src assets-cdn.github.com; form-action 'self' github.com gist.github.com; frame-src 'self' render.githubusercontent.com; img-src 'self' data: assets-cdn.github.com identicons.github.com www.google-analytics.com collector.githubapp.com *.gravatar.com *.wp.com *.githubusercontent.com; media-src 'none'; object-src assets-cdn.github.com; plugin-types application/x-shockwave-flash; script-src assets-cdn.github.com; style-src 'self' 'unsafe-inline' assets-cdn.github.com- X-Frame-Options
这个header主要用来配置哪些网站可以通过frame来加载资源。它主要是用来防止UI redressing 补偿样式攻击。IE8和firefox 18以后的版本都开始支持ALLOW-FROM。chrome和safari都不支持ALLOW-FROM,但是WebKit已经在研究这个了。
正确的设置
X-Frame-Options: deny deny – 禁止所有的资源(本地或远程)试图通过frame来加载其他也支持X-Frame-Options 的资源。sameorigion – 只允许遵守同源策略的资源(和站点同源)通过frame加载那些受保护的资源。 allow-from http://www.example.com – 允许指定的资源(必须带上协议http或者https)通过frame来加载受保护的资源。这个配置只在IE和firefox下面有效。其他浏览器则默认允许任何源的资源(在X-Frame-Options没设置的情况下)。- Access-Control-Allow-Origin
Access-Control-Allow-Origin是从Cross Origin Resource Sharing (CORS)中分离出来的。这个header是决定哪些网站可以访问资源,通过定义一个通配符来决定是单一的网站还是所有网站可以访问我们的资源。需要注意的是,如果定义了通配符,那么 Access-Control-Allow-Credentials选项就无效了,而且user-agent的cookies不会在请求里发送。
正确的设置
Access-Control-Allow-Origin : * *– 通配符允许任何远程资源来访问含有Access-Control-Allow-Origin 的内容。 http://www.example.com – 只允许特定站点才能访问(http://[host], 或者 https://[host])7.Public-Key-Pins
公钥固定(Public Key Pinning)是指一个证书链中必须包含一个白名单中的公钥,也就是说只有被列入白名单的证书签发机构(CA)才能为某个域名*.example.com签发证书,而不是你的浏览器中所存储的任何 CA 都可以为之签发。可以理解为https的证书域名白名单。 ??Public-Key-Pins (PKP)的目的主要是允许网站经营者提供一个哈希过的公共密钥存储在用户的浏览器缓存里。跟Strict-Transport-Security功能相似的是,它能保护用户免遭中间人攻击。这个header可能包含多层的哈希运算,比如pin-sha256=base64(sha256(SPKI)),具体是先将 X.509 证书下的Subject Public Key Info (SPKI) 做sha256哈希运算,然后再做base64编码。然而,这些规定有可能更改,例如有人指出,在引号中封装哈希是无效的,而且在33版本的chrome中也不会保存pkp的哈希到缓存中。
这个header和 STS的作用很像,因为它规定了最大子域名的数量。此外,pkp还提供了一个Public-Key-Pins-Report-Only 头用来报告异常,但是不会强制阻塞证书信息。当然,这些chrome都是不支持的。
五、使用iframe的风险
有时前端页面需要用到第三方提供的页面组件,通常会以iframe的方式引入。典型的例子是使用iframe在页面上添加第三方提供的广告、天气预报、社交分享插件等等。
iframe在给我们的页面带来更多丰富的内容和能力的同时,也带来了不少的安全隐患。因为iframe中的内容是由第三方来提供的,默认情况下他们不受我们的控制,他们可以在iframe中运行JavaScirpt脚本、Flash插件、弹出对话框等等,这可能会破坏前端用户体验。
如果说iframe只是有可能会给用户体验带来影响,看似风险不大,那么如果iframe中的域名因为过期而被恶意攻击者抢注,或者第三方被黑客攻破,iframe中的内容被替换掉了,从而利用用户浏览器中的安全漏洞下载安装木马、恶意勒索软件等等,这问题可就大了。如何防御
在HTML5中,iframe有个sandbox安全属性,通过它可以对iframe的行为进行各种限制,充分实现“最小权限“原则。例如: <iframe sandbox src="..."> ... </iframe>
sandbox提供了丰富的配置参数,可以进行较为细粒度的控制。 allow-forms:允许iframe中提交form表单 allow-popups:允许iframe中弹出新的窗口或者标签页(例如,window.open(),showModalDialog(),target=”_blank”等等) allow-scripts:允许iframe中执行JavaScript allow-same-origin:允许iframe中的网页开启同源策略更多详细的资料,可以参考iframe中关于sandbox的介绍。六、点击劫持
这是一种欺骗性比较强,同时也需要用户高度参与才能完成的一种攻击。通常的攻击步骤是这样的: 1、攻击者构造一个诱导用户点击的内容,如Web页面小游戏 2、将被攻击的页面放入到iframe当中 3、利用z-index等CSS样式将这个iframe叠加到小游戏的垂直方向的正上方 4、把iframe设置为100%透明度 5、受害者访问这个页面,肉眼看到的是一个小游戏,如果受到诱导进行了点击的话,实际上点击到的却是iframe中的页面
点击劫持的危害在于,攻击利用了受害者的用户身份,在其不知情的情况下进行一些操作如何防御
尽量减少第三方依赖,选用相对成熟的依赖包。
使用自动化工具检查这些第三方代码有没有安全问题,比如NSP(Node Security Platform),Snyk等等。七、错误的内容推断
攻击场景:某网站允许用户在评论里上传图片,攻击者将含有恶意JavaScript的脚本文件扩展名改成图片格式进行上传(这涉及到了恶意文件上传这个常见安全问题,但是由于和前端相关度不高因此暂不详细介绍)。接下来,受害者在访问这段评论的时候,浏览器会去请求这个伪装成图片的JavaScript脚本,而此时如果浏览器错误的推断了这个响应的内容类型(MIME types),那么就会把这个图片文件当做JavaScript脚本执行,于是攻击也就成功了。
问题的关键:后端服务器在返回的响应中设置的Content-Type Header仅仅只是给浏览器提供当前响应内容类型的建议,而浏览器有可能会自作主张的根据响应中的实际内容去推断内容的类型。
上例中,后端通过Content-Type Header建议浏览器按图片来渲染HTTP响应,但浏览器发现响应的其实是JavaScript,于是就擅自做主把这段响应当做JS脚本来解释执行,安全问题也就产生了。如何防御
浏览器根据响应内容来推断其类型,本来这是个很“智能”的功能,是浏览器强大的容错能力的体现,但是却会带来安全风险。要避免出现这样的安全问题,办法就是通过设置X-Content-Type-Options这个HTTP Header明确禁止浏览器去推断响应类型。
同样是上面的攻击场景,后端服务器返回的Content-Type建议浏览器按照图片进行内容渲染,浏览器发现有X-Content-Type-Options HTTP Header的存在,并且其参数值是nosniff,因此不会再去推断内容类型,而是强制按照图片进行渲染,从而最终防止了安全问题的发生。
更多关于X-Content-Type-Options的细节请参考:https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options八、不安全的第三方依赖包
现如今进行应用开发,无论是后端服务器应用还是前端应用开发,绝大多数时候我们都是在借助开发框架和各种类库进行快速开发。
这样做的好处显而易见,但是与此同时安全风险也在不断累积——应用使用了如此多的第三方代码,不论应用自己的代码的安全性有多高,一旦这些来自第三方的代码有安全漏洞,那么对应用整体的安全性依然会造成严峻的挑战。如何防御
尽量减少第三方依赖,选用相对成熟的依赖包。
使用自动化工具检查这些第三方代码有没有安全问题,比如NSP(Node Security Platform),Snyk等等。九、HTTPS中间人攻击
即使是服务器端开启了HTTPS,也还是存在安全隐患,黑客可以利用SSL Stripping这种攻击手段,强制让HTTPS降级回HTTP,从而继续进行中间人攻击。
问题的本质在于浏览器发出去第一次请求就被攻击者拦截了下来并做了修改,根本不给浏览器和服务器进行HTTPS通信的机会。大致过程如下,用户在浏览器里输入URL的时候往往不是从https://开始的,而是直接从域名开始输入,随后浏览器向服务器发起HTTP通信,然而由于攻击者的存在,它把服务器端返回的跳转到HTTPS页面的响应拦截了,并且代替客户端和服务器端进行后续的通信。由于这一切都是暗中进行的,所以使用前端应用的用户对此毫无察觉。如何防御
解决这个安全问题的办法是使用HSTS(HTTP Strict Transport Security),它通过下面这个HTTP Header以及一个预加载的清单,来告知浏览器在和网站进行通信的时候强制性的使用HTTPS,而不是通过明文的HTTP进行通信: Strict-Transport-Security: max-age=; includeSubDomains; preload
这里的“强制性”表现为浏览器无论在何种情况下都直接向服务器端发起HTTPS请求,而不再像以往那样从HTTP跳转到HTTPS。另外,当遇到证书或者链接不安全的时候,则首先警告用户,并且不再让用户选择是否继续进行不安全的通信。十、本地存储数据泄露
随着前后端分离,尤其是后端服务无状态化架构风格的兴起,随着SPA应用大量出现,存储在前端数据量也在逐渐增多。
前端应用是完全暴露在用户以及攻击者面前的,在前端存储任何敏感、机密的数据,都会面临泄露的风险,就算是在前端通过JS脚本对数据进行加密基本也无济于事。
尽管有浏览器的同源策略限制,但是如果前端应用有XSS漏洞,那么本地存储的所有数据就都可能被攻击者的JS脚本读取到。如果用户在公用电脑上使用了这个前端应用,那么当用户离开后,这些数据是否也被彻底清除了呢?前端对数据加密后再存储看上去是个防御办法,但其实仅仅提高了一点攻击门槛而已,因为加密所用到的密钥同样存储在前端,有耐心的攻击者依然可以攻破加密这道关卡。如何防御
在前端存储敏感、机密信息始终都是一件危险的事情,推荐的做法是尽可能不在前端存这些数据十一、CDN劫持/污染
以出于性能考虑,前端应用通常会把一些静态资源存放到CDN上,再提高前端应用的访问速度的同时也隐含了一个新的安全风险。
如果攻击者劫持了CDN,或者对CDN中的资源进行了污染,那么我们的前端应用拿到的就是有问题的JS脚本或者Stylesheet文件。这种攻击方式造成的效果和XSS跨站脚本攻击相似。如何防御
防御这种攻击的办法是使用浏览器提供的SRI(Subresource Integrity)功能。
每个资源文件都有一个SRI值。由两部分组成,减号(-)左侧是生成SRI值用到的哈希算法名,右侧是经过Base64编码后的该资源文件的Hash值。<script src="“https://example.js”" integrity="“sha384-eivAQsRgJIi2KsTdSnfoEGIRTo25NCAqjNJNZalV63WKX3Y51adIzLT4So1pk5tX”"/>
浏览器在处理这个script元素的时候,就会检查对应的JS脚本文件的完整性,看其是否和script元素中integrity属性指定的SRI值一致,如果不匹配,浏览器则会中止对这个JS脚本的处理。参考地址
https://www.cnblogs.com/AdamFamily/p/10059253.html
https://cloud.tencent.com/developer/article/1008829
https://blog.csdn.net/weixin_41088946/article/details/107101049
支持与分享
如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!












