Sysco

Challenge Lab (Medium) - by LainKusanagi

The following post by 0xb0b is licensed under CC BY 4.0


Scenario

Sysco is a Managed Service Provider that has tasked you to perform an external penetration testing on their active directory domain. You must obtain initial foothold, move laterally and escalate privileges while evading Antivirus detection to obtain administrator privileges.

Objectives and Scope

The core objective of this external penetration test is to simulate a realistic, determined adversary to achieve Domain Administrator privileges within Sysco's Active Directory (AD) environment. Starting from an external position, we will focus on obtaining an initial foothold, performing lateral movement, and executing privilege escalation while successfully evading Antivirus (AV) and other security controls. This is a red-team exercise to find security weaknesses before a real attacker does.

Summary

Summary

In Sysco we compromise an Active Directory environment starting from external web and SMB enumeration to full domain controller control. Using anonymous SMB access and website OSINT, we harvest employee names to build a valid username list and identify AS-REP roastable accounts. Cracking one of these offline provides our initial domain foothold as jack.dowland. Through mail enumeration we uncover a Cisco configuration revealing additional credentials, allowing access as lainey.moore. Further enumeration exposes a stored SSH credential that leads to greg.shields, a user with GenericWrite privileges on the Default Domain Policy. Abusing this misconfiguration via GPO modification, we add our account to the local Administrators group, refresh Group Policy, and achieve administrative access on the domain controller. Completing full domain compromise through chained enumeration and privilege escalation.

Recon

We use rustscan -b 500 -a sysco.hs -- -sC -sV -Pn to enumerate all TCP ports on 10.1.79.70, piping the discovered results into Nmap which runs default NSE scripts -sC, service and version detection -sV, and treats the host as online without ICMP echo -Pn.

A batch size of 500 trades speed for stability, the default 1500 balances both, while much larger sizes increase throughput but risk missed responses and instability.

rustscan -b 500 -a sysco.hs -- -sC -sV -Pn

With the results of our RustScan we identify a Windows host named DC01 on domain SYSCO.LOCAL exposing DNS (Simple DNS Plus) on 53, HTTP (Apache 2.4.58 / PHP 8.2.12) on 80, Kerberos on 88, Active Directory LDAP on 389 (AD), LDAPS/tcpwrapped on 636, kpasswd5 on 464, Microsoft RPC / MSRPC endpoints on 135, NetBIOS/SMB on 139 and 445 (SMB2 message signing required), RPC-over-HTTP on 593 and 49675, .NET message framing on 9389, RDP (Microsoft Terminal Services) on 3389 (cert: DC01.SYSCO.LOCAL), and several ephemeral MSRPC ports 49664, 49667, 49676, 49722.

WEB

We first look at the website manually and find only a static one.

When we scroll down to the team section, we find the first and last names of three team members.

For now, we'll make a note of these and save them in team.txt.

greg shields
sarah jhonson
jack dowland
lainey moore

In the footer, we find another email address for contact. The domain sysco.local is also used here.

We continue with a recursive directory scan using Feroxbuster. In addition to the directories of the static site, we also find a Roundcube instance.

feroxbuster -w /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-lowercase-2.3-medium.txt -u 'http://sysco.hs'

SMB

First, we try to authenticate with the guest account, but the account is disabled.

nxc smb sysco.hs -u guest -p '' 

But we are able to athenticate anonymously.

nxc smb sysco.hs -u '' -p '' 

We can use that to generate our /etc/hosts entry via NetExec.

nxc smb sysco.hs -u '' -p '' --generate-hosts-file hosts

Kerberos

We now have some names, but no usernames yet. We can generate a series of potential usernames using Username Anarchy.

We don't have passwords either, so we could try to create emails from the usernames we created and the information in the footer of the email, and then brute force them in Roundcube. However, this would be a very extensive task.

However, we also have a domain controller and Kerberos available. We could therefore first brute force valid usernames using kerbrute.

But first, we create a list of possible usernames using UsernameAnarchy and the names we have identified.

username-anarchy -i team.txt > usernames.txt

Next, we use kerbrute to test for valid usernames. And we are able to detect three.

kerbrute userenum --domain SYSCO.LOCAL --dc dc01.sysco.local usernames.txt

We save those to a file called users.txt.

greg.shields
lainey.moore
jack.dowland

Access as jack.dowland

The mind map from Orange Cyber Defense provides useful guidance on how to proceed in an Active Directory engagement depending on the information available:

One option that does not require passwords but does require valid usernames is ASREPRoasting.

AS-REP roasting is an attack where a Kerberos account with the Do not require preauthentication flag set allows to request an AS-REP authentication response from the KDC and extract an offline-crackable AS-REP ciphertext (an encrypted blob) of the user's password.

To ASREProas we will also use NetExec and are able to retrieve the blob of jack.dowland :

