年终前端安全防护规范总结

2,296 阅读15分钟

背景与意义

  • 建了一个“全栈大前端”的微信交流群,欢迎纯粹技术交流爱好者加入!(入群加微信mokinzhao)

随着互联网的发展,各种 Web 应用变得越来越复杂,满足了用户的各种需求的同时,各种网络安全问题也接踵而至,

QQ 邮箱、新浪微博、YouTube、WordPress 和 百度 等知名网站都曾遭遇攻击,如果你从未有过安全方面的问题,不是因为你所开发的网站很安全,更大的可能是你的网站的流量非常低或者没有攻击的价值。要想作为一个优秀的前端工程师对安全防护知识的了解和掌握是必不可少的。

常见的安全漏洞

1.XSS 跨站脚本攻击

XSS(Cross-Site Scripting,跨站脚本攻击)是一种代码注入攻击。攻击者在目标网站上注入恶意代码,当被攻击者登陆网站时就会执行这些恶意代码,这些脚本可以读取 cookie,session tokens,或者其它敏感的网站信息,对用户进行钓鱼欺诈,甚至发起蠕虫攻击等。

XSS 的本质是:恶意代码未经过滤,与网站正常的代码混在一起;浏览器无法分辨哪些脚本是可信的,导致恶意脚本被执行。由于直接在用户的终端执行,恶意代码能够直接获取用户的信息,利用这些信息冒充用户向网站发起攻击者定义的请求。

  • XSS 分类

1.反射型 XSS(非持久)

当用户点击一个恶意链接,或者提交一个表单,或者进入一个恶意网站时,注入脚本进入被攻击者的网站。Web服务器将注入脚本,比如一个错误信息,搜索结果等,未进行过滤直接返回到用户的浏览器上。

反射型 XSS 的攻击步骤:

  1. 攻击者构造出特殊的 URL,其中包含恶意代码。
  2. 用户打开带有恶意代码的 URL 时,网站服务端将恶意代码从 URL 中取出,拼接在 HTML 中返回给浏览器。
  3. 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
  4. 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。

反射型 XSS 漏洞常见于通过 URL 传递参数的功能,如网站搜索、跳转等。由于需要用户主动打开恶意的 URL 才能生效,攻击者往往会结合多种手段诱导用户点击。

POST 的内容也可以触发反射型 XSS,只不过其触发条件比较苛刻(需要构造表单提交页面,并引导用户点击),所以非常少见。

查看反射型攻击示例

请戳: github.com/YvetteLau/B…

根据 README.md 的提示进行操作(真实情况下是需要诱导用户点击的,上述代码仅是用作演示)。

注意 Chrome 和 Safari 能够检测到 url 上的xss攻击,将网页拦截掉,但是其它浏览器不行,如 Firefox

如果不希望被前端拿到cookie,后端可以设置 httpOnly (不过这不是 XSS攻击 的解决方案,只能降低受损范围)

如何防范反射型XSS攻击

对字符串进行编码。

对url的查询参数进行转义后再输出到页面。

app.get('/welcome', function(req, res) {
   //对查询参数进行编码,避免反射型 XSS攻击
    res.send(`${encodeURIComponent(req.query.type)}`); 
});

2.存储型 XSS(持久)

DOM 型 XSS 攻击,实际上就是前端 JavaScript 代码不够严谨,把不可信的内容插入到了页面。在使用 .innerHTML、 .outerHTML、 .appendChild、 document.write()等API时要特别小心,不要把不可信的数据作为 HTML 插到页面上,尽量使用 .innerText、 .textContent、 .setAttribute() 等。

DOM 型 XSS 的攻击步骤:

  1. 攻击者构造出特殊数据,其中包含恶意代码。
  2. 用户浏览器执行了恶意代码。
  3. 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。

如何防范 DOM 型 XSS 攻击

防范 DOM 型 XSS 攻击的核心就是对输入内容进行转义(DOM 中的内联事件监听器和链接跳转都能把字符串作为代码运行,需要对其内容进行检查)。

