前言

JSON(JavaScript Object Notation),可以说,这一事实,浏览器,server数据交换标准。的格式如XML,或者其他自己定义的格式会越来越少。

为什么JSON这么流行?

和JavaScript无缝对接是一个原因。

另一个重要原因是能够比較轻松的实现跨域。假设是XML。或者其他专有格式,则非常难实现跨域。要通过flash之类来实现。

不论什么一种数据格式,怎样解析处理不当。都会存在安全漏洞。

以下扯谈下JSON相关的一些安全东东。

在介绍之前,先来提几个问题:

  • 为什么XMLHttpRequest要遵守同源策略?
  • XMLHttpRequest 请求会不会带cookie?
  • <script scr="..."> 的标签请求会不会带cookie?
  • 向一个其他域名的站点提交一个form,会不会带cookie?
  • CORS请求能不能带cookie?

JSON注入

有的时候,可能是为了方便。有人会手动拼接下JSON,可是这样的随手代码,却可能带来意想不到的安全隐患。

第一种方式。利用字符串拼接:

		String user = "test01";
String password = "12345', admin:'true";
String json = "{user:'%s', password:'%s'}";
System.out.println(String.format(json, user, password));
//{user:'test01', password:'12345', admin:'true'}

用户添加了管理员权限。

另外一种,利用Parameter pollution, 类似http parameter pollution

		String string = "{user:'test01',password:'hello', password:'world'}";
JSONObject parse = JSON.parseObject(string);
String password = parse.getString("password");
System.out.println(password);
//world

当JSON数据key反复了会怎么处理?大部分JSON解析库都是后面的參数覆盖了前面的。

以下的演示了改动别人password的样例:

		//user%3Dtest01%26password%3D12345%27%2Cuser%3Dtest02"
//user=test01&password=12345',user=test02
HttpServletRequest request = null;
String user = request.getParameter("user");
//检查test01是否登陆
String password = request.getParameter("password");
String content = "{user:'" + user + "', password:'" + password + "'}"; User user = JSON.parseObject(content, User.class);
//{"password":"12345","user":"test02"}
updateDb(user);

所以说。不要手动拼接JSON字符串

浏览器端应该怎样处理JSON数据?

像eval这样的方式,自然是不能採用的。

如今的浏览器都提供了原生的方法 JSON.parse(str) 来转换为JS对象。

假设是IE8之前的浏览器,要使用这个库来解析:https://github.com/douglascrockford/JSON-js

參考:http://zh.wikipedia.org/wiki/JSON#.E5.AE.89.E5.85.A8.E6.80.A7.E5.95.8F.E9.A1.8C

JQuery里内置了JSON解析库

JSONP callback注入

简介jsonp的工作原理。

jsonp工作原理:

用js在document上插入一个<script>标签。标签的src指向远程server的API地址。client和server约定一个回调函数的名字,然后server返回回调函数包裹着的数据,然后浏览器运行回调函数,取得数据。

比方jquery是这样子实现的:

var url = 'http://localhost:8080/testJsonp?callback=?

';
$.getJSON(url, function(data){
alert(data)
});

jquery自己主动把?

转成了一个带时间戳特别的函数(防止缓存):

  http://localhost:8080/testJsonp?

callback=jQuery1102045087050669826567_1386230674292&_=1386230674293

相当于插入了这么一个<script>标签:

<script src="http://localhost:8080/testJsonp?callback=jQuery1102045087050669826567_1386230674292&_=1386230674293"></script>

server返回的数据是这样子的:

jQuery1102045087050669826567_1386230674292({'name':'abc', 'age':18})

浏览器会运行直接运行这个JS函数。

所以。假设在callback函数的名字上做点手脚,能够运行随意的JS代码。所以说callback名字一定要严格过滤。

当然。callback函数的名字一般是程序自己控制的,可是不能排除有其他被利用的可能。

那么callback函数的名字。怎样过滤?应当仅仅同意合法的JS函数命名。用正则来匹配应该是这样子的:

^[0-9a-zA-Z_.]+$

正则可能比較慢。能够写一个函数来推断:

	static boolean checkJSONPCallbackName(String name) {
try {
for (byte c : name.getBytes("US-ASCII")) {
if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_')
{
continue;
} else {
return false;
}
}
return true;
} catch (Throwable t) {
return false;
}
}

