2019年九月月 发布的文章

通过HashMap触发DNS检测Java反序列化漏洞

我们常说的反序列化漏洞一般是指readObject()方法处触发的漏洞,而除此以外针对不同的序列化格式又会产生不同的出发点,比如说fastjson会自动运行setter,getter方法。之后又有各种RMI,JNDI姿势去执行命令。现在常见的黑盒检测Java反序列化方式就是执行命令API,比如用一个gadget去执行nslookup xxx 最终通过服务器记录去判断。
但这种方式可能出现的一种问题是,你选择测试的gadget服务器正好没这个jar包或者更新过了,但却有另一个存在漏洞的jar包。这时候单一的gadget构造出的执行命令payload就会漏报。所以为了解决这种问题这里分享一个通过HashMap结合URL触发DNS检查的思路。在实际过程中可以首先通过这个去判断服务器是否使用了readObject()以及能否执行。之后再用各种gadget去尝试试RCE。

阅读剩余部分 –

深入理解Java反射中的invoke方法

什么是反射

反射(Reflection)是Java程序开发语言的特征之一,它允许运行中的Java程序获取自身的信息,并且可以操作类或对象的内部属性。主要是指程序可以访问、检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。

Oracle 官方对反射的解释是:

Reflection enables Java code to discover information about the fields, methods and constructors of loaded classes, and to use reflected fields, methods, and constructors to operate on their underlying counterparts, within security restrictions.
The API accommodates applications that need access to either the public members of a target object (based on its runtime class) or the members declared by a given class. It also allows programs to suppress default reflective access control.

简而言之,通过反射,我们可以在运行时获得程序或程序集中每一个类型的成员和成员的信息。程序中一般的对象的类型都是在编译期就确定下来的,而 Java 反射机制可以动态地创建对象并调用其属性,这样的对象的类型在编译期是未知的。所以我们可以通过反射机制直接创建对象,即使这个对象的类型在编译期是未知的。

反射的核心是 JVM 在运行时才动态加载类或调用方法/访问属性,它不需要事先(写代码的时候或编译期)知道运行对象是谁。

Java 反射主要提供以下功能:

  • 在运行时判断任意一个对象所属的类;
  • 在运行时构造任意一个类的对象;
  • 在运行时判断任意一个类所具有的成员变量和方法(通过反射甚至可以调用private方法);
  • 在运行时调用任意一个对象的方法

重点:是运行时而不是编译时

反射的主要用途

很多人都认为反射在实际的 Java 开发应用中并不广泛,其实不然。当我们在使用 IDE(如 Eclipse,IDEA)时,当我们输入一个对象或类并想调用它的属性或方法时,编译器就会自动列出它的属性或方法,这里就会用到反射,当然也有的用到了语法树。

在 Web 开发中,我们经常能够接触到各种可配置的通用框架。为了保证框架的可扩展性,它们往 往借助 Java 的反射机制,根据配置文件来加载不同的类。举例来说,Spring 框架的依赖反转 (IoC),便是依赖于反射机制。

反射invoke实现原理

invoke方法用来在运行时动态地调用某个实例的方法
它的实现代码如下:

1.权限检查

通过代码我们可以看到,首先invoke方法会检查AccessibleObject的override属性的值。而AccessibleObject类是实现了AnnotatedElement,它是Field、Method和Constructor对象的基类。它提供了将反射的对象标记为在使用时取消默认Java语言访问控制检查的能力。对于公共成员、默认(打包)访问成员、受保护成员和私有成员,在分别使用 Field、Method或Constructor对象来设置或获得字段、调用方法,或者创建和初始化类的新实例的时候,会执行访问检查。
override的值默认是false,表示需要权限调用规则。我们常使用的setAccessible方法就是将其设置为true,从而忽略权限规则,调用方法时无需检查权限。
继续往下看,当其需要权限调用则走Reflection.quickCheckMemberAccess,检查方法是否为public,如果是的话跳出本步。如果不是public方法,那么用Reflection.getCallerClass()方法获取调用这个方法的Class对象

这是一个native方法,我们从openJDK源码中去找它的JNI入口(Reflection.c)

具体实现在hotspot/src/share/vm/prims/jvm.cpp
屏幕快照 2019-09-08 下午4.10.28

获取了这个Class对象caller后用checkAccess方法做一次快速的权限校验

这里主要是进行一些基本的权限检查,以及使用缓存机制。

阅读剩余部分 –