1.对于 url链接(例如图片的 src属性),那么直接使用 encodeURIComponent 来转义。

2.非 url,我们可以这样进行编码:

function encodeHtml(str){
    return str.relpace(/"/g,'"')
   .replace(/'/g,''')
   .replace(/</g,'&lt;')
   .relpace(/>/g,'&gt;')
}

DOM 型 XSS 攻击中,取出和执行恶意代码由浏览器端完成,属于前端 JavaScript 自身的安全漏洞。

查看DOM型XSS攻击示例(根据readme提示查看)

请戳: github.com/YvetteLau/B…

3.Dom 型 XSS

恶意脚本永久存储在目标服务器上。当浏览器请求数据时,脚本从服务器传回并执行,影响范围比反射型和DOM型XSS更大。存储型XSS攻击的原因仍然是没有做好数据过滤:前端提交数据至服务端时,没有做好过滤;服务端在接受到数据时,在存储之前,没有做过滤;前端从服务端请求到数据,没有过滤输出。

存储型 XSS 的攻击步骤:

  1. 攻击者将恶意代码提交到目标网站的数据库中。
  2. 用户打开目标网站时,网站服务端将恶意代码从数据库取出,拼接在 HTML 中返回给浏览器。
  3. 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
  4. 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。

这种攻击常见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等。

如何防范存储型XSS攻击:

  1. 前端数据传递给服务器之前,先转义/过滤(防范不了抓包修改数据的情况)
  2. 服务器接收到数据,在存储到数据库之前,进行转义/过滤
  3. 前端接收到服务器传递过来的数据,在展示到页面前,先进行转义/过滤

查看存储型XSS攻击示例(根据Readme提示查看)

请戳: github.com/YvetteLau/B…

除了谨慎的转义,我们还需要其他一些手段来防范XSS攻击:

1.Content Security Policy

在服务端使用 HTTP的 Content-Security-Policy 头部来指定策略,或者在前端设置 meta 标签。

例如下面的配置只允许加载同域下的资源:

Content-Security-Policy: default-src 'self'
<meta http-equiv="Content-Security-Policy" content="form-action 'self';">

前端和服务端设置 CSP 的效果相同,但是 meta无法使用 report

更多的设置可以查看 Content-Security-Policy

严格的 CSP 在 XSS 的防范中可以起到以下的作用:

  1. 禁止加载外域代码,防止复杂的攻击逻辑。
  2. 禁止外域提交,网站被攻击后,用户的数据不会泄露到外域。
  3. 禁止内联脚本执行(规则较严格,目前发现 GitHub 使用)。
  4. 禁止未授权的脚本执行(新特性,Google Map 移动版在使用)。
  5. 合理使用上报可以及时发现 XSS,利于尽快修复问题。

2.输入内容长度控制

对于不受信任的输入,都应该限定一个合理的长度。虽然无法完全防止 XSS 发生,但可以增加 XSS 攻击的难度。

3.输入内容限制

对于部分输入,可以限定不能包含特殊字符或者仅能输入数字等。

4.其他安全措施

  • HTTP-only Cookie: 禁止 JavaScript 读取某些敏感 Cookie,攻击者完成 XSS 注入后也无法窃取此 Cookie。
  • 验证码:防止脚本冒充用户提交危险操作。

2.CSRF 跨站请求伪造

CSRF(Cross-site request forgery)跨站请求伪造:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。

  • 典型的 CSRF 攻击流程
  1. 受害者登录 A 站点,并保留了登录凭证(Cookie)。
  2. 攻击者诱导受害者访问了站点 B。
  3. 站点 B 向站点 A 发送了一个请求,浏览器会默认携带站点 A 的 Cookie 信息。
  4. 站点 A 接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是无辜的受害者发送的请求。
  5. 站点 A 以受害者的名义执行了站点 B 的请求。
  6. 攻击完成,攻击者在受害者不知情的情况下,冒充受害者完成了攻击。

图片

  • CSRF 的特点

1.攻击通常在第三方网站发起,如图上的站点 B,站点 A 无法防止攻击发生。

2.攻击利用受害者在被攻击网站的登录凭证,冒充受害者提交操作;并不会去获取 cookie 信息(cookie 有同源策略)

3.跨站请求可以用各种方式:图片 URL、超链接、CORS、Form 提交等等(来源不明的链接,不要点击)

  • 防御手段
  1. 添加验证码(体验不好)

  2. 判断请求的来源:检测 Referer(并不安全,Referer 可以被更改)

  3. 使用 Token(主流)

  4. Samesite Cookie 属性

3.点击劫持

点击劫持是指在一个 Web 页面中隐藏了一个透明的 iframe,用外层假页面诱导用户点击,实际上是在隐藏的 frame 上触发了点击事件进行一些用户不知情的操作。

  • 典型点击劫持攻击流程
  1. 攻击者构建了一个非常有吸引力的网页【不知道哪些内容对你们来说有吸引力,我就不写页面了,偷个懒】
  2. 将被攻击的页面放置在当前页面的 iframe 中
  3. 使用样式将 iframe 叠加到非常有吸引力内容的上方
  4. 将 iframe 设置为 100%透明
  5. 你被诱导点击了网页内容,你以为你点击的是*,而实际上,你成功被攻击了。
  • 防御手段

1. frame busting

 ( top.location != window.location ){
    top.location = window.location
}

需要注意的是: HTML5 中 iframe 的 sandbox 属性、IE 中 iframe 的 security 属性等,都可以限制 iframe 页面中的 JavaScript 脚本执行,从而可以使得 frame busting 失效。

2. X-Frame-Options

X-FRAME-OPTIONS 是微软提出的一个 http 头,专门用来防御利用 iframe 嵌套的点击劫持攻击。并且在 IE8、Firefox3.6、Chrome4 以上的版本均能很好的支持。

可以设置为以下值:

  • DENY: 拒绝任何域加载
  • SAMEORIGIN: 允许同源域下加载
  • ALLOW-FROM: 可以定义允许 frame 加载的页面地址

4.SQL 注入

1、简介:

用户可以提交一段数据库查询代码,根据程序返回的结果,获得某些他想得知的数据。

2.漏洞危害:

  • 可导致数据库被拖
  • 重要信息泄露
  • 上传webshell
  • 执行系统命令,进而控制服务器

之所以会发生SQL注入,主要因为代码中存在拼接SQL语句的情况。比如:

* SELECT field FROM tableName WHERE ( name = " + name + " )

这个查询使用参数name拼接了一条SELECT语句。

3.防范:

要堵住这个漏洞,关键是保证参数name的值必须合法有效。

解决方案:在实际拼接SQL语句之前,要对name进行合法性验证,通过验证后再去拼接。

5.本地数据窃取

** 原理:**

直接打开chrom 浏览器 appction 修改读取 cookie 、localStorage、sessionStorage

图片

防范:

数据加密、脱敏处理,不保存敏感数据在storage里

6.文件上传

1、简介:

用户上传一个可执行的脚本文件,并通过此脚本文件获得了执行服务端命令的能力。

2、分类:

1)文件名攻击:上传的文件采用上传之前的文件名,可能造成客户端和服务端字符码不兼容,导致文件名乱码问题;文件名包含脚本,从而造成攻击.

