经过一段时间的琢磨与反思,以及重读了大量之前看不懂的反序列化文章,目前为止算是对java反序列化这块有了一个阶段性的小理解。

目前为止,发送的所有java反序列化的漏洞中。主要需要两个触发条件:

1、反序列化的攻击入口

2、反序列化的pop攻击链

这两个条件缺一不可。网上大量分析gadgets的文章方法,让人误以为有攻击链就可以反序列化。其实这块是有一定的误导性的。在我最初研究反序列化的时候,我觉得攻击链是最重要的。其实不然,反序列化的攻击入口才是至关重要的。因为现阶段的java环境加上java所在的金融、保险等大型项目中,往往组件jar包和jdk版本是更新最缓慢的,因为这块需要测试大量的兼容性,对大型java项目来说,攻击链基本上一定存在,除非该java程序最近才被开发、部署,且开发人员喜欢用最新的版本软件包。

0X01攻击入口

目前其实在白盒过程中要比较快的查找攻击入口的话。可以全局搜索是否有以下这类方法函数:

ObjectInputStream.readObject
ObjectInputStream.readUnshared
XMLDecoder.readObject
Yaml.load
XStream.fromXML
ObjectMapper.readValue
JSON.parseObject

通过搜到到这些函数方法所在位置,再反向追踪是否可控输入流,如果可控,那么恭喜,反序列化的第一步已经完成。

拿我前几篇的文章来讲,XMLDecoder.readObject这块函数其实可以当做入口来看,至于为啥可以执行命令,你就当他当做system()函数来看,如果要更加深层的知道为啥可以执行命令,就可以跟下去,不过跟下去的话,属于更加底层的研究。

我们做安全其实可以分好几个攻击层次。

1、攻击普通开发者(这里的普通开发者可以指敏捷开发人员,大部分使用框架,或者现有函数库来使用,极大的加快了开发速度,但是对于框架具体底层功能实现可能不会特意去了解,大部分通过开发手册和api接口即可了解表层意义上的功能实现)

2、框架、底层库开发者(这类开发人员往往开发不是为了某个特定的东西,往往是为了帮助大量普通开发者更快、更短的代码实现一个功能,减少普通开发者的代码量,降低程序开发门槛)

3、系统层函数开发者(这类的开发者衔接的是高级面向对象的语言与底层汇编,甚至指令集之间的库函数)

随着攻击层次的加高,我们的攻击范围也会越广。

在这三个层次里,往往攻击入口点在1和2都会出现,更多的是出现在1层,而gadget在1和2也会出现,但是往往出现更多的在2层。

拿weblogic的xml反序列化来讲,把oracle的开发人员当做普通的拿现有开源框架库基础上开发的人员来看的话,他们造成反序列化的攻击入口点就在1层面,序列化的gadget在2层面。

在cve-2019-2725中,_async目录下的其实就是一个攻击入口,因为攻击入口和wls-wsat相似,所以后续分析和10271很像。

但是由于有10271补丁在,所以在2725中需要利用未在黑名单里的标签来绕过补丁。

0X02POP攻击链

java的pop攻击链不是说寻找难度不大,而是在现有yso工具在的情况下,对已有的漏洞利用来说,已经方便了很多。但是寻找一个新的pop链还是很困难的。

CommonsCollections1的gadget来说吧,因为网上这个的分析文章最多,所以也是我了解的比较熟悉的一个gadget。

这个漏洞的最关键地方是org.apache.commons.collections.functors.InvokerTransformer类下面的transform函数

public Object transform(Object input) {
        if (input == null) {
            return null;
        } else {
            try {
                Class cls = input.getClass();
                Method method = cls.getMethod(this.iMethodName, this.iParamTypes);
                return method.invoke(input, this.iArgs);
            } catch (NoSuchMethodException var5) {
                throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' does not exist");
            } catch (IllegalAccessException var6) {
                throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' cannot be accessed");
            } catch (InvocationTargetException var7) {
                throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' threw an exception", var7);
            }
        }
    }

