前端的安全问题与防御策略

2,257 阅读6分钟

在前端的开发中,安全是我们必须要了解的一环,即使前端很难说有真正的安全,但是了解这些攻击有助于我们如何去规避问题,毕竟安全问题都是需要提前预防,而不能等到真正发生的时候才来解决。

ClickJacking(点击劫持)

1.什么是ClickJacking?

ClickJacking(点击劫持)是一种视觉上的欺骗手段。大概有两种方式,一是攻击者使用一个透明的iframe,覆盖在一个网页上,然后诱使用户在该页面上进行操作,此时用户将在不知情的情况下点击透明的iframe页面;二是攻击者使用一张图片覆盖在网页,遮挡网页原有位置的含义。

2.如何防御ClickJacking

对于第一种情况我们可以通过设置http响应头标记X-Frame-Option来防止点击劫持。

X-Frame-Options:X-Frame-Options HTTP 响应头是用来给浏览器指示允许一个页面可否在<frame>,<iframe>或者<object>中展现的标记。网站可以使用此功能,来确保自己网站的内容没有被嵌到别人的网站中去,也从而避免了点击劫持 (clickjacking) 的攻击。

标记值 说明
DENY 表示该页面不允许在 frame 中展示,即便是在相同域名的页面中嵌套也不允许。
SAMEORIGIN 表示该页面可以在相同域名页面的 frame 中展示。
ALLOW-FROM uri 表示该页面可以在指定来源的 frame 中展示。

除此之外我们还可以使用CSP(Content-Security-Policy)里的frame-ancestors或frame-src来指定页面允许嵌入哪些页面。

对于不使用X-Frame—Options或CSP,参考网上的解决方法,在打开页面的时候检查一下window.top和window.self是否相等来决定是否重定向。

if (window.self != window.top) {
    top.location.href = self.location.href
}

至于第二种情况使用图片遮挡网页原有位置的含义,这种站点本身就是一个恶意站点,而不是来自第三方的攻击,这里不做讨论。

CSRF(跨站伪造请求)

1.什么是CSRF?

CSRF(跨站伪造请求)全称为 Cross-site request forgery,CSRF是通过伪装成受信任用户的请求来利用受信任的网站。例如:一位用户在站点A登录了,并且站点A把信息存储在用户本地,之后当用户打开站点B,站点B的恶意代码窃取了这位用户在站点A的个人用户信息,就可以假装成这位用户去请求站点A。

2.如何防御CSRF

  • cookie不存储重要信息
  • cookie设置httpOnly,secure,此外path和domain尽量不使用默认值
  • cookie设置SameSite(这个属性还不是一个规范,不确定是否有用)
  • 服务端增加多重安全校验
  • 使用https协议或其他安全协议发送请求

XSS(跨站脚本攻击)

1.什么是XSS?

XSS(跨站脚本攻击)全称为Cross Site Scripting,为了和CSS文件(Cascading Style Sheets)区分,故称为XSS。XSS通过往Web页面插入恶意代码,当用户访问该页面时,执行嵌入的恶意代码,以此来达到恶意攻击用户的目的。

XSS攻击又分为存储型和反射型。

存储型:一般是指我们页面中表单提交的数据存在恶意代码被存储到数据库中。

反射型:需要欺骗用户自己去点击链接才能触发XSS代码

2.如何防御XSS

  • CSP(Content-Security-Policy)

CSP(Content-Security-Policy)允许站点管理者在指定的页面控制用户代理的资源。

设置CSP可以极大程度上提高页面安全,CSP允许我们设置一套非常完善的资源允许请求规则,在此只大概罗列几个。

标记值 说明
script-src 限制javascript 源。
style-src 限制层叠样式表文件源。
img-src 限制图片和图标源。
media-src 限制通过<audio> 或<video> 标签加载的媒体文件源。
  • SRI(Subresource Integrity)

在项目中我们可能会引入一些第三方的文件,因为文件在第三方的服务器里,理论上第三方是有可能篡改文件对使用第三方的文件的站点进行攻击。在这种情况下我们可以使用SRI来保证我们引入的文件不被篡改。

SRI(子资源完整性 Subresource Integrity )用于让浏览器检查所下载的来自第三方的资源(例如 CDN)未被恶意篡改。它使用哈希值检查确保第三方资源的完整性。只要开发者提供了被需下载资源的哈希值,浏览器就可以检查实际下载的文件是否与预期的哈希值匹配。

如何使用SRI?只需给 script 或 style 标签添加integrity属性即可。

<script crossorigin="anonymous" integrity="shaxxx-xxxxxx" src="xxx.com/xxx.js"></script>

要注意的是因为浏览器需要下载资源内容进行计算,所以如果引用第三方的文件需要第三方服务器支持跨域请求(CORS),客户端则需要加上crossorigin="anonymous"属性。

另外,我们还可以使用CSP设置require-sri-for强制页面请求js或css文件使用SRI。

  • X-XSS-Protection

X-XSS-Protection响应头是浏览器检测到页面存在XSS攻击时,设置浏览器的行为。通常默认值为1,检测到XSS攻击浏览器将会删除不安全的部分。

标记值 说明
0 禁止XSS过滤。
1 启用XSS过滤(通常浏览器是默认的)。 如果检测到跨站脚本攻击,浏览器将清除页面(删除不安全的部分)。
1; mode=block 启用XSS过滤。 如果检测到攻击,浏览器将不会清除页面,而是阻止页面加载。
1; report=<reporting-uri> 启用XSS过滤。 如果检测到跨站脚本攻击,浏览器将清除页面并使用CSP report-uri指令的功能发送违规报告。
  • 对提交的数据encode或过滤

在页面里提交的数据需要存储到数据库的场景下,我们需要对提交的数据进行encode或者某些特殊字符进行过滤,特别是某些数据我们需要用在src或href里使用的情况。

除此之外,富文本也是XSS经常发生的重灾区,对于富文本提交的数据是一定要进行过滤的。

总结

上文所述基本上是我们前端里常见的安全问题,其实对于前端来说很难有真正的安全所言,毕竟我们的代码都是明文跑在浏览器上。

而现在基本上不使用https协议的请求全部都是不安全的,对于页面上数据提交进行过滤校验也是常规操作,大部分场景我们都是使用浏览器的机制来帮助我们防御攻击,增加第三方攻击的成本。