phpggc

yoseri

java

Java 框架 – java 中间件 — java服务漏洞(RMI)

3 个点是 java漏洞核心

我总结一下:

JVM的加载

一切的Java类都必须经过JVM加载后才能运行,而ClassLoader的主要作用就是Java类文件的加载

ClassLoader类有如下核心方法:

  1. loadClass(加载指定的Java类)
  2. findClass(查找指定的Java类)
  3. findLoadedClass(查找JVM已经加载过的类)
  4. defineClass(定义一个Java类)
  5. resolveClass(链接指定的Java类)

Java类动态加载方式

Java类加载方式分为显式和隐式,显式即我们通常使用Java反射或者ClassLoader来动态加载一个类对象,而隐式指的是类名.方法名()或new类实例。显式类加载方式也可以理解为类动态加载,我们可以自定义类加载器去加载任意的类。

常用的类动态加载方式:

// 反射加载TestHelloWorld示例
Class.forName("com.anbai.sec.classloader.TestHelloWorld");

// ClassLoader加载TestHelloWorld示例
this.getClass().getClassLoader().loadClass("com.anbai.sec.classloader.TestHelloWorld");

Class.forName("类名")默认会初始化被加载类的静态属性和方法,如果不希望初始化类可以使用Class.forName("类名", 是否初始化类, 类加载器),而ClassLoader.loadClass默认不会初始化类方法。

Java反射机制

Java反射(Reflection)是Java非常重要的动态特性,通过使用反射我们不仅可以获取到任何类的成员方法(Methods)、成员变量(Fields)、构造方法(Constructors)等信息,还可以动态创建Java类实例、调用任意的类方法、修改任意的类成员变量值等。Java反射机制是Java语言的动态性的重要体现,也是Java的各种框架底层实现的灵魂。

java反射操作的是java.lang.Class对象,所以我们需要先想办法获取到Class对象,通常我们有如下几种方式获取一个类的Class对象:

  1. 类名.class,如:com.anbai.sec.classloader.TestHelloWorld.class。
  2. Class.forName("com.anbai.sec.classloader.TestHelloWorld")。
  3. classLoader.loadClass("com.anbai.sec.classloader.TestHelloWorld");

知识点补充:

JAVA中类、实例与Class对象

  java提供了下面几种获取到类的Class对象的方法:

  1) 利用对象实例调用getClass()方法获取该对象的Class实例;
  2) 使用Class类的静态方法forName(“包名+类名”),用类的名字获取一个Class实例

  3)运用 类名.class 的方式来获取Class实例;

我一直有个问题!1 对象模板(就是平常说的某某类) 2 实例 就是创建-个对象

对象:

class Book {
public String name;
public String author;
public String isbn;
public double price;
}

实例:

Book ming = new Book();

定义了class,只是定义了对象模版,而要根据对象模版创建出真正的对象实例,必须用new操作符。

这就是解决了我刚刚看代码里的一个问题!

// 获取Runtime类对象
Class runtimeClass1 = Class.forName("java.lang.Runtime");

这个只是获取了类对象! 也就是那个 class{}

那接下来肯定就要获取他的实例了!

这里补一补大一的java课! java是不能变量覆盖的!在一个作用域里!

所以我们随便实例化下:

// 创建Runtime类示例,等价于 Runtime rt = new Runtime();
Object runtime2222 = constructor.newInstance();

image-20210525183456604

java文件系统

img

补充

什么是Native Method

一个Native Method就是一个java调用非java代码的接口。一个Native Method是这样一个java的方法:该方法的实现由非java语言实现,比如C。

java命令执行

在Java中我们通常会使用java.lang.Runtime类的exec方法来执行本地系统命令。

Runtime命令执行

java.lang.UNIXProcess.<init>(UNIXProcess.java:247)
java.lang.ProcessImpl.start(ProcessImpl.java:134)
java.lang.ProcessBuilder.start(ProcessBuilder.java:1029)
java.lang.Runtime.exec(Runtime.java:620)
java.lang.Runtime.exec(Runtime.java:450)
java.lang.Runtime.exec(Runtime.java:347)
org.apache.jsp.runtime_002dexec2_jsp._jspService(runtime_002dexec2_jsp.java:118)

通过观察整个调用链我们可以清楚的看到exec方法并不是命令执行的最终点,执行逻辑大致是:

  1. Runtime.exec(xxx)
  2. java.lang.ProcessBuilder.start()
  3. new java.lang.UNIXProcess(xxx)
  4. UNIXProcess构造方法中调用了forkAndExec(xxx) native方法。
  5. forkAndExec调用操作系统级别fork->exec(*nix)/CreateProcess(Windows)执行命令并返回fork/CreateProcess的PID。

有了以上的调用链分析我们就可以深刻的理解到Java本地命令执行的深入逻辑了,切记Runtime和ProcessBuilder并不是程序的最终执行点!

ProcessBuilder命令执行

UNIXProcess/ProcessImpl

ORM 实例教程

Object Relational Mapping

ORM 实例教程