实际上对callback函数名字进行严格检验还有其他的一个优点,就是防范了非常多UTF-7编码攻击。

由于UTF-7编码的头部都是带有特殊字符的,如"+/v8","+/v9",这样就过滤掉非法编码的请求了。

jsonp的请求的验证

jsonp在使用的时候,还有easy犯的错误是没有验证用户的身份。

第一。操作是否是用户自己提交的,而不是别的网页用<script>标签,或者用<form>提交的

所以要检查request的refer,或者验证token。这个实际是CSRF防护的范畴。可是非常easy被忽略。

第二,要验证用户的权限。

非常多时候。可能仅仅是验证了用户是否登录 。却没有细致推断用户是否有权限。

比方通过JSONP请求改动了别的用户的数据。

所以说,一定要难证来源。推断refer。验证用户的身份。

到乌云上搜索。能够找到不少类似的漏洞,都是由于没有严格验证用户的权限。http://www.wooyun.org/searchbug.php?q=jsonp

JSON hijacking

在JS里能够为对象定义一些setter函数。这种话就存在了能够利用的漏洞。

比方在浏览器的JS Console里运行:

window.__defineSetter__('x', function() {
alert('x is being assigned!');
});
window.x=1;

会非常奇妙地弹出一个alert窗体,说明我们定义的setter函数起作用了。

结合这个,当利用<script>标签请求外部的一个JSON API时,假设返回的是数组型,就能够利用窃取数据。

比方有这种一个API:

http://www.test.com/friends

返回的数据是JSON Array:

