漏洞主要分为水平越权和垂直越权。
水平越权主要是指用户操作服务端数据时,服务端未验证数据是否归属于请求用户。使得攻击者可操作其他用户数据,导致水平越权漏洞。
垂直越权又称权限提升
。其主要原因是由于应用程序没有做权限控制,或仅通过JavaScript在前端进行权限控制,导致攻击者猜测到管理页面或绕过前端验证,达到权限提升的目的。
(增加、删除、修改和查询)其他用户的数据。
初步可以定位为Gson在对Date类型进行序列化和反序列化的处理不一致造成,查看Gson的源码(1.7.1),问题得到确认:
Gson默认的Date类型处理类,有三种格式:enUs、local、iso8601
序列化时使用enUsFormat
反序列化时首先尝试localFormat
gson常见问题
1、序列化时int类型默认会转换成double类型,带小数位 .0 , com.md.jr.eco.common.utils.GsonUtils 默认 已修复此转换问题
2、对象中如有定义 boolean 类型字段 ,如 private boolean isSuccess;
fastjson 序列化结果为 {"code":"0000","info":"成功","success":true}
gson 序列化结果为 {"isSuccess":true,"code":"0000","info":"成功"}
{"code":"0000","info":"成功","success":true} 此json串 反序列化时 fastjson 结果为true ,gson 结果会是 false ,gson反序列化结果明显不符合预期
鉴于以上结果 在定义boolean类型字段时 不要带 is
3、gson中JsonObject操作时,使用不存在的key操作时 会报空指针,fastjson反而不会报错
4、 与系统Locale 相关。【通过localFormat、enUsFormat、iso8601Format三种format来解析日期】
.查看环境LANG 配置:
调整系统配置:zh_CH.UTF-8 并Source
5、 日期
gson默认日期格式,与地区有关,new SimpleDateFormat()生成的
这是一个很暴力的适配器模式, localFormat, enUsFormat, ISO8601Utils挨个尝试转换,那么这三个值具体是什么呢, 打个断点来看看:
ISO8601:
首先是ISO8601,Google的大佬直接hard code 成Locale.US.
ISO8601
这是个UTC时间, T标识是UTC时间,Z标识时区, 北京时间比UTC快的8个小时, 会被记作UTC+8, 这就是东八区的由来, 如下:
enUsFormat
美国的时间会标记出上午和下午, 时间格式是MMM dd, yyyy hh:mm:ss a, 例如Sep 16, 2015 10:34:23 AM.
LocalFormat:
最后是localFormat,
cn-localFormat
注意到这个java.text.DateFormat#getDateTimeInstance(int, int)这个方法,
不同地区规定的常用日期格式是不一样的, 查询WIKI百科各地日期和时间表示法,得知这个日期格式是台湾的常用日期格式,
问题它怎么知道我是在美国还是在中国台湾, 看getDateTimeInstance方法的源码
getDateTimeInstance()
发现这个方法在Java7之后, 根据操作系统的语言, 判断用户所在的时区,
那现在将WIN10控制面板=>时钟、语言和区域=>添加语言=>更改windows显示语言为英语-美国, 再来看localFormat变成了什么:
us-localFormat
坑爹啊Gson, 使用locale命令查一查线上CentOS7的语言环境
[root@VM_0_9_centos ~]# locale
LANG=en_US.utf8
LC_CTYPE="en_US.utf8"
LC_NUMERIC="en_US.utf8"
LC_TIME="en_US.utf8"
LC_COLLATE="en_US.utf8"
LC_MONETARY="en_US.utf8"
LC_MESSAGES="en_US.utf8"
LC_PAPER="en_US.utf8"
LC_NAME="en_US.utf8"
LC_ADDRESS="en_US.utf8"
LC_TELEPHONE="en_US.utf8"
LC_MEASUREMENT="en_US.utf8"
LC_IDENTIFICATION="en_US.utf8"
LC_ALL=
果然是英文环境, 这样的话yyyy-MM-dd HH:mm:ss,
既无法被UTC时间yyyy-MM-dd’T’HH:mm:ss’Z’适配,
无法被美国默认时间MMM dd, yyyy hh:mm:ss a适配, 最后抛出了JsonSyntaxException.
根治:
改成中文, 并重启系统
// 查看系统拥有语言包
locale -a
zh_CN.UTF-8是简体中文,如果没有zh_CN.UTF-8,就安装语言包,如果存在可以直接设置
// 安装简中语言包
yum install kde-l10n-Chinese
永久修改系统语言
localectl set-locale LANG=zh_CN.UTF8
Exception in thread "main" com.google.gson.JsonSyntaxException: 2018-03-26 22:22:35
at com.google.gson.internal.bind.DateTypeAdapter.deserializeToDate(DateTypeAdapter.java:74)
at com.google.gson.internal.bind.DateTypeAdapter.read(DateTypeAdapter.java:59)
at com.google.gson.internal.bind.DateTypeAdapter.read(DateTypeAdapter.java:41)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:129)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:220)
at com.google.gson.Gson.fromJson(Gson.java:888)
at com.google.gson.Gson.fromJson(Gson.java:853)
at com.google.gson.Gson.fromJson(Gson.java:802)
at com.google.gson.Gson.fromJson(Gson.java:774)
at web.service.JsonTest.main(JsonTest.java:25)
Caused by: java.text.ParseException: Failed to parse date ["2018-03-26 22:22:35']: Invalid time zone indicator ' '
at com.google.gson.internal.bind.util.ISO8601Utils.parse(ISO8601Utils.java:274)
at com.google.gson.internal.bind.DateTypeAdapter.deserializeToDate(DateTypeAdapter.java:72)
... 9 more
Caused by: java.lang.IndexOutOfBoundsException: Invalid time zone indicator ' '
at com.google.gson.internal.bind.util.ISO8601Utils.parse(ISO8601Utils.java:245)
... 10 more
private synchronized Date deserializeToDate(String json) {
try {
return localFormat.parse(json);
} catch (ParseException ignored) {
}
try {
return enUsFormat.parse(json);
} catch (ParseException ignored) {
}
try {
return ISO8601Utils.parse(json, new ParsePosition(0));
} catch (ParseException e) {
throw new JsonSyntaxException(json, e);
}
}```
###
➜ gson git:(master) find ./ -type f -name "*.java" | xargs grep "datePattern"
.//gson/src/main/java/com/google/gson/DefaultDateTypeAdapter.java: DefaultDateTypeAdapter(Class extends Date> dateType, String datePattern) {
.//gson/src/main/java/com/google/gson/DefaultDateTypeAdapter.java: dateFormats.add(new SimpleDateFormat(datePattern, Locale.US));
.//gson/src/main/java/com/google/gson/DefaultDateTypeAdapter.java: dateFormats.add(new SimpleDateFormat(datePattern));
.//gson/src/main/java/com/google/gson/GsonBuilder.java: private String datePattern;
.//gson/src/main/java/com/google/gson/GsonBuilder.java: this.datePattern = gson.datePattern;
.//gson/src/main/java/com/google/gson/GsonBuilder.java: this.datePattern = pattern;
.//gson/src/main/java/com/google/gson/GsonBuilder.java: this.datePattern = null;
.//gson/src/main/java/com/google/gson/GsonBuilder.java: this.datePattern = null;
.//gson/src/main/java/com/google/gson/GsonBuilder.java: addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, factories);
.//gson/src/main/java/com/google/gson/GsonBuilder.java: datePattern, dateStyle, timeStyle,
.//gson/src/main/java/com/google/gson/GsonBuilder.java: private void addTypeAdaptersForDate(String datePattern, int dateStyle, int timeStyle,
.//gson/src/main/java/com/google/gson/GsonBuilder.java: if (datePattern != null && !"".equals(datePattern.trim())) {
.//gson/src/main/java/com/google/gson/GsonBuilder.java: dateTypeAdapter = new DefaultDateTypeAdapter(Date.class, datePattern);
.//gson/src/main/java/com/google/gson/GsonBuilder.java: timestampTypeAdapter = (TypeAdapter) new DefaultDateTypeAdapter(Timestamp.class, datePattern);
.//gson/src/main/java/com/google/gson/GsonBuilder.java: javaSqlDateTypeAdapter = (TypeAdapter) new DefaultDateTypeAdapter(java.sql.Date.class, datePattern);
.//gson/src/main/java/com/google/gson/Gson.java: final String datePattern;
.//gson/src/main/java/com/google/gson/Gson.java: LongSerializationPolicy longSerializationPolicy, String datePattern, int dateStyle,
.//gson/src/main/java/com/google/gson/Gson.java: this.datePattern = datePattern;