<script src=""></script><span>我在留言中</span>
上述的富文本数据如果直接输出到页面中,必然会导致eval.com站点的js注入到当前页面中,造成了XSS攻击。为了防止这个漏洞,我们只要在模板或者程序中,调用Security.richText方法,处理用户输入的富文本。
调用方法与escapeHtml类似,有如下两种方式
方法1: 直接在Node.js程序中调用
复制代码 代码如下:
message =Security.richText(message);
var html = xtpl.render(message)
方法2: 在模板中调用
复制代码 代码如下:
<div>
Security.richText({{{message}}})
</div>
通过调用Security的richText方法后,最终的输出如下:
复制代码 代码如下:
<div>
<span>我在留言中</span>
</div>
可以看出,首先:会造成XSS攻击的script标签被直接过滤掉;同时style标签中CSS属性position:fixed;样式也被过滤了。最终输出了无害的HTML富文本
了解其他可能导致XSS攻击的途径
除了在页面的模板中可能存在XSS攻击之外,在Web应用中还有其他几个途径也可能会有风险。
1. 出错页面的漏洞
一个页面如果找不到,系统可能会报一个404 Not Found的错误,例如:
404 NotFound
Page /page/not/found does not exsit
很显然:攻击者可以利用这个页面,构造一个类似这样的连接,%3Cscript%3Ealert%28%27hello%27%29%3C%2Fscript%3E,并引诱受害者点击 ;假如出错页面未对输出变量进行转义的话,那么连接中隐藏的 <script>alert('hello')</script> 将会被执行。
在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 ="{\"<script>\":\"<script>\"}";
console.log(SecurityUtil.escapeJson(jsonText));// {"<script>":"<script>"}
var jsonText ="{\"你好\":\"<script>\"}";
console.log(SecurityUtil.escapeJsonForJsVar(jsonText));//{\"\u4f60\u597d\":\"<script>\"}
var str ="alert(\"你好\")";
console.log(SecurityUtil.jsEncode(str));// alert(\"\u4f60\u597d\")
跨站请求伪造攻击(CSRF)的预防
问题及解决思路
名词解释: 表单:泛指浏览器端用于客户端提交数据的形式;包括a标签、ajax提交数据、form表单提交数据等,而非对等于HTML中的form标签。
跨站请求伪造(CSRF,Cross-site request forgery)是另一种常见的攻击。攻击者通过各种方法伪造一个请求,模仿用户提交表单的行为,从而达到修改用户的数据或执行特定任务的目的。
为了假冒用户的身份,CSRF攻击常常和XSS攻击配合起来做,但也可以通过其它手段:例如诱使用户点击一个包含攻击的链接。
解决CSRF攻击的思路分如下两个步骤
1.增加攻击的难度。GET请求是很容易创建的,用户点击一个链接就可以发起GET类型的请求,而POST请求相对比较难,攻击者往往需要借助JavaScript才能实现;因此,确保form表单或者服务端接口只接受POST类型的提交请求,可以增加系统的安全性。
2.对请求进行认证,确保该请求确实是用户本人填写表单或者发起请求并提交的,而不是第三者伪造的。
一个正常用户修改网站信息的过程如下