(四)前后端分离模式下的安全解决方案
最后更新于:2022-04-02 00:34:23
原文:http://ued.taobao.org/blog/2014/05/midway-security/
作者:lorrylockie
> ## 前言
>
> 在前后端分离的开发模式中,从开发的角色和职能上来讲,一个最明显的变化就是:以往传统中,只负责浏览器环境中开发的前端同学,需要涉猎到服务端层面,编写服务端代码。而摆在面前的一个基础性问题就是如何保障Web安全?
本文就在前后端分离模式的架构下,针对前端在Web开发中,所遇到的安全问题以及应对措施和注意事项,并提出解决方案。
## 跨站脚本攻击(XSS)的防御
### 问题及解决思路
跨站脚本攻击(XSS,Cross-site scripting)是最常见和基本的攻击Web网站的方法。攻击者可以在网页上发布包含攻击性代码的数据,当浏览者看到此网页时,特定的脚本就会以浏览者用户的身份和权限来执行。通过XSS可以比较容易地修改用户数据、窃取用户信息以及造成其它类型的攻击,例如:CSRF攻击。
预防XSS攻击的基本方法是:确保任何被输出到HTML页面中的数据以HTML的方式进行转义(HTML escape)。例如下面的模板代码:
~~~
~~~
这段代码中的`$description`为模板的变量(不同模板中定义的变量语法不同,这里只是示意一下),由用户提交的数据,那么攻击者可以输入一段包含”JavaScript”的代码,使得上述模板语句的结果变成如下的结果:
~~~
~~~
上述代码,在浏览器中渲染,将会执行JavaScript代码并在屏幕上alert hello。当然这个代码是无害的,但攻击者完全可以创建一个JavaScript来修改用户资料或者窃取cookie数据。
解决方法很简单,就是将`$description`的值进行html escape,转义后的输出代码如下
~~~
~~~
以上经过转义后的HTML代码是没有任何危害的。
### Midway的解决方案
#### 转义页面中所有用户输出的数据
对数据进行转义有以下几种情况和方法:
##### 1\. 使用模板内部提供的机制进行转义
中途岛内部使用KISSY xtemplate作为模板语言。
在xtemplate实现中,语法上使用两个中括号( `{{val}}`)解析模板数据, ,默认既是对数据进行HTML转义的,所以开发者可以这样写模板:
~~~
~~~
在xtemplate中,如果不希望输出的数据被转义,需要使用三个中括号({{{val}}})。
##### 2\. 在Midway中明确的调用转义函数
开发者可以在Node.js程序或者模板中,直接调用Midway提供的HTML转义方法,显示的对数据进行转义,如下:
方法1:在Node.js程序中对数据进行HTML转义
~~~
var Security= require('midway-security');
//data from server,eg {html:'',other:""}
data.html =Security.escapeHtml(data.html);
xtpl = xtpl.render(data);
~~~
方法2:在模板中对HTML数据进行HTML转义
~~~
~~~
注意:只有当模板内部没有对数据进行转义的时候才使用Security.escapeHtml进行转义。 否则,模板内部和程序会两次转义叠加,导致不符合预期的输出。
推荐:如果使用xtemplate,建议直接使用模板内置的`{{}}`进行转义; 如果使用其他模板,建议使用`Security.escapeHtml`进行转义。
#### 过滤页面中用户输出的富文本
你可能会想到:“其实我就是想输出富文本,比如一些留言板、论坛给用户提供一些简单的字体大小、颜色、背景等功能,那么我该如何处理这样的富文本来防止XSS呢?”
##### 1\. 使用Midway中Security提供的richText函数
Midway中提供了richText方法,专门用来过滤富文本,防止XSS、钓鱼、cookie窃取等漏洞。
有一个留言板,模板代码可能如下:
~~~
我在留言中
~~~
上述的富文本数据如果直接输出到页面中,必然会导致eval.com站点的js注入到当前页面中,造成了XSS攻击。为了防止这个漏洞,我们只要在模板或者程序中,调用Security.richText方法,处理用户输入的富文本。
调用方法与escapeHtml类似,有如下两种方式
方法1: 直接在Node.js程序中调用
~~~
message =Security.richText(message);
var html = xtpl.render(message)
~~~
方法2: 在模板中调用
~~~
~~~
通过调用Security的richText方法后,最终的输出如下:
~~~
~~~
可以看出,首先:会造成XSS攻击的`script`标签被直接过滤掉;同时style标签中CSS属性`position:fixed;`样式也被过滤了。最终输出了无害的HTML富文本
#### 了解其他可能导致XSS攻击的途径
除了在页面的模板中可能存在XSS攻击之外,在Web应用中还有其他几个途径也可能会有风险。
##### 1\. 出错页面的漏洞
一个页面如果找不到,系统可能会报一个404 Not Found的错误,例如:[http://localhost/page/not/found](http://localhost/page/not/found)
~~~
404 NotFound
Page /page/not/found does not exsit
~~~
很显然:攻击者可以利用这个页面,构造一个类似这样的连接,`http://localhost/%3Cscript%3Ealert%28%27hello%27%29%3C%2Fscript%3E`,并引诱受害者点击 ;假如出错页面未对输出变量进行转义的话,那么连接中隐藏的 `` 将会被执行。
在express中,发送一个404页面的方法如下
~~~
res.send(404,'Sorry,we don\'t find that!')
~~~
这里就需要开发者注意错误页面(404或者其他错误状态)的处理方式。如果错误信息的返回内容带有路径信息(其实更准确的讲,是用户输入信息),就一定要进行escapeHtml了。
后续,错误处理的安全机制,会在Midway框架层面中完成。
### Midway解决方案的补充说明
#### 其他模板引擎
Midway默认支持xtemplate模板,但将来也有可能支持其他模板:如jade、mustache、ejs等。目前在主流模板中,都提供了默认转义和不转义的输出变量写法,需要开发者特别留意其安全性。
#### 关于escape的其他支持
除了对页面中输出的普通数据和富文本数据,一些场景中也还包含其他可能需要转义的情况,Midway提供了如下几个常用的转义方法,供开发者使用:
* escapeHtml 过滤指定的HTML中的字符,防XSS漏洞
* jsEncode 对输入的String进行JavaScript 转义 对中文进行unicode转义,单引号,双引号转义
* escapeJson 不破坏JSON结构的escape函数,只对json结构中name和vaule做escapeHtml处理
* escapeJsonForJsVar 可以理解就是jsEncode+escapeJson
例子如下
~~~
var jsonText ="{\"
';
~~~
因为message是用户的输入数据,其留言板的内容,包含了富文本信息,所以这里在xtemplate中,使用了三个大括号,默认不进行HTML转义;那么用户输入的数据假如如下:
~~~