Oren [Boot2Root]

For the first time, SherpaSec had its own physical CTF! But wait, what is SherpaSec? Well according to ChatGPT, SherpaSec is a Malaysian volunteer-based cybersecurity community dedicated to creating a sustainable ecosystem for cybersecurity. It brings together students, professionals, and enthusiasts to share knowledge, build skills, and foster collaboration. The organisation regularly hosts events like sharing sessions, workshops, and for the very first time, a Capture The Flag (CTF) competition, SherpaCTF!
Now, like PwC Hackaday CTF 2024, what is my goal? Dominate Boot2Roots. However, Red Teamers were shocked to know that the Boot2Roots weren’t normal Linux or Windows boxes, it was Active Directory, my playground. By the way, what made the Boot2Roots scary was that we knew who was the challenge creator beforehand. It was the legendary H0j3n!
Enumeration

In context, a virtual machine was provided to us for the challenge. So, with that, a host scan denoted by the -sn
switch was needed to find out what was the IP address of the virtual machine. As shown in the results, it’s 192.168.138.143
as our attacker machine has the IP Address of 192.168.138.129
.
jigsaw@jigsaw ~/H0j3n_AD> sudo nmap -sC -sV -p- 192.168.138.143 --open -oN 192.168.138.143.nmap_all_ports
Starting Nmap 7.94SVN ( <https://nmap.org> ) at 2024-11-24 12:56 +08
Nmap scan report for 192.168.138.143
Host is up (0.00090s latency).
Not shown: 65510 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
80/tcp open http Microsoft IIS httpd 10.0
|_http-title: Site doesn't have a title.
|_http-server-header: Microsoft-IIS/10.0
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2024-11-24 04:58:20Z)
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: oren.local0., Site: Default-First-Site-Name)
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open tcpwrapped
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: oren.local0., Site: Default-First-Site-Name)
3269/tcp open tcpwrapped
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
8080/tcp open http Apache httpd 2.4.58 ((Win64) OpenSSL/3.1.3)
|_http-server-header: Apache/2.4.58 (Win64) OpenSSL/3.1.3
|_http-title: Maintenance
|_http-open-proxy: Proxy might be redirecting requests
8530/tcp open http Microsoft IIS httpd 10.0
|_http-title: Site doesn't have a title.
|_http-server-header: Microsoft-IIS/10.0
8531/tcp open unknown
9389/tcp open mc-nmf .NET Message Framing
49666/tcp open msrpc Microsoft Windows RPC
49667/tcp open msrpc Microsoft Windows RPC
49679/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
49680/tcp open msrpc Microsoft Windows RPC
49682/tcp open msrpc Microsoft Windows RPC
49690/tcp open msrpc Microsoft Windows RPC
49695/tcp open msrpc Microsoft Windows RPC
53564/tcp open msrpc Microsoft Windows RPC
MAC Address: 00:0C:29:B1:43:DB (VMware)
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
|_nbstat: NetBIOS name: DC01, NetBIOS user: <unknown>, NetBIOS MAC: 00:0c:29:b1:43:db (VMware)
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled and required
| smb2-time:
| date: 2024-11-24T04:59:14
|_ start_date: N/A
Service detection performed. Please report any incorrect results at <https://nmap.org/submit/> .
Nmap done: 1 IP address (1 host up) scanned in 207.22 seconds
Now that we know the IP address of the target, a full port scan was done on the target. What was noteworthy in the scan was the 3 web servers hosted on port 80
, 8080
and 8530
. Only the web server on port 8080
showed something of interest.

On the web server running on port 8080
, a page indicating the site was under maintenance was displayed.

Performing directory bruteforcing on all 3 of the web servers, the web server on port 8080
was the only one that showed interesting directories.

Going into admin.php
, a login page was displayed. However, after exhausting SQLmap and Hydra to bruteforce it, I turned my head to phpinfo.php
.

Right here, a goldmine of information can be found such as the target’s operating system and the web application’s PHP version.

Quickly googling the PHP version along with the word “exploit” showed that there were proof of concepts (POCs) for exploiting this PHP version that will lead to remote code execution. However, using some of the POCs did not work.

With that, I googled for the CVE, which led to a Git repository from WatchTowr which had a Python exploit. (THANK GOD FOR PYTHON EXPLOITS)
Initial Access

So, after cloning the repository, I executed the script with the -h
switch to see what arguments can be parsed in. The script takes in the URL of the web application with the --target
switch followed by the command we want to run wrapped around PHP tags with the -c
switch.

Using the example command from the help menu, replaced with the target’s IP address and port number followed by a PowerShell command to callback to my Python server reveals a callback!

