InsoSystems was a pwn challenge from Insomni’hack teaser 2023.
Leak the base address of the binary with an md5 out of bounds read. Exploit a
buffer overflow using ROP to leak the address of the libc then ret2main. And
finally re-exploit this buffer overflow to call
system and get a shell.
In this challenge, we are given all the source code of the application as well as the configuration files (nginx, docker, …) allowing to deploy it locally.
The organization of the project is in this form:
So we are dealing with a symfony environment (recognized by the presence of a
composer.json and a
.env file). Before going to look at the source code of the application and play with PHP, we will take a look at the configuration files. Indeed, in the configuration files, we can notice several things:
readflag : The binary will fetch the flag in /root, so we will absolutely need an RCE
redis.conf : There is a redis service, we will probably have to get an SSRF to interact with it
proxy.conf : A reverse proxy has been set up on the application
This is a long write-up. It’s not particularly technical, I just wanted to show how I reverse-engineering this challenge fully statically using Binary Ninja.
The archive contains two files,
checker.exe, so we can already guess that the
.exe is a user-mode application making requests (spoil : IRPs) to the
.sys kernel driver for flag verification.
Since we can make the (educated) guess that most of the code is inside the driver, let’s take a quick look inside
checker.exe. Quick tip if you’re looking for the call to the
main function inside the
_start in a Portable Executable :
babyfile is a file stream exploitation I did during the SECCON CTF 2022 Quals event. I didn’t succeed to flag it within the 24 hours :(. But anyway I hope this write up will be interesting to read given I show another way to gain code execution – I have not seen before – based on
_IO_obstack_jumps! The related files can be found here. If you’re not familiar with file stream internals, I advice you to read my previous writeups about file stream exploitation, especially this one and this other one.
- Populate base buffer with heap addresses with the help of
- Make both input and output buffer equal to the base buffer with the help of
- Partial overwrite on right pointers to get a libc leak by simply flushing the file stream.
- Leak a heap address by printing a pointer stored within the main_arena.
_IO_obstack_overflow ends up calling a function pointer stored within the file stream we have control over which leads to a call primitive (plus control over the first argument). Then I just called