2)文件后缀攻击:上传的文件的后缀可能是exe可执行程序,js脚本等文件,这些程序可能被执行于受害者的客户端,甚至可能执行于服务器上.因此我们必须过滤文件名后缀,排除那些不被许可的文件名后缀.

3)文件内容攻击:IE6有一个很严重的问题 , 它不信任服务器所发送的content type,而是自动根据文件内容来识别文件的类型,并根据所识别的类型来显示或执行文件.如果上传一个gif文件,在文件末尾放一段js攻击脚本,就有可能被执行.这种攻击,它的文件名和content type看起来都是合法的gif图片,然而其内容却包含脚本,这样的攻击无法用文件名过滤来排除,而是必须扫描其文件内容,才能识别。

3、防御措施:

1)文件上传的目录设置为不可执行。

2)判断文件类型。在判断文件类型的时候,可以结合使用MIME Type,后缀检查等方式。因为对于上传文件,不能简单地通过后缀名称来判断文件的类型,因为攻击者可以将可执行文件的后缀名称改为图片或其他后缀类型,诱导用户执行。

3)对上传的文件类型进行白名单校验,只允许上传可靠类型。

4)上传的文件需要进行重新命名,使攻击者无法猜想上传文件的访问路径,将极大地增加攻击成本。

5)限制上传文件的大小。