So, repeating the steps before, I replaced the command that will be executed with a PowerShell reverse shell command encoded in Base64.

And as expected, we received a reverse shell!

To make my life easier, I will be using the Sliver C2. An implant was generated and a listener was started.

Then, on the PowerShell reverse shell, the implant was downloaded and executed.

As you can see here, I have a session!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Admin Console</title>
<style>
body {
font-family: Consolas, monospace;
background-color: #000000;
color: #00ff00;
text-align: center;
}
.container {
background-color: #1e1e1e;
padding: 20px;
margin-top: 50px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
display: inline-block;
width: 80%;
text-align: left;
}
.console {
background-color: #000000;
padding: 15px;
height: 300px;
overflow-y: auto;
white-space: pre-wrap;
font-family: Consolas, "Courier New", monospace;
color: #00ff00;
border-radius: 8px;
border: 1px solid #333;
}
input[type="text"] {
background-color: #000000;
border: 1px solid #333;
color: #00ff00;
padding: 10px;
width: 90%;
font-family: Consolas, monospace;
font-size: 16px;
border-radius: 8px;
}
.cmd {
color: #00ff00;
display: inline-block;
margin-right: 10px;
}
button {
background-color: #00ff00;
color: #000;
border: none;
padding: 10px 20px;
font-family: Consolas, monospace;
font-size: 16px;
cursor: pointer;
border-radius: 8px;
}
button:hover {
background-color: #00e600;
}
.cmd-prompt {
text-align: left;
white-space: nowrap;
margin: 0;
padding: 0;
}
.cmd-output {
text-align: left;
white-space: pre-wrap;
}
</style>
</head>
<body>
<div class="container">
<h1>Admin Console</h1>
<div class="console">
<?php if (!empty($command)): ?>
<div class="cmd-output"><?php echo htmlspecialchars($output); ?></div>
<?php endif; ?>
</div>
<form method="POST">
<span class="cmd cmd-prompt">CMD></span>
<input type="text" name="command" placeholder="Type a command..." autofocus required>
<button type="submit">Run</button>
</form>
<br><br>
<a href="admin.php?logout=true">Logout</a>
</div>
</body>
</html>
Now, as shown before there was a admin.php
file which we saw before on the web page. Analysing it, we found our first set of credentials! However, we will not be using it.
webadmin:N0ts0s3cr3t_123!!!

Privilege Escalation
sliver (NUCLEAR_HEALTH) > sa-whoami
[*] Successfully executed sa-whoami (coff-loader)
[*] Got output:
UserName SID
====================== ====================================
OREN\\webadmin S-1-5-21-2956732219-3055473855-868524036-1105
GROUP INFORMATION Type SID Attributes
================================================= ===================== ============================================= ==================================================
OREN\\Domain Users Group S-1-5-21-2956732219-3055473855-868524036-513 Mandatory group, Enabled by default, Enabled group,
Everyone Well-known group S-1-1-0 Mandatory group, Enabled by default, Enabled group,
BUILTIN\\Remote Management Users Alias S-1-5-32-580 Mandatory group, Enabled by default, Enabled group,
BUILTIN\\Users Alias S-1-5-32-545 Mandatory group, Enabled by default, Enabled group,
BUILTIN\\Pre-Windows 2000 Compatible Access Alias S-1-5-32-554 Mandatory group, Enabled by default, Enabled group,
NT AUTHORITY\\SERVICE Well-known group S-1-5-6 Mandatory group, Enabled by default, Enabled group,
CONSOLE LOGON Well-known group S-1-2-1 Mandatory group, Enabled by default, Enabled group,
NT AUTHORITY\\Authenticated Users Well-known group S-1-5-11 Mandatory group, Enabled by default, Enabled group,
NT AUTHORITY\\This Organization Well-known group S-1-5-15 Mandatory group, Enabled by default, Enabled group,
LOCAL Well-known group S-1-2-0 Mandatory group, Enabled by default, Enabled group,
Authentication authority asserted identity Well-known group S-1-18-1 Mandatory group, Enabled by default, Enabled group,
OREN\\Web_Administrator Alias S-1-5-21-2956732219-3055473855-868524036-1107 Mandatory group, Enabled by default, Enabled group,
OREN\\GPO_Manager Alias S-1-5-21-2956732219-3055473855-868524036-1108 Mandatory group, Enabled by default, Enabled group,
Mandatory Label\\High Mandatory Level Label S-1-16-12288 Mandatory group, Enabled by default, Enabled group,
Privilege Name Description State
============================= ================================================= ===========================
SeMachineAccountPrivilege Add workstations to domain Disabled
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeImpersonatePrivilege Impersonate a client after authentication Enabled
SeCreateGlobalPrivilege Create global objects Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Disabled
So, the first thing to do when you have user access, is to CHECK YOUR PRIVILEGES! As you can see here, we have SeImpersonatePrivilege which is exploitable with PrintSpoofer through named pipes. PrintSpoofer is vulnerable to Windows Server 2019 which we have identified in phpinfo.php
.

