JavaSec系列 - 5. SpEL注入

本章源码: https://github.com/hey3e/JavaSec-Code/tree/main/javasec5

先前,我们在系列2中jdk>8u191的环境下实现JNDI注入时,使用到了EL表达式。SpEL,是EL的一种,”Sp”代表”Spring”,即用于Spring的表达式。而最近,Spring Cloud爆出两个RCE,其原理均为SpEL注入,因此我们下面通过接触这两个实例来了解SpEL注入的实现。

Read more

JNI 101

本章参考: 《深入理解Android 卷Ⅰ》

在逆向so文件时,我们经常遇到/发现:

  1. 找不到Java层native函数对应的JNI函数;
  2. 要把JNI函数的第一个参数改为JNIEnv *env以便识别;
  3. 加载so时,频繁调用NewStringUTFReleaseStringUTFChars等字符串函数。

在深入理解JNI (Java Native Interface) 之后,我们可以解释上述现象。

Read more

JavaSec系列 - 2. JNDI注入

本章源码: https://github.com/hey3e/JavaSec-Code/tree/main/javasec2

命名与目录系统 (Naming and Directory services),如RMI (Remote Method Invocation)、LDAP (Lightweight Directory Access Protocol) 等,能够以类似字典key-valuename-object形式对对象进行存储,使得我们可以通过名称来查询并访问对象。JNDI (Java Naming and Directory Interface) 便是该过程的接口。

结合上一章的知识,我们考虑在系统中存储对象序列化后的字节流,当用户进行查询时,系统返回对应的字节流,用户再进行反序列化获取对象。但在实际场景中,如果对象过大,采用该方式往往会给系统带来一定的负担。

于是,JNDI使用Naming References的方式进行存储,此时,name-object中的object并非对象本身,而是对象的引用Reference,其中包含对象名及其真正被存放的地址codebase。当用户进行查询时,系统返回Reference,用户解析后再从codebase获取对象。不过这里说的不太严谨,后面会进行补充

不过,上述从远程codebase加载对象的方式存在许多安全问题,随着jdk版本的迭代,系统对codebase已逐渐不再信任,JNDI受到越来越多的限制。我们下面看一下各版本下JNDI如何实现。

Read more

JavaSec系列 - 1. 反序列化与反射

本章源码: https://github.com/hey3e/JavaSec-Code/tree/main/javasec1

(1)序列化与反序列化

在Java中,我们创建的对象会随着其JVM的销毁而销毁。但有时,我们希望能在其他JVM、或是其他机器上复用这个对象。序列化允许我们将Java对象转换为字节流,便于存储到本地,以及通过网络发送给其他机器。而反序列化允许我们重新将序列化的字节流还原为Java对象。

Read more