yuanyuanbyte / Blog

圆圆的博客,预计写七个系列:JavaScript深入系列、JavaScript专题系列、网络系列、Webpack系列、Vue系列、JavaScript基础系列、HTML&CSS应知应会系列。
306 stars 125 forks source link

网络安全系列之前端常见的 Web 安全攻防解析 #133

Open yuanyuanbyte opened 2 years ago

yuanyuanbyte commented 2 years ago

本系列的主题是网络安全,每期讲解一个技术要点。如果你还不了解各系列内容,文末点击查看全部文章,点我跳转到文末

如果觉得本系列不错,欢迎 Star,你的支持是我创作分享的最大动力。

常见的 Web 安全攻防解析,前端开发的你不来了解一下嘛~

随着互联网的高速发展,信息安全问题已经成为企业最为关注的焦点之一,而前端又是引发企业安全问题的高危据点。在移动互联网时代,前端人员除了传统的 XSS、CSRF 等安全问题之外,又时常遭遇网络劫持、非法调用 API 等新型安全问题。当然,浏览器自身也在不断在进化和发展,不断引入 CSP、Same-Site Cookies 等新技术来增强安全性,但是仍存在很多潜在的威胁,这需要前端技术人员不断进行“查漏补缺”。

在互联网时代,数据安全与个人隐私受到了前所未有的挑战,各种新奇的攻击技术层出不穷。如何才能更好地保护我们的数据?本文主要侧重于分析几种常见的攻击的类型以及防御的方法。

XSS

XSS 全称是 Cross Site Scripting(即跨站脚本攻击),是一种代码注入攻击。为了和 CSS 区分,故叫它XSS。攻击者通过在目标网站上注入恶意脚本,使之在用户的浏览器上运行。利用这些恶意脚本,攻击者可获取用户的敏感信息等,进而危害数据安全。

对用户造成的危害如:

XSS 的本质是:恶意代码未经过滤,与网站正常的代码混在一起;浏览器无法分辨哪些脚本是可信的,导致恶意脚本被执行。

XSS 攻击的三种方式

通常情况,XSS 攻击的实现有三种方式——反射型存储型DOM型

反射型 XSS(非持久型 XSS)

攻击者事先制作好攻击链接,需要诱导欺骗用户自己去点击链接才能触发XSS代码(服务器中没有这样的页面和内容),一般容易出现在搜索页面。

用户点击攻击链接将一段含有恶意代码的请求提交给 Web 服务器,Web 服务器接收到请求时,又将恶意代码反射给了浏览器端。用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。

反射型 XSS 漏洞常见于通过 URL 传递参数的功能,如网站搜索、跳转等。

由于需要用户主动打开恶意的 URL 才能生效,攻击者往往会结合多种手段诱导用户点击。

存储型 XSS(持久型 XSS)

储存型XSS会把用户输入的数据“储存”在服务器端。

它是最危险的一种跨站脚本,相比反射型XSS和DOM型XSS具有更高的隐蔽性,所以危害更大,因为它不需要用户手动触发。允许用户存储数据的web程序都可能存在存储型XSS漏洞,当攻击者提交一段XSS代码后,被服务器端接收并存储,当所有浏览者访问这个页面时都会被XSS攻击,这种攻击常见于带有用户保存数据的网站功能,如论坛发帖、评论、用户私信等。

DOM型 XSS

基于 DOM 的 XSS 攻击是不牵涉到页面 Web 服务器的。

在 Web 资源传输过程或者在用户使用页面的过程中修改 Web 页面的数据。

比如在数据传输过程劫持到网络数据包,然后修改里面的 html 文档!这样的劫持方式包括WIFI路由器劫持或者本地恶意软件等。

如何预防 XSS 攻击

利用 CSP

CSP 内容安全策略,它的核心思想就是服务器决定浏览器加载哪些资源。我们只需要配置规则,如何拦截是由浏览器自己实现的。

可以设置 HTTP Header 中的 Content-Security-Policy来开启 CSP

这里以设置 HTTP Header 来举例:

Content-Security-Policy: default-src 'self'
Content-Security-Policy: img-src https://*

通过CSP可以:

纯前端渲染

不采用服务端渲染,改成纯前端渲染,把代码和数据分隔开。

在纯前端渲染中,我们会明确的告诉浏览器:下面要设置的内容是文本(.innerText),还是属性(.setAttribute),还是样式(.style)等等。浏览器不会被轻易的被欺骗,执行预期外的代码了。

HttpOnly Cookie

这是预防XSS攻击窃取用户cookie最有效的防御手段。Web应用程序在设置cookie时,将其属性设为HttpOnly,浏览器会禁止页面的JS访问带有HttpOnly属性的Cookie。这样就可以避免该网页的cookie被客户端恶意JavaScript窃取,保护用户cookie信息。

CSRF

CSRF(Cross Site Request Forgery),即跨站请求伪造,是一种常见的Web攻击,它利用用户已登录的身份,在用户毫不知情的情况下,以用户的名义完成非法操作。