So, PrintSpoofer is uploaded on the target, and executed with the parameter of the implant that was uploaded just now with the -c
switch.

As shown here, we have gained machine access, which is higher than NT Authority System!
User Flag

Now I have the highest authority, let’s get the flag. As the user webadmin
, I can view the files in my directory.

On the Desktop of the webadmin
, there are 3 files. A user.zip
which has the user flag, an encrypted password and a PowerShell script to decrypt the password.
# Load the necessary assembly
Add-Type -AssemblyName System.Security
# Read the encrypted password from the file
$encryptedPassword = [System.IO.File]::ReadAllBytes("C:\\Users\\webadmin\\Desktop\\encryptedPassword.bin")
# Decrypt the password using DPAPI
$decryptedPasswordBytes = [System.Security.Cryptography.ProtectedData]::Unprotect($encryptedPassword, $null, [System.Security.Cryptography.DataProtectionScope]::CurrentUser)
# Convert the decrypted password back to a string
$decryptedPassword = [System.Text.Encoding]::UTF8.GetString($decryptedPasswordBytes)
# Retrieve Password
Write-Host "Here your password = $decryptedPassword"
Write-Host "Use the password to unzip user.zip and submit your flag!"
However, user.zip
is password protected. So, with the information that we gathered, it can be assumed that the PowerShell script is used to decrypt the encrypted password file which will reveal the password to user.zip. However, the PowerShell script only works if you are the current user as shown in the PowerShell script above. it uses the user’s DPAPI secret to decrypt the file. To elaborate on this, you can only decrypt the password if you are logged in as the user that encrypted the file.

Using that script we have the password for user.zip
!

We got the user flag!
SHCTF24{CVE_0ren_G0tcha!}
Root Flag

Now continuing our red team assessment, I mean CTF challenge, time for post-exploitation. mimikatz.exe
was uploaded and the SAM account passwords were dumped using that.

Looking at the Administrator’s Desktop, we had the same exact files as the user account except this time there is a root.zip
file. At this point, I had every account. The Administrator account, the machine account and the user account. However, the PowerShell script did not work for some reason even though I am logged in as the user that encrypted the file. So, I raised a ticket and the issue was resolved.

The resolution for this error was to give us a password.zip
file which was password protected by the Administrator’s hash.

So, using the results from mimikatz.exe
, the zip file was decrypted and we got the password for root.zip
.

From there, we got the root flag!
SHCTF24{H0pe_y0u_3njoyed_AD!}
Intended Solution

BUT WAIT, what if I told you the way I did the privilege escalation was an unintended way? Remember the credentials we got? The first thing to do when you get domain credentials is to run Bloodhound.

So, using the credentials, I ran bloodhound-python
to query the LDAP server on the Active Directory for all Domain objects.
Note that in my opinion
bloodhound-python
is not recommended for red team assessments or basically any advanced red team certifications mainly because it does not pick up every Domain object such as Active Directory Certificate Services (ADCS). For this reason, Sharphound is recommended.

When we have the Domain objects, I loaded up neo4j
, the database for Bloodhound and of course, the Bloodhound GUI. So, what do we do from here? As John Hammond would put it, CLICK EVERYTHING. However, my methodology is to check the outbound permissions of the compromised user first. As you can see the webadmin
user is part of the WEB_ADMINISTRATOR
group.

Looking at the WEB_ADMINISTRATOR
group, it can add itself to the GPO_MANAGER group.

So, by using net group "GPO_MANAGER" webadmin /add /domain
, the user webadmin
is now in the GPO_Manager
group!

Looking at the outbound permissions of the GPO_Manager
group, it is shown that it has full read and write permissions on the ACCESS_FILES
Group Policy!

From here, SharpGPOAbuse
is used to add the webadmin
user as a local administrator.

Finally, NetExec can be used to dump the SAM account passwords.
Conclusion
Overall, I think this box is a good Active Directory box, despite some hiccups and the unintended way. It constrains you to be a certain user to get the flag and also uses some access control lists or ACLs to get Domain Admin. If you wanna try one of H0j3n’s Active Directory boxes, here is one which at the time of writing is still available and was created for Wargames 2022. I really enjoyed this CTF as we as a team did not intend to get 2nd place in the open category as well as the best presentation for the creative category. I hope SherpaSec can organise another physical CTF next for the open category as well! Till then, peace out!
Last updated