> For the complete documentation index, see [llms.txt](https://0xb0b.gitbook.io/writeups/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://0xb0b.gitbook.io/writeups/hack-smarter-labs/2025/sysco.md).

# Sysco

{% embed url="<https://www.hacksmarter.org/courses/18876893-1afd-443f-b448-0681b13e86ec>" %}

The following post by 0xb0b is licensed under [CC BY 4.0<img src="https://mirrors.creativecommons.org/presskit/icons/cc.svg?ref=chooser-v1" alt="" data-size="line"><img src="https://mirrors.creativecommons.org/presskit/icons/by.svg?ref=chooser-v1" alt="" data-size="line">](http://creativecommons.org/licenses/by/4.0/?ref=chooser-v1)

***

## 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 <a href="#user-content-objectives-and-scope" id="user-content-objectives-and-scope"></a>

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

<details>

<summary>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.

</details>

## 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
```

<figure><img src="/files/Lws862u92hswugzAEhFv" alt=""><figcaption></figcaption></figure>

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`.

<figure><img src="/files/0FGAgd4IVdPYpL71IJ8m" alt=""><figcaption></figcaption></figure>

### WEB

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

<figure><img src="/files/PTFC878UxIaor2OX3VrL" alt=""><figcaption></figcaption></figure>

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

<figure><img src="/files/17XMYPNY5QwG0oj2ee91" alt=""><figcaption></figcaption></figure>

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.

<figure><img src="/files/OYn4o0WlpqsAxcaEuPND" alt=""><figcaption></figcaption></figure>

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

{% code overflow="wrap" %}

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

{% endcode %}

<figure><img src="/files/xKq9OtZVVCRKl6rsMUyQ" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/Hnh2ss0LvobgJPqEn9qv" alt=""><figcaption></figcaption></figure>

### SMB

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

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

<figure><img src="/files/84KvQj1cA3HNGS5xDzKs" alt=""><figcaption></figcaption></figure>

But we are able to athenticate anonymously.

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

<figure><img src="/files/nln799NbH1vbAJYprSI6" alt=""><figcaption></figcaption></figure>

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

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

<figure><img src="/files/hXX3sdE91S6T8rTXOe5p" alt=""><figcaption></figcaption></figure>

### Kerberos

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

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.

{% embed url="<https://github.com/urbanadventurer/username-anarchy>" %}

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

<figure><img src="/files/p2vbRximTzzZCfcW4Bp6" alt=""><figcaption></figcaption></figure>

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
```

<figure><img src="/files/UF0uTL8fomyNA4PwtJb0" alt=""><figcaption></figcaption></figure>

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:

{% embed url="<https://orange-cyberdefense.github.io/ocd-mindmaps/>" %}

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.

{% embed url="<https://www.thehacker.recipes/ad/movement/kerberos/asreproast>" %}

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
```

<figure><img src="/files/APVGqQTsmq5TDQKJpG8S" alt=""><figcaption></figcaption></figure>

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 
```

<figure><img src="/files/H6o8kULI6wPceAidfz0w" alt=""><figcaption></figcaption></figure>

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
```

<figure><img src="/files/gH40lK0z0IF6da6Zjszs" alt=""><figcaption></figcaption></figure>

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
```

<figure><img src="/files/YMuoNPvteMHkxiw9fFnE" alt=""><figcaption></figcaption></figure>

## Bloodhound Enumeration

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

{% code overflow="wrap" %}

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

{% endcode %}

<figure><img src="/files/MrOeAwu7R5kdPpw1r0ZK" alt=""><figcaption></figcaption></figure>

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

<figure><img src="/files/rZc5csXLjLb1H6GjW8fZ" alt=""><figcaption></figcaption></figure>

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.

<figure><img src="/files/PqYI37U306B6vdcm5v51" alt=""><figcaption></figcaption></figure>

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.

<figure><img src="/files/cm3R06yenefNj6qP0O93" alt=""><figcaption></figcaption></figure>

## 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.&#x20;

<figure><img src="/files/MCTGsQzNg5PM6lKV6oPW" alt=""><figcaption></figcaption></figure>

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`.

<figure><img src="/files/pX5C2mv0cSsm5Rwc2HN6" alt=""><figcaption></figcaption></figure>

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

<figure><img src="/files/5YLbPg8dgdr49qQvtBG8" alt=""><figcaption></figcaption></figure>

Cisco Type 5 Secret:

{% embed url="<https://hashcat.net/wiki/doku.php?id=example_hashes>" %}

<figure><img src="/files/L7zH8MFaQRpor84ZLuWz" alt=""><figcaption></figcaption></figure>

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

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

<figure><img src="/files/1Xso2wSx2die7OB1uD15" alt=""><figcaption></figcaption></figure>

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
```

<figure><img src="/files/yVV0INBiUbZyBqGHzy5W" alt=""><figcaption></figcaption></figure>

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

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

<figure><img src="/files/0fJVrhykMEayc0Nyzlbd" alt=""><figcaption></figcaption></figure>

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

<figure><img src="/files/xVPJe2suNEKfX9zwDOeh" alt=""><figcaption></figcaption></figure>

## 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.

<figure><img src="/files/CArwIIuuCjTsgZih2kyr" alt=""><figcaption></figcaption></figure>

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.

<figure><img src="/files/rybiX3vJoKhfyhqvQxDH" alt=""><figcaption></figcaption></figure>

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"
```

<figure><img src="/files/G0SMCZDaHwoEtdAztfHR" alt=""><figcaption></figcaption></figure>

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
```

<figure><img src="/files/8YluwQYpaUiJNBuATQ8r" alt=""><figcaption></figcaption></figure>

## Shell as local admin

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

<figure><img src="/files/eQHKxsn9UFz7oZyXqTae" alt=""><figcaption></figcaption></figure>

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

```
google: "generic write on default domain policy"
```

{% embed url="<https://www.thehacker.recipes/ad/movement/group-policies>" %}

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.

{% code overflow="wrap" %}

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

{% endcode %}

{% code overflow="wrap" %}

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

{% endcode %}

<figure><img src="/files/GqODRSpjWykGMI06miLZ" alt=""><figcaption></figcaption></figure>

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
```

<figure><img src="/files/PCyRcF2To3aOhCtQEguY" alt=""><figcaption></figcaption></figure>

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

<figure><img src="/files/J7gFadYY4Apv7uRv8Rno" alt=""><figcaption></figcaption></figure>

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

<figure><img src="/files/xqE8LaT6sC5RuyT2qQre" alt=""><figcaption></figcaption></figure>
