[网络]带你了解前端安全问题

419 阅读8分钟

最近想重新系统地整理一下前端的知识,因此写了这个专栏。我会尽量写一些业务相关的小技巧和前端知识中的重点内容,核心思想。

前言

今天我们来了解前端相关的安全知识。网络安全是一个很大的话题,涉及的知识十分广阔。当一个程序的出现网络漏洞的时候,其实每个开发岗位(前端,后端,测试等)都或多或少的有一定的责任。因此在开发过程中,我们要尽可能地把自己负责范围内的工作做好。

同源策略

其实浏览器本身已经给我们带来了一个安全措施,就是【同源策略】。它是页面中最基础、最核心的安全策略。在浏览器中如果两个 URL 的协议、域名和端口都相同,我们就称这两个 URL 同源。浏览器默认只允许同源的页面相互访问资源和操作 DOM ,如果是非同源页面,浏览器会作出一连串的安全限制。

相信大多数的开发者都遇到过下图的情况,这就是同源策略的效果之一。

更多关于同源策略可以参考:developer.mozilla.org/zh-CN/docs/…

同源策略的“开放”

按理来说,同源策略确实很强大,已经足够保证我们的页面安全了。但在实际使用中,我们的业务场景往往需要获取不同源的文件,考虑到这个需求,同源策略其实是有“后门”的。

嵌入第三方资源

页面难免需要引用一些第三方资源。最常见的情况就是嵌入第三方的图片,以及从cdn获取自己的页面资源等,为了满足这种场景,同源策略为浏览器留了一个后门,开发者可以通过一些标签引用非同源的资源:

// 引用非同源CDN资源
<script src="http://cdn.xxx.xxx/xxx.js"></script>
// 引用非同源图片资源
<image src="http://xxx.xxx.xxx/xxx.png"/>

跨域资源共享(CORS)

除了页面资源以外,我们的页面还需要往非同源的服务器发送请求,常见场景是页面部署在域名A,服务部署在域名B。或者页面需要同时调用多个不同的服务器。在同源策略的限制下,XMLHttpRequest 或者 Fetch的请求是不允许发出的。

为了满足这个需要,同源策略留出了第2个后门——【跨域资源共享(CORS)】。

跨文档消息机制

同源策略原则上是不允许2个不同源的页面互相访问dom的,但我们业务场景中又经常出现子应用嵌套这种需求。因此同源策略留出了第三个后门——【跨文档消息机制】。

我们可以通过 window.postMessage 访问到不同源的 DOM 。

正是因为这些“后门”,导致出现了一连串的常见前端安全问题。

跨站脚本攻击(XSS)

跨站脚本攻击(Cross Site Scripting)是指黑客往 HTML 文件中或者 DOM 中注入恶意脚本,从而在用户浏览页面时利用注入的恶意脚本对用户实施攻击的一种手段。由于我们的浏览器是无法判断请求回来的页面资源是否安全的,因此假如我们请求的html被黑客篡改了,浏览器是不会感知的,会默认加载渲染。

<!DOCTYPE html>
<html>
	<head>
  	<link rel='stylesheet' href='/stylesheets/style.css' />
	</head>
	<body>
    <script src='http://xxx.xxx.xxx/xxx.js'></script> //黑客注入了一行
 		<div>hello world</div>
	</body>
</html>

如上方代码的情况,浏览器是会正常加载被注入的scirpt的,这样黑客就可以用javascript修改我们的页面了。

可能带来的问题

XSS通过在页面资源中注入代码可能会带来下列的问题:

  • 窃取浏览器本地信息:注入的JS代码 可以通过接口获取 Cookie ,local Storage,Session Storage等信息,然后通过 跨越请求把信息发送到自己的服务中就可以窃取用户信息了。
  • 监听用户行为:注入的 JS代码 可以监听键盘,鼠标等事件。可以记录用户的操作,甚至获得用户通过键盘输入的账号密码。
  • 生成诱导页面元素:注入代码可以通过修改页面DOM来生成一些伪造的登录窗口,用来欺骗用户输入用户名和密码等信息。
  • 生成浮窗广告:除了生成诱骗页面元素,还可以生成浮窗广告,严重地影响用户体验。

XSS的注入途径

