From 1938e4d9cd9c304cb6dd6d9b1a056ace4ef6dba3 Mon Sep 17 00:00:00 2001 From: Alexander Ponticello Date: Sun, 19 Jan 2020 19:04:22 +0100 Subject: [PATCH] Markdown images are hard --- writeups/aliponti/otw_advent_bonanza19.md | 2 +- writeups/aliponti/ructfe19.md | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/writeups/aliponti/otw_advent_bonanza19.md b/writeups/aliponti/otw_advent_bonanza19.md index 158a8a0..f253c6d 100644 --- a/writeups/aliponti/otw_advent_bonanza19.md +++ b/writeups/aliponti/otw_advent_bonanza19.md @@ -14,7 +14,7 @@ The second Easter egg had no description at all just the link to the CTFs websit For Easter egg number 3 we got a link to a tweet by the organizers showing a picture of a matrix barcode that had the characteristic corner elements of a QR-code. So i scanned it, obtaining the resulting string `137:64:137:154:171:146:63:175`. This fits the format of an IPv6 address. So I checked, but no server was responding to this IP. I also tried converting the numbers to ASCII symbols, since the numbers would be in the range of octal numbers for ASCII characters. but the result did not look like anything meaningful to me `_4_lyf3}`. What I missed, but luckily not one of my colleagues who solved the challenge in the end, is that the middle part of the matrix code was in fact not part of the QR-encoding, but is part is the position marker for another matrix encoding known as [Aztec Code](https://en.wikipedia.org/wiki/Aztec_Code). So what we have after all is a matrix barcode polyglot, since the code is both a valid QR-Code as well as Aztec-Code. This is possible because such codes have error correcting properties that allow for extra stuff to be included while keeping the code readable. [1](https://hackaday.com/2011/08/11/how-to-put-your-logo-in-a-qr-code/) -![Easter Egg 3](otw_advent19/easter_egg3.jpeg) +![Easter Egg 3](otw_advent_bonanza19/easter_egg3.jpeg) ## Time report diff --git a/writeups/aliponti/ructfe19.md b/writeups/aliponti/ructfe19.md index 71f44c7..19561eb 100644 --- a/writeups/aliponti/ructfe19.md +++ b/writeups/aliponti/ructfe19.md @@ -14,7 +14,7 @@ This already made it clear what we want to achieve, namely access other users (t So our first thought was that maybe we are able to generate a valid session for another user. We generated some sessions for ourself, trying to find some pattern in it but without any luck. So we looked further into the code in order to understand, how sessions generation was done and where the hardcoded secret was used. But by doing so, we stumbled over something even more interesting. The service included a class with the sounding name `RuntimeClassLoader`, which did exactly as its name suggests, loading classes at runtime. -![RuntimeClassLoader class](ructfe19/fclass_loader.png) +![RuntimeClassLoader class](ructfe19/class_loader.png) This is known to cause problems [1](https://stackoverflow.com/questions/42720149/what-is-a-purpose-of-the-secureclassloader), also the IDE I used highlighted already that the `defineClass` method used had been deprecated. If we are able to inject arbitrary bytecode into this method, we have a potential RCE. We found one usage of the method in question in the `Decoder` class `isValidKey` method, which gets its input from the `isValid` method of the `RegisterData` class. This class is annotated as serializable. We figured out that the registers frontend sends the data as a json-encoded serialized Java object. So in order in get our custom class loaded we have to compile it, encode it and send it to the `/register` endpoint as a custom filed. Another important puzzle piece was found in the `decodeMessage` method of the `Decoder` class. Here, the previously input class gets instanciated, resulting the execution of its constructor method. We can use this to execute arbitrary code and retrieve the output via a call to the `/info` endpoint. @@ -22,7 +22,7 @@ This is known to cause problems [1](https://stackoverflow.com/questions/42720149 In order to exploit this, the first thing to do is write a Java class where to constructor contains the code one wants to execute. In this case, we retrieved a list of users and read their message data containing the flags. We made use of the service's OR mapping functionality. The so build Java class can the be compiled, also using the pre-build Java jar. By doing so we obtain the Java bytecode. This can then be send to the `/register` endpoint, along with the other necessary data. We did so using a python script and the requests library. The output of the code can then be accessed via the `/info` endpoint. -![Java class used in the exploit](ructfe19/fexploit_class.png) +![Java class used in the exploit](ructfe19/exploit_class.png) #### Considerations @@ -32,17 +32,17 @@ Since this was an attack-defense CTF, there are some additional steps one might Before exploiting the services of other teams, we tried to fix our own service, since we expected other teams to copy our exploit rather quickly. So we deployed a quick-and-dirty fix by filtering out every request that was larger than a certain threshold. We check typical GS requests to the `/register` endpoint and noticed that they where significantly smaller than requests produced by our exploit. This fix proved sufficient for the rest of the CTF since it constrained other teams well enough in the exploiting that we did not loose any flags. Of course, in a real-world scenario this is not an ideal solution. A better patch would be letting `RuntimeClassLoader` inherit from `SecureClassLoader` provided by Java/Kotlin and restrain the loaded class accordingly. This could prove efficient since a standard class used by this service does not run any code so restrictions could be quite strict. -![Patched RuntimeClassLoader class](ructfe19/fpatch_classloader.png) +![Patched RuntimeClassLoader class](ructfe19/patch_classloader.png) ### Further developing the exploit When the fix was deployed and the first version of the exploit was busy stealing flags, we had still plenty of time left in the CTF to become creative with this RCE. The most promising idea that came up was, using the RCE to patch other teams services in order for them to not be vulnerable to the exploit any more. This should prevent other teams from exploiting weaker teams who did not patch their service and where therefore an easy target. Of course, in order for us to be able to still exploit the service, we implemented a backdoor in our patch. So we patched the `RuntimeClassLoader` class to include a blacklist for the `loadClass` method, filtering out malicious functionality such as accessing user messages. The backdoor was a simple hard coded string that let every input get through. We then modified our exploit Java class to replace the `RuntimeClassLoader` in the original service jar with our adapted version. -![Placing the modified class in the jar](ructfe19/fpatch_class.png) +![Placing the modified class in the jar](ructfe19/patch_class.png) Lastly, we had to force the container to restart to use the patched version of the code. This was easy, since the Docker-compose configuration used had `restart: always` set, meaning the container restarts automatically once the executed program terminates. So we could just call `System.exit(0)` inside our malicious Java class. During the CTF, other teams adapted their exploits to bypass our implemented patch, which in order made us adapt our blacklist and repatch services through our backdoor and so on and so fourth. -![Final version of the patch blacklist](ructfe19/fpatch_advances.png) +![Final version of the patch blacklist](ructfe19/patch_advances.png) ### The take away -- 2.43.0