nxc ldap SYSCO.LOCAL -u users.txt -p '' --asreproast output.txt

Next, we try to crack the blob using hashcat and are successful. We now have the credentials of jack.dowland.

hashcat -m18200 -a0 output.txt /usr/share/wordlists/rockyou.txt 

We test the credentials using NetExec and are able to list shares.

nxc smb SYSCO.LOCAL -u 'jack.dowland' -p 'REDACTED'
nxc smb SYSCO.LOCAL -u 'jack.dowland' -p 'REDACTED' --shares

Since the IPC$ share is readable we can try an rid brute force to enumerate further users. But here we are only able to spot the three we already know. A password spray to the other users is unsuccessful.

nxc smb SYSCO.LOCAL -u 'jack.dowland' -p 'REDACTED' --rid

Bloodhound Enumeration

Now that we have the credentials of a user we can use bloodhound to enumerate the domain:

bloodhound-ce.py --zip -c All -d SYSCO.LOCAL -u jack.dowland -p 'REDACTED' -dc DC01.SYSCO.LOCAL -ns 10.0.27.111

But unfortunately the user jack.dowland has no interesting group membership or outbound object control that we can use to escalate our privileges.

We also check for the other users and see that lainey.moore is part of the REMOTE MANAGEMENT USERS group, that would allow us low privilege access to the domain controller.

We query for Shortest Path To Domain Admins and see that greg.shields has GenericWrite permissions on DEFAULT DOMAIN POLICY as being part of the DOMAIN POLICY CREATOR OWNERS group. This would allow us to escalate our priviliges. More on that later.

Shell as lainey.moore

Since we cannot escalate our privileges for now via the permissions and relationships of the user jack.dowland we can try to check if that user reused the credentials for RoundCube.

We are able to log in as jack.dowland with the credentials found ealier and spot a mail in the sent directory about issues with a router config. Furthermore the mail was sent to lainey.moore@sysco.local.

We download the attached router config and find Cisco Type 5 Secret.

Cisco Type 5 Secret:

Next, we try to crack it using hashcat and are successful.

 hashcat -m500 -a0 'REDACTED' /usr/share/wordlists/rockyou.txt --show 

We are now able to perform another password spray with the recovered password and identified users. And are able to authenticate as lainey.moore.

nxc smb SYSCO.LOCAL -u users.txt -p 'REDACTED' --continue-on-success

We use evil-winrm to log on to the target as lainey.moore...

evil-winrm -i SYSCO.LOCAL -u lainey.moore -p REDACTED 

... and find the user flag at C:\Users\lainey.morre\user.txt.

Access as greg.shields

In addition to the user flag on the desktop, we find a note, a putty executable, and a link in the Documents folder. The note is about tasks that need to be completed on the router and mentions SSH, among other things. That's probably why the Putty client is included.

If we take a look at the link file, we can see at a glance that it can be used to connect to the router via SSH. The SSH credentials are stored there.

However, we want to illustrate this a little better and download the link file.

Next, we install liblnk-utils to examine the link file in more detail using linkinfo.

sudo apt install liblnk-utils

We inspect the link file with linkinfo and can now easily see the password.

lnkinfo "Putty - HS Router login.lnk"

We perform another password spray using NetExec with the identified usernames and the newly discovered password. And we are able to authenticate as greg.shields.

nxc smb SYSCO.LOCAL -u users.txt -p 'REDACTED' --continue-on-success

Shell as local admin

Recalling our Bloodhound Enumeration we know that greg.shields has GenericWrite permissions on the DEFAULT DOMAIN POLICY GPO.

We can easily Google how to exploit these and find ourselves on hackers.recipes:

google: "generic write on default domain policy"

With pyGPOabuse we can update an existing GPO and a a local admin:

pyGPOabuse, update an existing GPO - add a local admin pygpoabuse 'domain'/'user':'password' -gpo-id "12345677-ABCD-9876-ABCD-123456789012"

We could now add either greg.shields or lainey.moore to the local Administrators group, both are in the REMOTE MANAGEMENT USERS group. We add greg.shields to the local Administrators group.

pygpoabuse.py 'SYSCO.LOCAL'/'greg.shields':'REDACTED' -gpo-id '31B2F340-016D-11D2-945F-00C04FB984F9' -command 'net localgroup Administrators greg.shields /add'
pygpoabuse.py 'SYSCO.LOCAL'/'greg.shields':'REDACTED' -gpo-id '31B2F340-016D-11D2-945F-00C04FB984F9' -command 'net localgroup Administrators lainey.moore /add'

Next, we log in as greg.shields and issue gpupdate /force to force the update via the GPOs present.

evil-winrm -i SYSCO.LOCAL -u greg.shields -p 'REDACTED'
gpupdate /force

We are now in the local administrators group on the domain controller...

... and are able to access the final flag at C:\Users\Administrator\Desktop\root.txt.

Last updated

Was this helpful?