CSRF攻击的原理(建议详读下图)

在这里插入图片描述

从上图我们可以知道CSRF攻击的流程:

常见的 CSRF 攻击类型

自动发送 GET 请求的 CSRF

GET类型的CSRF利用非常简单,只需要一个HTTP请求,一般会这样利用:

<img src="http://bank.example/withdraw?amount=10000&for=hacker" > 

在用户访问含有这个img的页面后,浏览器会自动向http://bank.example/withdraw?account=xiaoming&amount=10000&for=hacker发出一次HTTP请求bank.example就会收到包含用户登录信息的一次跨域请求。

自动发送 POST 请求的 CSRF

这种类型的CSRF利用起来通常使用的是一个自动提交的表单,如:

 <form action="http://bank.example/withdraw" method=POST>
    <input type="hidden" name="account" value="xiaoming" />
    <input type="hidden" name="amount" value="10000" />
    <input type="hidden" name="for" value="hacker" />
</form>
<script> document.forms[0].submit(); </script> 

访问该页面后,表单会自动提交,相当于模拟用户完成了一次POST操作。

POST类型的攻击通常比GET要求更加严格一点,但仍并不复杂。任何个人网站、博客,被黑客上传页面的网站都有可能是发起攻击的来源,后端接口不能将安全寄托在仅允许POST上面。

诱导点击发送 GET 请求 的 CSRF

链接类型的CSRF并不常见,比起其他两种用户打开页面就中招的情况,这种需要用户点击链接才会触发。这种类型通常是在论坛中发布的图片中嵌入恶意链接,或者以广告的形式诱导用户中招,攻击者通常会以比较夸张的词语诱骗用户点击,例如:

  <a href="http://test.com/csrf/withdraw.php?amount=1000&for=hacker" taget="_blank">
  重磅消息!!
  <a/>

由于之前用户登录了信任的网站A,并且保存登录状态,只要用户主动访问上面的这个PHP页面,则表示攻击成功。

如何预防 CSRF 攻击

同源检测

既然 CSRF 攻击大多来自第三方网站,那么我们就直接禁止外域(或者不受信任的域名)对我们发起请求,从而阻止 CSRF 攻击。

那么问题来了,我们如何判断请求是否来自外域呢?利用 HTTP 请求头中的 Referer 和 Origin 属性。

在这里插入图片描述

优先判断 Origin,如果请求头中没有包含 Origin 属性,再根据实际情况判断是否使用 Referer 值。

这两个Header在浏览器发起请求时,大多数情况会自动带上,并且不能由前端自定义内容。

服务器可以通过解析这两个Header中的域名,确定请求的来源域。

CSRF Token

讲到CSRF的一个特征是,攻击者无法直接窃取到用户的信息(Cookie,Header,网站内容等),仅仅是冒用Cookie中的信息。

而CSRF攻击之所以能够成功,是因为服务器误把攻击者发送的请求当成了用户自己的请求。那么我们可以要求所有的用户请求都携带一个CSRF攻击者无法获取到的Token。服务器通过校验请求是否携带正确的Token,来把正常的请求和攻击的请求区分开,也可以防范CSRF的攻击。

利用Cookie的SameSite属性

CSRF攻击中重要的一环就是自动发送目标站点下的 Cookie,就是这一份 Cookie 模拟了用户的身份。为了从源头上解决这个问题,可以为Set-Cookie响应头设置Samesite属性,它用来标明这个 Cookie是个“同站 Cookie”。

Set-Cookie: foo=1; Samesite=Strict
Set-Cookie: bar=2; Samesite=Lax
Set-Cookie: baz=3

SameSite可以设置为三个值,StrictLaxNone

注意!!!

使用该方法的问题是Samesite的兼容性不是很好,现阶段除了从新版Chrome和Firefox支持以外,Safari以及iOS Safari都还不支持,现阶段看来暂时还不能普及。

而且,SamesiteCookie目前有一个致命的缺陷:不支持子域。例如,种在topic.a.com下的Cookie,并不能使用a.com下种植的SamesiteCookie。这就导致了当我们网站有多个子域名时,不能使用SamesiteCookie在主域名存储用户登录信息。每个子域名都需要用户重新登录一次。

总之,SamesiteCookie是一个可能替代同源验证的方案,但目前还并不成熟,其应用场景有待观望。

验证码

应用程序和用户进行交互过程中,特别是账户交易这种核心步骤,强制用户输入验证码,才能完成最终请求。在通常情况下,验证码够很好地遏制CSRF攻击。但增加验证码降低了用户的体验,网站不能给所有的操作都加上验证码。所以只能将验证码作为一种辅助手段,在关键业务点设置验证码。

参考

查看全部文章

博文系列目录

交流

各系列文章汇总:https://github.com/yuanyuanbyte/Blog

我是圆圆,一名深耕于前端开发的攻城狮。

weixin