[{'user':'test01','age':18},{'user':'test02,'age':19},{'user':'test03','age':20}]

在攻击页面上插入下面的代码,就能够获取到用户的全部的朋友的信息。

<script>
Object.prototype.__defineSetter__('user',function(obj)
{alert(obj);
}
);
</script>
<script src="http://www.test.com/friends"></script>

这个漏洞在前几年非常流行,比方qq邮箱的一个漏洞:http://www.wooyun.org/bugs/wooyun-2010-046

如今的浏览器都已经修复了,能够下载一个Firefox3.0版本号来測试下。眼下的浏览器在解析JSON Array字符串的时候。不再去触发setter函数了。

但对于object.xxx 这种设置。还是会触发。

IE的utf-7编码解析问题

这个漏洞也以前非常流行。

利用的是老版的IE能够解析utf-7编码的字符串或者文件,绕过server的过滤。举个乌云上的样例:http://www.wooyun.org/bugs/wooyun-2011-01293

有这种一个jsonp调用接口:

http://jipiao.taobao.com/hotel/remote/livesearch.do?callback=%2B%2Fv8%20%2BADwAaAB0AG0APgA8AGIAbwBkAHkAPgA8AHMAYwByAGkAcAB0AD4AYQBsAGUAcgB0ACgAMQApADsAPAAvAHMAYwByAGkAcAB0AD4APAAvAGIAbwBkAHkAPgA8AC8AaAB0AG0APg

url decoder之后是:

http://jipiao.taobao.com/hotel/remote/livesearch.do?callback=+/v8 +ADwAaAB0AG0APgA8AGIAbwBkAHkAPgA8AHMAYwByAGkAcAB0AD4AYQBsAGUAcgB0ACgAMQApADsAPAAvAHMAYwByAGkAcAB0AD4APAAvAGIAbwBkAHkAPgA8AC8AaAB0AG0APg

由于jsonp调用是直接返回callback包装的数据。所以实际上。上面的请求直接返回的是:

+/v8 +ADwAaAB0AG0APgA8AGIAbwBkAHkAPgA8AHMAYwByAGkAcAB0AD4AYQBsAGUAcgB0ACgAMQApADsAPAAvAHMAYwByAGkAcAB0AD4APAAvAGIAbwBkAHkAPgA8AC8AaAB0AG0APg-(调用结果数据)

IE做了UTF-7解码之后数据是这样子的:

<htm><body><script>alert(1);</script></body></htm>(调用结果数据)

于是。就运行了XSS。

另外用IFrame也是能够的。

可是我在IE8上測试,url的后缀须要是html才会触发。

IE把没有声明返回Content-Type的请求当做了"text/html"类型的。然后解析就有问题了。仅仅要server端显式设置了Content-Type为"application/json",则IE不会识别编码,就不会触发漏洞。所以说server端的Content-Type一定要设置对。虽然设置之后调试有点麻烦。可是却大大提高了安全性。

JSON格式设置为:"application/json"

JavaScript设置为:"application/x-javascript"

JavaScript另一些设置为:"text/javascript"等,都是不规范的。

其他的一些东东

MongoDB注入

这个实际上就是JSON注入,简单的字符串拼接。可能会引发各种数据被改动的问题。

JSON解析库的问题

有些JSON库解析库支持循环引用,那么能否够构造特别的数据,导致其解析失败?从而引起CPU使用过高,拒绝服务等问题?

FastJSON的一个StackOverflowError Bug:

https://github.com/alibaba/fastjson/issues/76

有些JSON库解析有问题:

http://www.freebuf.com/articles/web/10672.html

JSON-P

有人提出一个JSON-P的规范,可是貌似眼下都没有浏览器有支持这个的。

原理是对于JSONP请求。浏览器能够要求server返回的MIME是"application/json-p",这样能够严格校验是否合法的JSON数据。

CORS(Cross-Origin Resource Sharing)

为了解决跨域调用的安全性问题。眼下实际上可用的方案是CORS:

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

http://www.w3.org/TR/cors/

原理是通过server端设置同意跨域调用,然后浏览器就同意XMLHttpRequest跨域调用了。

CORS能够发起GET/POST请求。不像JSONP。仅仅能发起GET请求。

默认情况下,CORS请求是不带cookie的。

我个人觉得,这个方法也非常蛋疼。一是须要server配置。二是协议复杂。浏览器假设不能确定是否可以跨域调用。还要先进行一个Preflight Request。。

实际上,即使server不同意CORS,XMLHttpRequest请求实际上是发送出去,而且返回数据的了。仅仅是浏览器没有让JS环境拿到而已。

另外。我觉得有第二种数据泄露的可能:黑客可能控制了某个路由,他不能任意抓包,可是他能够在回应头里插入一些特别的头部。比方:

Access-Control-Allow-Credentials: true 

那么。这时XMLHttpRequest请求就是带cookie的了。

最初的问题

回到最初的问题:

  • 为什么XMLHttpRequest要遵守同源策略?
即使XMLHttpRequest是不带Cookie的,也是有可能造成数据泄露的。比方内部站点是依据IP限制訪问的,假设XMLHttpRequest不遵守同源策略,那么攻击者能够在用户浏览网页的时候,发起请求,取得内部站点数据。
  • XMLHttpRequest 请求会不会带cookie?
同域情况下会。不同域情况下不会。假设server设置Access-Control-Allow-Credentials: true ,也是能够跨域带Cookie的。
  • <script scr="..."> 的标签请求会不会带cookie?
会。
  • 向一个其他域名的站点提交一个form,会不会带cookie?
会。

总结:

  • 禁止手动拼接JSON字符串。一律应当用JSON库输出。也不应使用自己实现的ObjectToJson等方法,由于可能有各种没有考虑到的地方。

  • jsonp请求的callback要严格过滤,仅仅同意"_",0到9。a-z, A-Z,即合法的javascript函数的命名。
  • jsonp请求也要推断合法性,比方用户是否登陆(这点非常easy被忽略)。
  • 设置好Content-Type(这点对于调试不方便。可是提高了安全性)。

  • 以jsonp方式调用第三方的接口。实际相当于引入了第三方的JS代码,要谨慎。

參考:

http://www.json.org/

http://www.slideshare.net/wurbanski/nosql-no-security

https://github.com/douglascrockford/JSON-js

http://toolswebtop.com/      在线编码转换,能够转换UTF-7

http://www.thespanner.co.uk/2011/05/30/json-hijacking/

http://www.thespanner.co.uk/2009/11/23/bypassing-csp-for-fun-no-profit/

http://stackoverflow.com/questions/1830050/why-same-origin-policy-for-xmlhttprequest

阿赫亚web安全JSON的更多相关文章

  1. python3实现的web端json通信协议

    之前有用python3实现过tcp协议的,后来又实现了http协议的通信,今天公司想做一个功能自动测试系统, 下午弄了一会,发现json格式的实现可以更简单一点,代码如下:简单解说一下,一般与服务器通 ...

  2. 玩转Web之Json(四)---json与(Object/List/Map)的相互转化

    在做web应用时,经常需要将json转化成Object/list/map或者将Object/List/map转化成json,通过简单封装可以在写代码是减轻很多负担.本文将给出json转化的一系列方法. ...

  3. 解决ASP.NET Web API Json对象循环参考错误

    前言 一般我们在开法 ASP.NET Web API 时,如果是使用 Entity Framework 技术来操作数据库的话,当两个 Entity 之间包含导览属性(Navigation Proper ...

  4. 有趣Web之Json(四)---json与(Object/List/Map)相互转化

    干web报名时间.通常,他们需要json转换为Object/list/map要么Object/List/map转换为json,由能够编写代码的简单包装非常多,以减轻负担. 本文将给出json的一系列的 ...

  5. 在Spring MVC Controller的同一个方法中,根据App还是WEB返回JSON或者HTML视图。

    如有高见,欢迎交流! 最近在做一个web的项目,web版已经开发完毕,现在正在进行手机APP的开发,开发中遇到一个问题: 就是web版和app版都有登录功能,本想着是分别走不同的URL,实际开发的时候 ...

  6. Java Web返回JSON

    Web项目中经常涉及到AJAX请求返回JSON和JSONP数据.JSON数据在server端和浏览器端传输,本质上就是传输字符串,只是这个字符串符合JSON语法格式.浏览器端会依照普通文本的格式接收J ...

  7. SpringBoot-(2)-Web的json接口,静态网页,动态页面

    一, 了解注解@Controller和@RestController @Controller:处理Http请求 @RestController:Spring4以后新增注解,相当于@Controller ...

  8. pyhton 从web获取json数据 保存到本地然后再读取

    从web中获取json数据直接进行处理总认为太慢.主要是从web中获取获取数据的过程有点慢. 所以就在想 假设先利用空暇时间把json数据获取并保存到本地,然后再从本地文件里读取和操作.应该就要快非常 ...

  9. 玩转web之json(五)---将表单通过serialize()方法获取的值转成json

    form表单有一个serialize()方法,可以序列化表单的值,但是jquery提供的这个方法会把数据序列化为类似下面的形式: a=1&b=2&c=3&d=4 jquery并 ...

随机推荐

  1. Struts2获取演示示例教程

    回想Struts2的使用过程,网上搜的教程多多少少都会有点问题.又一次记录下创建过程,方便查阅. 1.下载Struts2的jar包 下载地址:http://archive.apache.org/dis ...

  2. 简体中文 — ANSI Common Lisp 中文版

    简体中文 - ANSI Common Lisp 中文版 简体中文¶

  3. hdu 1240 Asteroids!(BFS)

    题目链接:点击链接 简单BFS,和二维的做法相同(需注意坐标) 题目大意:三维的空间里,给出起点和终点,“O”表示能走,“X”表示不能走,计算最少的步数 #include <iostream&g ...

  4. The tempfile module

    The tempfile module The tempfile module This module allows you to quickly come up with unique names ...

  5. Java中的工具类和新特性

    1:Collections集合框架工具类: /* 集合框架的工具类. Collections:集合框架的工具类.里面定义的都是静态方法. Collections和Collection有什么差别? Co ...

  6. Routing 服务

    WCF Routing 服务 WCF4.0支持路由机制,通过RoutingService实现请求分发.拦截处理. 一.应用场景 1.暴露一个endpoint在外网,其余服务部署于内网: 2.请求分发, ...

  7. hdu4289(最小割)

    传送门:Control 题意:有n个城市,有个小偷想从其中一个城市逃到另一个城市,警察想要堵截这个小偷,知道了在每个城市堵截的成本,问如何安排在哪些城市堵截可以使得小偷一定会被抓住,而且成本最低. 分 ...

  8. curl的封装

    首先要搭建一个httpserver,这里採用tomcat6为例: 过程:新建一个Servlet,并使用tomcat的默认port号8080监听,最后写一个jsp来測试能否够訪问该server 1)新建 ...

  9. Jquery插件placeholder的用法

    闲的蛋疼,演示一下Jquery插件placeholder的用法,借助该插件能够轻松实现HTML5中placeholder特效: 效果图: 实现代码: <%@ page language=&quo ...

  10. 获取webshell的十种方法

    黑客在入侵企业网站时,通常要通过各种方式获取webshell从而获得企业网站的控制权,然后方便进行之后的入侵行为.本篇文章将如何获取webshell总结成为了十种方法,希望广大的企业网络管理员能够通过 ...