IT and security stuff

Metasploit Community CTF Writeup

Everybody into IT Security knows about The Metasploit Framework from Rapid7. This weekend I had the chance to attend their own CTF event partnered with THM. This is a HackQuest CTF where teams have to pentest a machine running several services on ports up to 35000.

Access & Enumeration

The first step was to gain access to a Kali box using an SSH key.
Step 2: Attack!

We have a victim IP so let’s begin enumeration.

┌──(kali㉿kali)-[~/neoh]
└─$ cat nmap.md  
# Nmap 7.92 scan initiated Sat Dec  4 01:03:10 2021 as: nmap -sSCV -p- -T4 -oN nmap.md 172.17.26.149
Nmap scan report for 172.17.26.149
Host is up (0.00059s latency).
Not shown: 65516 closed tcp ports (reset)
PORT      STATE SERVICE    VERSION
80/tcp    open  http       Werkzeug httpd 2.0.1 (Python 3.9.7)
|_http-server-header: Werkzeug/2.0.1 Python/3.9.7
|_http-title: Metasploit CTF
443/tcp   open  http       Apache httpd 2.4.51
| http-git: 
|   172.17.26.149:443/.git/
|     Git repository found!
|     Repository description: Unnamed repository; edit this file 'description' to name the...
|_    Last commit message: More enthusiasm 
|_http-server-header: Apache/2.4.51 (Debian)
|_http-title: Site doesn't have a title (text/html).
8080/tcp  open  http       WSGIServer 0.2 (Python 3.8.10)
|_http-server-header: WSGIServer/0.2 CPython/3.8.10
|_http-title: Cookies Galore
10010/tcp open  rxapi?
| fingerprint-strings: 
|   GenericLines: 
|     HTTP/1.1 400 Bad Request
|   GetRequest: 
|     HTTP/1.0 200 OK
|     X-Frame-Options: SAMEORIGIN
|     X-XSS-Protection: 1; mode=block
|     X-Content-Type-Options: nosniff
|     X-Download-Options: noopen
|     X-Permitted-Cross-Domain-Policies: none
|     Referrer-Policy: strict-origin-when-cross-origin
|     Link: </assets/application-b8c697e38f5ecf278f5ea80d758553eae08a5635194a002f5b5dc51db0ef1145.css>; rel=preload; as=style; nopush,</packs/js/application-e39138e5c24b0104f8e3.js>; rel=preload; as=script; nopush
|     Content-Type: text/html; charset=utf-8
|     ETag: W/"44b03926e2ba708aa4e9f7b36d44edbf"
|     Cache-Control: max-age=0, private, must-revalidate
|     Set-Cookie: 321dece65c1d444b49c690630b2faca0d6e2f6e41cc5dacb19f2242ea6f745a44437e0f524427181e28f71d651f5982d9e36ba9542824f09cb103c7515d50a21ad2e4edd30573074c2d62296e6fb6ac5a4460060a646d108ede4a1793038eb061e8b27194ce54b5fbd3804f7ec76182fda465e6c51fc822eacc230b2f1721294=NFYh7P05VazNRGtDJdG2lA2wVe7IODPDZFD%2F7pb%2BifJoVU1oDhO
|   HTTPOptions: 
|     HTTP/1.0 404 Not Found
|     Content-Type: text/html; charset=UTF-8
|     X-Request-Id: b01c438b-5b8c-4771-af66-5d8b31cc8563
|     X-Runtime: 0.002082
|     Content-Length: 1722
|     <!DOCTYPE html>
|     <html>
|     <head>
|     <title>The page you were looking for doesn't exist (404)</title>
|     <meta name="viewport" content="width=device-width,initial-scale=1">
|     <style>
|     .rails-default-error-page {
|     background-color: #EFEFEF;
|     color: #2E2F30;
|     text-align: center;
|     font-family: arial, sans-serif;
|     margin: 0;
|     .rails-default-error-page div.dialog {
|     width: 95%;
|     max-width: 33em;
|     margin: 4em auto 0;
|     .rails-default-error-page div.dialog > div {
|     border: 1px solid #CCC;
|     border-right-color: #999;
|     border-left-color: #999;
|     border-bottom-color: #BBB;
|     border-top: #B00100 solid 4px;
|     border-top-left-radius: 9px;
|     border-top-right-radius: 9px;
|_    background-color: white
11111/tcp open  http       Thin httpd
|_http-server-header: thin
| http-title: Web App
|_Requested resource was http://172.17.26.149:11111/index
12380/tcp open  http       Apache httpd 2.4.49 ((Debian))
|_http-server-header: Apache/2.4.49 (Debian)
|_http-title: Site doesn't have a title (text/html).
15000/tcp open  hydap?
| fingerprint-strings: 
|   GenericLines: 
|     Welcome to the Student Database Management System!
|     Time is 2021-12-04 01:03:13 +0000.
|     Pick one of the following options:
|     Create new student record
|     Show student records
|     Update an existing record
|     Delete student record
|     Exit
|     Input: 
|     Error. Unrecognised choice: 0
|     Pick one of the following options:
|     Create new student record
|     Show student records
|     Update an existing record
|     Delete student record
|     Exit
|     Input: 
|     Error. Unrecognised choice: 0
|     Pick one of the following options:
|     Create new student record
|     Show student records
|     Update an existing record
|     Delete student record
|     Exit
|     Input:
|   GetRequest: 
|     Welcome to the Student Database Management System!
|     Time is 2021-12-04 01:03:24 +0000.
|     Pick one of the following options:
|     Create new student record
|     Show student records
|     Update an existing record
|     Delete student record
|     Exit
|     Input: 
|     Error. Unrecognised choice: 0
|     Pick one of the following options:
|     Create new student record
|     Show student records
|     Update an existing record
|     Delete student record
|     Exit
|     Input: 
|     Error. Unrecognised choice: 0
|     Pick one of the following options:
|     Create new student record
|     Show student records
|     Update an existing record
|     Delete student record
|     Exit
|     Input:
|   NULL: 
|     Welcome to the Student Database Management System!
|     Time is 2021-12-04 01:03:13 +0000.
|     Pick one of the following options:
|     Create new student record
|     Show student records
|     Update an existing record
|     Delete student record
|     Exit
|_    Input:
15010/tcp open  http       Thin httpd
|_http-server-header: thin
| http-title: Site doesn't have a title (text/html;charset=utf-8).
|_Requested resource was http://172.17.26.149:15010/index
15122/tcp open  ssh        OpenSSH 8.6 (protocol 2.0)
| ssh-hostkey: 
|   3072 30:06:8b:5a:9b:7c:1c:1c:93:7a:bb:57:0a:1a:e4:e0 (RSA)
|   256 49:c0:84:75:38:b1:6b:50:4c:bd:37:77:c5:64:78:67 (ECDSA)
|_  256 f6:07:cf:3a:4a:49:db:2e:3b:a8:84:4e:c4:19:12:0a (ED25519)
20000/tcp open  http       SimpleHTTPServer 0.6 (Python 3.7.3)
|_http-server-header: SimpleHTTP/0.6 Python/3.7.3
|_http-title: Site doesn't have a title (text/html).
20001/tcp open  microsan?
| fingerprint-strings: 
|   DNSStatusRequestTCP, DNSVersionBindReqTCP, FourOhFourRequest, GenericLines, GetRequest, HTTPOptions, Help, RPCCheck, RTSPRequest, SSLSessionReq, TLSSessionReq, TerminalServerCookie, X11Probe: 
|_    PyMissing game mode
20011/tcp open  unknown
| fingerprint-strings: 
|   GenericLines: 
|     HTTP/1.1 400 Bad Request
|     Connection: close
|     Content-Type: text/html
|     Content-Length: 193
|     <html>
|     <head>
|     <title>Bad Request</title>
|     </head>
|     <body>
|     <h1><p>Bad Request</p></h1>
|     Invalid Request Line &#x27;Invalid HTTP request line: &#x27;&#x27;&#x27;
|     </body>
|     </html>
|   GetRequest: 
|     HTTP/1.0 200 OK
|     Server: gunicorn
|     Date: Sat, 04 Dec 2021 01:03:19 GMT
|     Connection: close
|     Content-Type: text/html; charset=utf-8
|     Content-Length: 947
|     <!doctype html>
|     <html>
|     <link rel="stylesheet" href="/static/style.css">
|     <head>
|     <title>CTF Gallery</title>
|     </head>
|     <body>
|     <h1>CTF Gallery</h1>
|     <div class="panel">
|     class="pan_item" href="/admin">admin</a>
|     </div>
|     <div class="gal_links"><p><a href="/gallery/Sarah">Sarah's gallery</a></p></div>
|     <div class="gal_links"><p><a href="/gallery/John">John's gallery</a></p></div>
|     <div class="gal_links"><p><a href="/gallery/Ripley">Ripley's gallery</a></p></div>
|     <div class="gal_links"><p><a href="/gallery/Ash">Ash's gallery</a></p></div>
|     <p>Some galleries have not yet been added to the main page.<br>For those cases, the form below can be used to access them.</p>
|     <div id
|   HTTPOptions: 
|     HTTP/1.0 200 OK
|     Server: gunicorn
|     Date: Sat, 04 Dec 2021 01:03:19 GMT
|     Connection: close
|     Content-Type: text/html; charset=utf-8
|     Allow: OPTIONS, HEAD, GET
|_    Content-Length: 0
20022/tcp open  http       Apache httpd 2.4.51 ((Debian))
|_http-title: Site doesn't have a title (text/html).
|_http-server-header: Apache/2.4.51 (Debian)
20055/tcp open  http       Apache httpd 2.4.51 ((Debian))
|_http-server-header: Apache/2.4.51 (Debian)
|_http-title: Site doesn't have a title (text/html).
20123/tcp open  ssh        OpenSSH 8.6 (protocol 2.0)
| ssh-hostkey: 
|   3072 83:a3:ad:9e:e5:d3:4c:c3:27:4f:22:47:3e:d4:4b:07 (RSA)
|   256 83:33:6e:4a:04:b1:58:39:0f:fd:e4:1d:5e:53:46:2c (ECDSA)
|_  256 2a:a5:66:1a:af:d6:e5:78:8a:51:91:17:e3:57:91:9a (ED25519)
30033/tcp open  unknown
| fingerprint-strings: 
|   DNSStatusRequestTCP, DNSVersionBindReqTCP, FourOhFourRequest, GenericLines, GetRequest, HTTPOptions, Help, JavaRMI, Kerberos, LANDesk-RC, LDAPBindReq, LDAPSearchReq, LPDString, NCP, NotesRPC, RPCCheck, RTSPRequest, SIPOptions, SMBProgNeg, SSLSessionReq, TLSSessionReq, TerminalServer, TerminalServerCookie, WMSRequest, X11Probe, afp, giop, ms-sql-s, oracle-tns: 
|_    [error] invalid input key
30034/tcp open  http       SimpleHTTPServer 0.6 (Python 3.8.10)
|_http-server-header: SimpleHTTP/0.6 Python/3.8.10
|_http-title: Directory listing for /
33337/tcp open  http-proxy Apache Traffic Server 7.1.1
|_http-server-header: ATS/7.1.1
|_http-title: Did not follow redirect to http://threeofhearts.ctf.net/
35000/tcp open  http       Apache httpd 2.4.38 ((Debian))
|_http-server-header: Apache/2.4.38 (Debian)
|_http-title: Ace of Diamonds
5 services unrecognized despite returning data. If you know the service/version, please submit the following fingerprints at https://nmap.org/cgi-bin/submit.cgi?new-service

Port 80

So from here we start with port 80 which is an http service running Werkzeug httpd 2.0.1 (Python 3.9.7).

My teammate EricHogue came up with a great way to create a tunnel on our host computer to the target machine port.

From left to right: The port you want to tunnel on, the victim’s IP, the victim’s service port, the kali box IP and the SSH key.
One thing I forgot to mention is the way we submit flags

So, two things here. First the PNG image reveals in which challenge to deposit the flag. In this case, it’s 4 of Hearts. Next step is to calculate the MD5sum with a simple command.

The flag is 3bb0409396fdc4e168c9185929af8347

Port 443

443/tcp   open  http       Apache httpd 2.4.51
| http-git: 
|   172.17.26.149:443/.git/
|     Git repository found!
|     Repository description: Unnamed repository; edit this file 'description' to name the...
|_    Last commit message: More enthusiasm 
|_http-server-header: Apache/2.4.51 (Debian)
|_http-title: Site doesn't have a title (text/html).

Next we attack port 443. Quite unusual there is not SSL here. Nmap revealed /.git which is a Git Repo. Going to http://localhost:8888/.git gives nothing but Website under development. Since it’s a Git i decided to try some tools i’ve used before.

git clone https://github.com/internetwache/GitTools.git
GitTools have 3 tools and I only need Dumper and Extractor. Let’s begin with Extractor. [*] USAGE: extractor.sh GIT-DIR DEST-DIR
Dumping using gitdumper.
Using gitextractor and i see something interesesting.
The flag location is revealed in this .env file!
I could obtain the next flag easily!

Port 8080

8080/tcp  open  http       WSGIServer 0.2 (Python 3.8.10)
|_http-server-header: WSGIServer/0.2 CPython/3.8.10
|_http-title: Cookies Galore
I started by creating a new account and logging in.
Once logged I tried the /admin path. Which I did not have permissions for.
Since the challenge is named cookie-galore, I decided to check my cookies.
Changing the “admin” cookie to “true”.
Going back to /admin and we got the flag!

Port 10010

(This flag was first captured by my teammate @EricHogue)

10010/tcp open  rxapi?
We land on this website. Let’s create an account.
Nothing of interest on the site except for /admin directory which we can’t access, for now.
Looking at the source code reveals something interesting.
    <script>
        var current_account = {"id":8,"username":"neoh","password":"password123","role":"user","created_at":"2021-12-06T01:21:33.495Z","updated_at":"2021-12-06T01:21:33.495Z"};
    </script>

On creation of a user, we have other parameters than username and password. The most interesting one is “role”: “user”, which we can change for “role”: “admin”. This is now as Mass Assignment exploit documented here and here. Let’s create a new user with admin role.

With burp I can intercept the register process.
Adding the account_role=admin parameter.
It worked!
Done!

Port 12380

12380/tcp open  http       Apache httpd 2.4.49 ((Debian))
|_http-server-header: Apache/2.4.49 (Debian)
|_http-title: Site doesn't have a title (text/html).

This was pretty obvious. Apache 2.4.49 is known to be vulnerable to RCE.

There was an exquisite looking website made with Notepad.

I didn’t need to look further, let’s get serious!

I fired up Metasploit and searched for Apache 2.4.49
I’ve setup my options and was ready to EXPLOIT!
The exploit is working perfectly!
Finding the flag was not a hard task.

Then I needed a visual on the flag. I copied it to the webroot folder using cp /secret/safe/flag.png /var/www/html/

Done!

Port 20011

(This flag was captured by my teammate @EricHogue)

20011/tcp open  unknown
This port brings us to website that seems to be a gallery.
We have access to every gallery except for John’s.
Also, /admin is 401, for now.
On the main page, there was something interesting. Let’s try this.
Uncheck John and save.
Now we can access John’s gallery and here is the flag!

Port 20022

20022/tcp open  http       Apache httpd 2.4.51 ((Debian))
|_http-title: Site doesn't have a title (text/html).
|_http-server-header: Apache/2.4.51 (Debian)
Looking at my cookie, I knew something was going on here.
It was a base64 string turned into another base64 string revealing O:4:"user":3:{s:8:"username";s:5:"guest";s:5:"admin";b:0;s:11:"profile_img";s:23:"/var/www/html/guest.png";}

At first I changed the user to admin like this O:4:"admin":3:{s:8:"username";s:5:"guest";s:5:"admin";b:0;s:11:"profile_img";s:23:"/var/www/html/guest.png";} Then changed my cookie and refresh the page.

First hint!

Then I changed the profile_img to /flag.png. Rinse and repeat previous steps.

Which gave me nearly the same thing so I went back with username user
Now I got a new error but, it wasn’t helping me much.

After a couple minutes, I figured something out. "profile_img";s:23:"/var/www/html/guest.png";} The s:23 represents the length of the string "/var/www/html/guest.png". So in order to access /flag.png I need to change s:23 to s:9 resulting : O:4:"user":3:{s:8:"username";s:5:"guest";s:5:"admin";b:0;s:11:"profile_img";s:9:"/flag.png";}

Nice! Another hint! I was pretty it was just a directory manipulation to get to show the flag.
O:4:"user":3:{s:8:"username";s:5:"guest";s:5:"admin";b:0;s:11:"profile_img";s:31:"/var/www/html/../../../flag.png";}
Flagged!

Port 20055

(This flag was first captured by my teammate @EricHogue)

20055/tcp open  http       Apache httpd 2.4.51 ((Debian))
|_http-server-header: Apache/2.4.51 (Debian)
|_http-title: Site doesn't have a title (text/html).
This brings us to an upload server. Pretty obvious the challenge will be about file upload restrictions bypass. A lot of extensions are blocked in this case. Also at the bottom of the page, there is a hint about the flag’s location which is /flag.png
The trick here is to create a .htaccess file. Which will allow us to create a new extension type that will considered as executable. Let’s try uploading it.
I can’t access it but, it doesn’t matter. Now, I can upload a .lol file that will be an executable.
And here is the flag! This was something new for me and I always love to learn! Thanks to my team!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.