Java 序列化/反序列化

在Java中实现对象反序列化非常简单,实现java.io.Serializable(内部序列化)或java.io.Externalizable(外部序列化)接口即可被序列化,其中java.io.Externalizable接口只是实现了java.io.Serializable接口。

反序列化类对象时有如下限制:

  1. 被反序列化的类必须存在。
  2. serialVersionUID值必须一致。

ObjectInputStream、ObjectOutputStream

java.io.ObjectOutputStream类最核心的方法是writeObject方法,即序列化类对象。

java.io.ObjectInputStream类最核心的功能是readObject方法,即反序列化类对象。

所以,只需借助ObjectInputStream和ObjectOutputStream类我们就可以实现类的序列化和反序列化功能了。

cc链

Apache Commons Collections反序列化漏洞

Apache Commons是Apache开源的Java通用类项目在Java中项目中被广泛的使用,Apache Commons当中有一个组件叫做Apache Commons Collections,主要封装了Java的Collection(集合)相关类对象。

通过接口实现查询,能获取到 ConstantTransformer、invokerTransformer、ChainedTransformer、TransformedMap 这些类均实现了 Transformer接口

RMI

RMI(Remote Method Invocation)即Java远程方法调用,RMI用于构建分布式应用程序,RMI实现了Java程序之间跨JVM的远程通信。

socket连接方式

既然RMI使用了反序列化机制来传输Remote对象,那么可以通过构建一个恶意的Remote对象,这个对象经过序列化后传输到服务器端,服务器端在反序列化时候就会触发反序列化漏洞。

RMI两种协议

JRMP接口的两种常见实现方式:

  1. JRMP协议(Java Remote Message Protocol),RMI专用的Java远程消息交换协议。
  2. IIOP协议(Internet Inter-ORB Protocol) ,基于 CORBA 实现的对象请求代理协议。

JNDI

JNDI(Java Naming and Directory Interface)是Java提供的Java 命名和目录接口。通过调用JNDI的API应用程序可以定位资源和其他程序对象。JNDI是Java EE的重要部分,需要注意的是它并不只是包含了DataSource(JDBC 数据源),JNDI可访问的现有的目录及服务有:JDBC、LDAP、RMI、DNS、NIS、CORBA。

JAVAWEB

Filter和Servlet的总结

Filter和Servlet

对于基于Filter和Servlet实现的简单架构项目,代码审计的重心集中于找出所有的Filter分析其过滤规则,找出是否有做全局的安全过滤、敏感的URL地址是否有做权限校验并尝试绕过Filter过滤。第二点则是找出所有的Servlet,分析Servlet的业务是否存在安全问题,如果存在安全问题是否可以利用?是否有权限访问?利用时是否被Filter过滤等问题,切勿看到Servlet、JSP中的漏洞点就妄下定论,不要忘了Servlet前面很有可能存在一个全局安全过滤的Filter。

Filter和Servlet都是Java Web提供的API,简单的总结了下有如下共同点。

  1. Filter和Servlet都需要在web.xml或注解(@WebFilter、@WebServlet)中配置,而且配置方式是非常的相似的。
  2. Filter和Servlet都可以处理来自Http请求的请求,两者都有request、response对象。
  3. Filter和Servlet基础概念不一样,Servlet定义是容器端小程序,用于直接处理后端业务逻辑,而Filter的思想则是实现对Java Web请求资源的拦截过滤。
  4. Filter和Servlet虽然概念上不太一样,但都可以处理Http请求,都可以用来实现MVC控制器(Struts2和Spring框架分别基于Filter和Servlet技术实现的)。
  5. 一般来说Filter通常配置在MVC、Servlet和JSP请求前面,常用于后端权限控制、统一的Http请求参数过滤(统一的XSS、SQL注入、Struts2命令执行等攻击检测处理)处理,其核心主要体现在请求过滤上,而Servlet更多的是用来处理后端业务请求上。

JSP

JSP(JavaServer Pages) 是与 PHP、ASP、ASP.NET 等类似的脚本语言,JSP是为了简化Servlet的处理流程而出现的替代品,早期的Java EE因为只能使用Servlet来处理客户端请求而显得非常的繁琐和不便,使用JSP可以快速的完成后端逻辑请求。

JSP 九大对象

变量名 类型 作用
pageContext PageContext 当前页面共享数据,还可以获取其他8个内置对象
request HttpServletRequest 客户端请求对象,包含了所有客户端请求信息
session HttpSession 请求会话
application ServletContext 全局对象,所有用户间共享数据
response HttpServletResponse 响应对象,主要用于服务器端设置响应信息
page Object 当前Servlet对象,this
out JspWriter 输出对象,数据输出到页面上
config ServletConfig Servlet的配置对象
exception Throwable 异常对象

从本质上说 JSP 就是一个Servlet ,因为 jsp 文件最终会被编译成 class 文件,而这个 class 文件实际上就是一个特殊的Servlet 。

invoke 动态调用

动态调用方法!

https://zhidao.baidu.com/question/394854109.html