6)单独设置文件服务器的域名。

7.CDN 劫持

出于性能考虑,前端应用通常会把一些静态资源存放到CDN(Content Delivery Networks)上面,例如 js 脚本和 style 文件。这么做可以显著提高前端应用的访问速度,但与此同时却也隐含了一个新的安全风险。如果攻击者劫持了CDN,或者对CDN中的资源进行了污染,攻击者可以肆意篡改我们的前端页面,对用户实施攻击。 现在的CDN以支持SRI为荣,script 和 link 标签有了新的属性 integrity,这个属性是为了防止校验资源完整性来判断是否被篡改。它通过 验证获取文件的哈希值是否和你提供的哈希值一样来判断资源是否被篡改。 使用 SRI 需要两个条件:一是要保证 资源同域 或开启跨域,二是在script中 提供签名 以供校验。

图片integrity 属性分为两个部分,第一部分是指定哈希值的生成算法(例:sha384),第二部分是经过编码的实际哈希值,两者之前用一个短横(-)来分隔

这个属性也存在兼容问题

图片

安全检测工具

上面我们介绍了几种常见的前端安全漏洞,也了解一些防范措施,那么我们如何发现自己网站的安全问题呢?没有安全部门的公司可以考虑下面几款开源扫码工具:

1. Arachni

Arachni是基于Ruby的开源,功能全面,高性能的漏洞扫描框架,Arachni提供简单快捷的扫描方式,只需要输入目标网站的网址即可开始扫描。它可以通过分析在扫描过程中获得的信息,来评估漏洞识别的准确性和避免误判。

Arachni默认集成大量的检测工具,可以实施 代码注入、CSRF、文件包含检测、SQL注入、命令行注入、路径遍历等各种攻击。

同时,它还提供了各种插件,可以实现表单爆破、HTTP爆破、防火墙探测等功能。

针对大型网站,该工具支持会话保持、浏览器集群、快照等功能,帮助用户更好实施渗透测试。

2. Mozilla HTTP Observatory

Mozilla HTTP Observatory,是Mozilla最近发布的一款名为Observatory的网站安全分析工具,意在鼓励开发者和系统管理员增强自己网站的安全配置。用法非常简单:输入网站URL,即可访问并分析网站HTTP标头,随后可针对网站安全性提供数字形式的分数和字母代表的安全级别。

检查的主要范围包括:

  • Cookie
  • 跨源资源共享(CORS)
  • 内容安全策略(CSP)
  • HTTP公钥固定(Public Key Pinning)
  • HTTP严格安全传输(HSTS)状态
  • 是否存在HTTP到HTTPs的自动重定向
  • 子资源完整性(Subresource Integrity)
  • X-Frame-Options
  • X-XSS-Protection

3. w3af

W3af是一个基于Python的Web应用安全扫描器。可帮助开发人员,有助于开发人员和测试人员识别Web应用程序中的漏洞。

扫描器能够识别200多个漏洞,包括跨站点脚本、SQL注入和操作系统命令。

学习交流

建了一个“全栈大前端”的微信交流群,欢迎纯粹技术交流爱好者加入!