想要我们开发的页面避免XSS攻击,首先得先知道XSS是怎么注入的。通常情况下,主要有存储型 XSS 攻击、反射型 XSS 攻击和基于 DOM 的 XSS 攻击三种方式来注入恶意脚本。

  • 存储型 XSS 攻击:指黑客通过把非法信息直接存储在服务器中,这样用户每次请求回来的资源其实都已经被修改了。
  • 反射型 XSS 攻击:指利用网页上的显示的信息,是请求的一部分的场景。在请求中加入非法字段,使页面加载渲染非法字段。
  • 基于DOM的XSS攻击:指不涉及服务器,在网络传输途中篡改页面资源的情况。如WiFi 路由器劫持,通过本地恶意软件劫持等。

防范XSS注入

知道了XSS的注入途径后,我们就可以尝试找办法防范了。

  • 服务器对请求入参过滤处理:服务器不应该过分信任请求的入参,可以在处理请求前,对请求体的内容作过滤处理,尤其是一些敏感字符(可以构建HTML标签的内容)。避免把这些内容存入数据库或者响应体中。
  • 充分利用 内容安全策略( CSP ): csp提供一个配置,让我们可以更精准地做安全策略。CSP内容可以看:developer.mozilla.org/zh-CN/docs/…
  • 使用 HttpOnly 属性: XSS很多时候是在想办法获取用户的cookie信息,那么我们可以考虑使用httpOnly来保护信息。设置了httpOnly的cookie只能在http请求中读取,不能通过js脚本读到。

跨站请求伪造(CSRF)

跨站请求伪造( Cross-site request forgery)是值黑客利用用户的已登录状态,通过第三方的站点来进行不法操作。与XSS有着本质的不同,XSS会想办法在页面资源中注入脚本获取用户信息。而CSRF则是想办法利用用户的登录状态。

操作途径

记住,CSRF的核心通过伪造网站,利用用户的登录状态。一旦用户误打开了黑客提供的url,CSRF就有可能发生。主要的操作方式主要有以下:

  • 自动发起 Get 请求: 通过image标签之类的同源策略后门,让浏览器自动发起get请求。由于用户已经处于该网站的登录状态,这个请求会默认带上用户信息。
  • 自动发起 POST 请求: 黑客可以通过写一个隐藏表单,利用表单的特性,自动发出post请求。
  • 引诱用户点击链接: 黑客通过页面的某个链接(a标签)上覆盖一些诱导信息(图片等),如果用户点了信息,就会触发下层链接请求。

防范CSRF

我们看过了CSRF的实现方式,现在来总结一下有哪些防范途径。

  • 利用Cookie 的 SameSite 属性: 与httpOnly一样,这是一个cookie的安全配置,可以限制第三方网站对cookie的操作。具体可以看:developer.mozilla.org/zh-CN/docs/…
  • 验证请求的来源站点: 换个思路,我们可以从服务端下手。利用HTTP请求头中的RefererOrigin属性为一些重要请求做限制。假如请求来源不安全就拒绝请求。referer会带有更多的请求信息,但开发者可以自行决定是否使用,而origin在通过 XMLHttpRequest、Fecth 发起跨站请求或者通过 Post 方法发请求时浏览器会默认带上,但信息量很少只有一个根域名。因此服务端比较稳妥的做法是先判断origin再判断referer。
  • CSRF Token: 服务器可以在首次请求页面时,在页面中加入一个判断标识(也就是CSRF Token),此后如果需要发重要请求则需要把CSRF token带上。这样黑客的伪造页面除了利用用户的登录状态以外,还需要拿到真正的CSRF token,这样就大大增加了不法操作的难度。

总结

今天我们了解了浏览器的同源策略,它为我们带来了很多的安全保护。但安全与自由是相对的,WEB的应用往往追求更开放,因此同源策略并不是绝对严格的,他为开发者留了一些“后门”。

正是因为这几个后门,黑客门发明了诸如XSS,CSRF等攻击方式。本文也带大家了解了这2种攻击方式的核心原理,操作方式。并提出了防范方式,希望对大家有所帮助。

当然除此以外,像https,浏览器本身的安全机制,还有一些本文没提到的安全知识,都是构建稳定web的重要角色,大家有兴趣的可以自行查阅。只是XSS和CSRF对前端来说更为重要,所以重点描述。

参考

《浏览器工作原理与实践》——李兵