最近找寻找json安全输出解决方案,方案基本上已经确定,发到博客给大家分享分享。
什么是json
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScript(Standard ECMA-262 3rd Edition - December 1999)的一个子集。 JSON采用完全独立于语言的文本格式。
官方网站:http://www.json.org/
JSON是一种数据交换格式,可用于机器之间的数据传送。它只是表达数据,所以它本身是与安全无关的。使用JSON的系统安全与否,取决于该系统自身设计的好坏。JSON本身并不会引入安全隐患。
json的应用场景
应用场景1:
userInfo.json内容: var userInfo ={"name":"123"} userInfo.htm: <script src="userInfo.json" ></script> <script> alert(userInfo.name); alert(userInfo.length); alert(userInfo.substr(0)); </script> |
应用场景2:
userInfo.json内容: {"name":"123"} 浏览器、flash等内置组建(如activeX、ajax)等请求获取json数据,如由XMLHttpRequest 得到的文本格式,可通过eval方法快速地转换成为有用的数据结构。 通过eval(json数据)解析成json对象,通过javascript 对象引用处理: httpRequest = getHttpRequest() //get aa.json var userInfo = eval(httpRequest.responseText) alert(userInfo.name); |
应用场景3:
userInfo.json内容: var userInfo ={"name":"123"} userInfo.htm: <script src="userInfo.json" ></script> <script> nameDiv.innerHTML=userInfo.name; </script> |
json攻击原理:
json 以http方式提供给外网访问,几乎人人都可以直接打开json地址,
如果用户自己写程序、工具或者使用获取http的命令(如wget) 请求获取json数据,那么json只是作为一个文本数据交换使用,不存在安全隐患.
如果使用浏览器打开,那么它就相当于一个普通的html页面, 如果有恶意脚步等就会存在xss攻击的隐患.(xss攻击原里在这里不细讲)
攻击原理场景1
step1 用户A通过修改会员信息,伪造攻击脚步,name:<img src=javascript:alert(1)> 提交至web服务器 step2 json数据格式(vm模板): var userInfo = {"name":"$name"}; step3 用户A把json地址发给用户B,用户B在不知情的情况下(用浏览器)打开 var userInfo = {"name":="<img src=javascript:alert(1)>"; 结果:用户A伪造的攻击脚步:alert(1) 在用户B的浏览器解析并执行 |
攻击原理场景2
step1 用户A通过修改会员信息,伪造攻击脚步,name:"};alert(2);{" 提交至web服务器 step2 json.vm 模板内容: var userInfo = {"name":"$name"}; userinfo.vm 模板内容: <script src="json.vm"></script> <script> dispalayName(userInfo.name); </script> step3 用户B打开userinfo.vm查看用户A的信息:userinfo.vm?userid=b json.vm渲染结果: var userInfo = {"name":""};alert(2);{""}; 结果:用户A伪造的攻击脚步:alert(2) 被浏览者B的浏览器解析并执行 |
攻击原理场景3(html dom)
step1 用户A通过修改会员信息,伪造攻击脚步,name:<img src=vbscript:msgbox(0)> 提交至web服务器 step2 json.vm 模板内容: var userInfo = {"name":"$name"}; userinfo.vm 模板内容: <div id="divName"></div> <script src="json.vm"></script> <script> ..... document.getElementById("divName").innerHTML=userInfo.name; </script> step3 用户B打开userinfo.vm查看用户A的信息:userinfo.vm?userid=a json.vm渲染结果: var userInfo = {"name":"<img src=vbscript:msgbox(0)>"}; 结果:用户A伪造的攻击脚步:msgbox(0) 在执行innerHTML插入html的时候被执行 |
严格来讲,攻击原理场景3(html dom)不属于json安装输出范围
解决方案:
为了让用户伪造的脚步不被执行,有两种方案可以实现:
A、 过滤恶意脚步。 (我们不能确保所有的需求都允许过滤,因此不考虑这种方案)
B、对用户数据进行escape编码之后再输出,有两种escape方式,分别为javascript escape和html escape
1。通常情况下采用采用:javascript escape 之后输出
javasceipt escape:alert(2) 结果:alert\x282\x29
编码之后长度问题:
"alert(2)".length==8
"alert\x282\x29".length==8
"alert\x282\x29".length==8
"alert\x282\x29".substr(0,6)=="alert("
结果一样,编码之后不会对字符串长度、字符串截取产生影响.
2。对于html dom(应用场景3),采用html escape之后输出
需要指出,html escape之后,就不能作为javascript字符窜进行长度,截取部分字符等操作,你能作为html dom插入操作:*.innerHTML=?。
3。解析javascript方法eval()不太安全,使用yahoo yui:YAHOO.lang.JSON.parse 代替eval方法,具体请参见http://developer.yahoo.com/yui/json/
附
javascript escape:
public static String escapedJavaScript(String string) { if (string == null || string.length() == 0) { return string; } StringBuilder buffer = new StringBuilder(string.length() << 1); String hex; for (int i = 0; i < string.length(); i++) { char c = string.charAt(i); if (c < 127 && COMMON_ASCII[c]) { buffer.append(c); } else if (c <= 127) { hex = Integer.toHexString(c).toUpperCase(); if (hex.length() < 2) { buffer.append("\\x0"); } else { buffer.append("\\x"); } buffer.append(hex); } else { // c > 0x7F // len >= 2 hex = Integer.toHexString(c).toUpperCase(); if (c < 0x100) {// len == 2 buffer.append("\\u00"); } else if (c < 0x1000) {// len == 3 buffer.append("\\u0"); } else {// len == 4 buffer.append("\\u"); } buffer.append(hex); } } return buffer.toString(); } |
Html escape:
function HTMLEscape(str) { var s = ""; if(str.length == 0) return ""; s = str.replace(/&/g,"&"); s = s.replace(/</g,"<"); s = s.replace(/>/g,">"); s = s.replace(/ /g," "); s = s.replace(/\'/g,"'"); s = s.replace(/\"/g,"""); return s; } |