Appearance
有哪些可能引起前端安全的的问题?
- 跨站脚本攻击(Cross-Site Scripting, XSS):⼀种代码注⼊⽅式, 为了与 CSS 区分所以被称作 XSS. 早期常⻅于⽹络论坛, 起因是⽹站没有对⽤户的输⼊进⾏严格的限制, 使得攻击者可以将脚本上传到帖⼦让其他⼈浏览到有恶意脚本的⻚ ⾯, 其注⼊⽅式很简单包括但不限于 JavaScript / VBScript / CSS / Flash 等
- 跨站点请求伪造(Cross-Site Request Forgeries, CSRF):指攻击者通过设置好的陷阱,强制对已完成认证的⽤ 户进⾏⾮预期的个⼈信息或设定信息等某些状态更新,属于被动攻击
- iframe 的滥⽤:iframe 中的内容是由第三⽅来提供的,默认情况下他们不受我们的控制,他们可以在 iframe 中运⾏ JavaScirpt 脚本、Flash 插件、弹出对话框等等,这可能会破坏前端⽤户体验
- 恶意第三⽅库:⽆论是后端服务器应⽤还是前端应⽤开发,绝⼤多数时候我们都是在借助开发框架和各种类库进⾏快速开发,⼀旦第三⽅库被植⼊恶意代码很容易引起安全问题,⽐如
event-stream的恶意代码事件,2018年11⽉21⽇,名为 FallingSnow 的⽤户在知名 JavaScript 应⽤库event-stream在 github Issuse 中发布了针对植⼊的恶意代码的疑问,表示event-stream中存在⽤于窃取⽤户数字钱包的恶意代码
⽹络劫持有哪⼏种?
- DNS劫持
- DNS 强制解析: 通过修改运营商的本地 DNS 记录,来引导⽤户流量到缓存服务器
- 302 跳转的⽅式: 通过监控⽹络出⼝的流量,分析判断哪些内容是可以进⾏劫持处理的,再对劫持的内存发起 302 跳转的回复,引导⽤户获取内容
- HTTP 劫持: (访问⾕歌但是⼀直有贪玩蓝⽉的⼴告),由于 http 明⽂传输,运营商会修改你的 http 响应内容(即加⼴告)
防御策略:
DNS 劫持由于涉嫌违法,已经被监管起来,现在很少会有 DNS 劫持,⽽ http 劫持依然⾮常盛⾏。最有效的办法就是全站 HTTPS,将 HTTP 加密,这使得运营商⽆法获取明⽂,就⽆法劫持你的响应内容。
HTTPS ⼀定是安全的吗?
- ⾮全站 HTTPS 并不安全
- 中间⼈攻击
前端安全 XSS、CSRF 等
XSS(Cross Site Scripting) - 跨站脚本攻击
- 存储型 XSS 攻击: 利用漏洞提交恶意 JavaScript 代码,提交后信息会存在服务器中,当用户再次打开网站请求到相应的数据,打开页面,恶意脚本就会将用户的 Cookie 信息等数据上传到黑客服务器
- 反射型 XSS 攻击: 用户将一段含有恶意代码的请求提交给 Web 服务器,Web 服务器接收到请求时,又将恶意代码反射给了浏览器端,这就是反射型 XSS 攻击。 在现实生活中,黑客经常会通过 QQ 群或者邮件等渠道诱导用户去点击这些恶意链接,所以对于一些链接我们一定要慎之又慎。
Web 服务器不会存储反射型 XSS 攻击的恶意脚本,这是和存储型 XSS 攻击不同的地方
- 基于 DOM 的 XSS 攻击: 我们客户端的 js 可以对页面 DOM 节点进行动态的操作,比如插入、修改页面的内容。比如说客户端从 URL 中提取数据并且在本地执行、如果用户在客户端输入的数据包含了恶意的 js 脚本的话,但是这些脚本又没有做任何过滤处理的话,那么我们的应用程序就有可能受到 DOM-based XSS 的攻击
预防策略:
- 将 cookie 等敏感信息设置为 httponly,禁止 Javascript 通过
document.cookie获得 - 对所有的输入做严格的校验尤其是在服务器端,过滤掉任何不合法的输入,比如手机号必须是数字,通常可以采用正则表达式
- 净化和过滤掉不必要的 html 标签,比如:
<iframe>,<script>等,净化和过滤掉不必要的 Javascript 的事件标签,比如:onclick,onfocus等 - 转义单引号,双引号,尖括号等特殊字符,可以采用 encode 编码,或者过滤掉这些特殊字符
- CSP,全称为 Content Security Policy,即内容安全策略。主要以白名单的形式配置可信任的内容来源,在网页中,能够使白名单中的内容正常执行(包含 JS,CSS,Image 等等),而非白名单的内容无法正常执行,从而减少跨站脚本攻击(XSS),当然,也能够减少运营商劫持的内容注入攻击
开启 CSP 的两种方法:
meta元素html<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">- 网络服务器返回
Content-Security-PolicyHTTP 头部
CSRF(Cross-site request forgery) - 跨站请求伪造
利用了 Cookie 允许在第三方网站发起的请求中携带这一「弱点」,引诱用户打开黑客的网站,在黑客的网站中,利用用户的登录状态发起的跨站请求。
发起 CSRF 攻击的三个必要条件:
- 目标站点一定要有 CSRF 漏洞
- 用户要登录过目标站点,并且在浏览器上保持有该站点的登录状态
- 需要用户打开一个第三方站点,如黑客的站点等
预防策略:
- 充分利用好 Cookie 的 SameSite 属性
- 验证请求的来源站点(在服务器端验证请求来源的站点,就是验证 HTTP 请求头中的
Origin和Referer属性) - 验证码(思路是每次的用户提交都需要用户在表单中填写一个图片上的随机字符串,但是大多场景下都不会选用这种方案)
- One-Time Tokens(不同的表单包含一个不同的伪随机值)
- 使用额外的 csrfToken 校验请求来源 由于目前很多项目是前后端分离的,前端页面不是由后端动态生成的,因此可以在授权时生成一个随机的 csrfToken,并设置到 cookie 中,在后续的请求中,要求前端从 cookie 中读取到 csrfToken 并设置到 header 中,之后后端验证 cookie 中的 csrfToken 和 header 中的 x-csrf-token 是否一致来判断请求来源是否合法
服务端防御 CSRF 的方式方法很多样,但总的思想都是一致的,就是在客户端页面增加伪随机数
SQL注入:
拼接 SQL 时未仔细过滤,黑客可提交畸形数据改变语义。比如查某个文章,提交了这样的数据 id=-1 or 1=1 等。1=1 永远是 true,导致 where 语句永远是 ture。那么查询的结果相当于整张表的内容,攻击者就达到了目的。或者,通过屏幕上的报错提示推测 SQL 语句等。
预防策略:
- 禁止目标网站利用动态拼接字符串的方式访问数据库
- 减少不必要的数据库抛出的错误信息
- 对数据库的操作赋予严格的权限控制
- 净化和过滤掉不必要的 SQL 保留字,比如:
where,or,exec等
点击劫持:
- 诱使用户点击看似无害的按钮(实则点击了透明 iframe 中的按钮)
- 监听鼠标移动事件,让危险按钮始终在鼠标下方
- 使用 HTML5 拖拽技术执行敏感操作(例如 deploy key)
预防策略:
- 服务端添加
X-Frame-Options响应头。这个 HTTP 响应头是为了防御用 iframe 嵌套的点击劫持攻击,这样浏览器就会阻止嵌入网页的渲染 - JS 判断顶层视口的域名是不是和本页面的域名一致,不一致则不允许操作,
top.location.hostname === self.location.hostname - 敏感操作使用更复杂的步骤(验证码、输入项目名称以删除)
window.opener 安全问题:
window.opener 表示打开当前窗体页面的的父窗体的是谁。例如,在 A 页面中,通过一个带有 target="_blank" 的 a 标签打开了一个新的页面 B,那么在 B 页面里,window.opener 的值为 A 页面的 window 对象。
一般来说,打开同源(域名相同)的页面,不会有什么问题。但对于跨域的外部链接来说,存在一个被钓鱼的风险。比如你正在浏览购物网站,从当前网页打开了某个外部链接,在打开的外部页面,可以通过 window.opener.location 改写来源站点的地址。利用这一点,将来源站点改写到钓鱼站点页面上,例如跳转到伪造的高仿购物页面,当再回到购物页面的时候,是很难发现购物网站的地址已经被修改了的,这个时候你的账号就存在被钓鱼的可能了。
预防策略:
- 设置
rel属性<a href="https://xxxx" rel="noopener noreferrer">外链<a>,规定禁止新页面传递源页面的地址,通过设置了此属性的链接打开的页面,其window.opener的值为null - 将外链替换为内部的跳转连接服务,跳转时先跳到内部地址,再由服务器 redirect 到外链
- 可以由
widow.open打开外链
文件上传漏洞:
服务器未校验上传的文件,致使黑客可以上传恶意脚本等方式。
预防策略:
- 用文件头来检测文件类型,使用白名单过滤(有些文件可以从其中一部分执行,只检查文件头无效,例如 PHP 等脚本语言)
- 上传后将文件彻底重命名并移动到不可执行的目录下
- 升级服务器软件以避免路径解析漏洞
- 升级用到的开源编辑器
- 管理后台设置强密码
参考资料