然后更关键的地方是

 Class cls = input.getClass();
 Method method = cls.getMethod(this.iMethodName, this.iParamTypes);
 return method.invoke(input, this.iArgs);

为啥这块危险呢,首先这个地方利用了java的反射机制,如果你不了解,你可以直接死记硬背或者理解成这样子写就是有一定问题的,等同于system(xxx),而xxx根据transform的形参来看,也就是input是我们可控的。且之间没有任何过滤。

this.iMethodName, this.iParamTypes

    public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) {
        this.iMethodName = methodName;
        this.iParamTypes = paramTypes;
        this.iArgs = args;
    }

这两个读一下InvokerTransformer类的实现代码,发现初始化InvokerTransformer的时候,这两个也可控。所以这块是有可能成为POP链的。

public class InvokerTransformer implements Transformer, Serializable {

根据类的接口来看,这个类是可以序列化的,所以条件都达成。

但是这个类没有readObject的方法,所以payload还需要一个能触发这个反序列化类的地方。

根据对yso的源码查看,我发现CommonsCollections系列的readObject都是在sun.reflect.annotation.AnnotationInvocationHandler里触发readObject。

至于这个类,是在gadget.java里写死的。

public static final String ANN_INV_HANDLER_CLASS = "sun.reflect.annotation.AnnotationInvocationHandler";

在CommonsCollections1里

final InvocationHandler handler = Gadgets.createMemoizedInvocationHandler(mapProxy);

但是目前的构造还需要依赖于触发Map中某一项去调用setValue(),我们需要想办法通过readObject()直接触发
我们观察到java运行库中有这样一个类AnnotationInvocationHandler,这个类有一个成员变量memberValues是Map类型,如下所示
\openjdk\jdk\src\share\classes\sun\reflect\annotation\AnnotationInvocationHandler.java

因此,我们只需要使用前面构造的Map来构造AnnotationInvocationHandler,进行序列化,当触发readObject()反序列化的时候,就能实现命令执行。另外需要注意的是,想要在调用未包含的package中的构造函数,我们必须通过反射的方式,综合生成任意代码执行的payload的代码如下

中途遇到个比我写的好的。可以参考这个来看。

http://blog.0kami.cn/2019/10/24/study-java-deserialized-commonscollections3-1/

最新文章

  1. ORACLE数据库存储空间使用情况查询
  2. PHPCMS \phpsso_server\phpcms\modules\phpsso\index.php、\api\get_menu.php Authkey Leakage
  3. What he did
  4. iOS 开发知识小集(1)
  5. phonegap配置启动动画
  6. 九度OJ 1480 最大上升子序列和 -- 动态规划
  7. bootstrap和jQuery.Gantt的css冲突问题
  8. Android XML解析
  9. socket编程原理
  10. jdk1.6下载页面
  11. USACO Section 2.1 The Castle
  12. 体验CSDN-Markdown
  13. Win7硬盘的AHCI模式
  14. mysql进阶(十四) 批量更新与批量更新多条记录的不同值实现方法
  15. matlab工作空间数据导入simulink
  16. 用CSS解决一个让人头疼的问题
  17. 玩转X-CTR100 l STM32F4 l FPU单精度浮点性能测试
  18. IntelliJ IDEA总是提示Cannot resolve symbol
  19. f5健康检查
  20. $python用装饰器实现一个计时器

热门文章

  1. SpringMVC利用AOP实现自定义注解记录日志
  2. inline-block默认间距
  3. python自动华 (八)
  4. jQuery 操作一览表
  5. 005_STM32程序移植之_RC522读卡模块
  6. Hihocoder #1142 : 三分·三分求极值
  7. thinkphp5 大量数据批量插入数据库的解决办法
  8. Leetcode题目338:比特位计数(中等)
  9. Linux设备驱动程序 之 内存池
  10. mysql CONCAT函数