SPECTRE — Grey-Box Penetration Test

APACHE 2.4.58 TARGET · POSTGRESQL 16 DEFENDED · CIS/OWASP/ISO 27002 METHODOLOGY · QUALITY GATE — CLEAR

// ENGAGEMENT STATUS — COMPLETE · rev 2026-06-12
// IN PLAIN TERMS — Before you can defend a system, you need to understand how it's attacked. This is a controlled, authorised break-in attempt against a web server, documented to the standard a paid engagement would require — including a tamper-proof evidence trail proving exactly what happened, and the point where I deliberately stopped rather than cross an ethical line.
// Overview — Grey-box penetration test of a peer-supplied Apache 2.4.58 host on Ubuntu 24.04.2 LTS, conducted against a self-hardened PostgreSQL 16 server built to CIS Level 1 Benchmark. Full methodology documented: reconnaissance, host enumeration, two exploitation attempts, a reproducible SHA-256 evidence chain, and countermeasures mapped to ISO/IEC 27002:2022 and CIS Apache HTTP Server 2.4 Benchmark v1.4.0 — then closed with a detection perspective that maps every offensive step to the log source and Wazuh rule that would catch it, turning a one-sided test into a purple-team artefact.

Attack Path

The engagement unfolded as a single connected chain. A full-port SYN scan surfaced only two services — SSH on 22 and Apache 2.4.58 on 80 — but the server banner disclosed its exact version and OS unprompted: the first information leak. HTTP fingerprinting confirmed an active Index of / at the web root before any directed probing, and Gobuster narrowed the surface further — /server-status returned 403, proving mod_status was loaded but only access-controlled, partial hardening rather than removal. Two unauthenticated GET requests then tested the two strongest leads: /server-status held at 403, but the web root returned 200 with a live directory listing (CWE-548) — the finding that would expose any future backup archive, source file, or credential string to anonymous enumeration and seed follow-on attacks. Authenticated local enumeration with LinPEAS closed the picture: an over-privileged sudo account and services irrelevant to the web stack widened the host's attack surface well beyond HTTP.

The control case ran in parallel. The self-hardened PostgreSQL 16 server — same Ubuntu base, same hypervisor — returned nothing enumerable: only SSH reachable, the database loopback-bound, every CIS Level 1 control satisfied, no escalation path found. Same OS, opposite outcome — configuration, not platform, decided breach resistance. That contrast is the engagement's headline finding and the way these results would be framed for a client.


Attack Path Timeline

  1. Reconnaissancenmap -sS -sV -O -p-: full-port SYN scan with service and OS

fingerprinting surfaced exactly two services: SSH on 22/tcp and Apache 2.4.58 on 80/tcp. Key observation: the server banner disclosed its exact version and OS unprompted — the engagement's first information leak (feeds F4).

  1. Enumeration — WhatWeb -a 3 · Gobuster (common.txt, 4,615 paths) · Nikto v2.5.0

(8,102 requests): HTTP fingerprinting confirmed an active Index of / at the web root before any directed probing. /server-status returned 403 — proving mod_status was loaded but only access-controlled (partial hardening, F5). Nikto returned 15 findings including missing security headers (F3).

  1. Exploitation — curl / manual HTTP, two unauthenticated GET requests: GET /server-status

held at 403; GET / returned 200 with a live directory listing — CWE-548, the engagement's primary finding (F1).

  1. Post-Exploitation — LinPEAS (PEASS-ng v0.2.0), scoped to the user home tree, halted

pre-token-harvest: an over-privileged sudo account with no command restrictions (F6) and services irrelevant to the web stack — snapd, ModemManager — widening the attack surface (F7).

  1. Reporting — OWASP risk scoring · ISO/IEC 27002:2022 · CIS Apache 2.4 Benchmark v1.4.0:

seven findings, each severity-rated and mapped to a concrete countermeasure. Evidence: 24 files (4.1 MiB), every artefact SHA-256 hashed, dual session logs.


Engagement Scope

AspectDetail
TargetApache 2.4.58 on Ubuntu 24.04.2 LTS — peer-operated host
ModelGrey-box — authenticated console access available; disruptive exploits out of scope
EnvironmentTwo VirtualBox guests (2 vCPUs / 2 GB RAM) on an isolated /24 host-only subnet (addresses tokenised as 192.0.2.0/24). Kali Linux workstation as attack platform.
ConstraintUnauthenticated HTTP vectors only. No command injection, LFI/RFI, or brute-force. All actions logged and SHA-256 verified.
Defended AssetPostgreSQL 16 server — built to CIS Level 1 standard. Exposed no enumerable attack surface.

PTES Phase Map

PTES PhaseActivityReference
Pre-engagementGrey-box scope, rules of engagement, lab topology agreedengagement-scope.md
Intelligence gatheringFull-port SYN scan, HTTP fingerprinting, directory enumerationreconnaissance.md
Threat modellingRisk questions and defended-asset definitionREADME §2
Vulnerability analysisFindings cross-referenced to CWE, CIS Apache 2.4, OWASPvulnerability-report.md
ExploitationTwo unauthenticated HTTP GET attemptsexploitation.md
Post-exploitationLinPEAS privilege/service enumeration (scoped, halted pre-token-harvest)README §3.3
ReportingFindings, severity, ISO/IEC 27002-mapped countermeasurescountermeasures.md

Toolchain

ToolUse
nmap -sS -sV -O -p-Full-port SYN scan with service and OS fingerprinting. Identified open ports 22/tcp (SSH) and 80/tcp (Apache 2.4.58).
Gobuster dirDirectory brute-force with common.txt (4,615 paths). Confirmed /server-status access-controlled (403) and web-root indexing active.
WhatWeb -a 3HTTP fingerprinting at aggression level 3. Resolved Apache[2.4.58], HTTPServer[Ubuntu Linux], Index-Of — version and indexing disclosure.
Nikto v2.5.08,102 requests, 15 findings. Confirmed missing security headers, directory indexing at multiple paths, permitted OPTIONS methods.
LinPEAS (PEASS-ng v0.2.0)Host privilege and service enumeration. Scoped to the user home tree, halted pre-API-key phase. Identified unrestricted sudo, unnecessary services, autoindex config.
curl / manual HTTPTwo unauthenticated exploitation attempts: GET /server-status (403 returned) and GET / (200 — directory listing confirmed, CWE-548).

Findings

#FindingSeverityCWE / ControlRemediation
F1Directory auto-indexing enabled at web root — Options Indexes active; web root returned HTTP 200 with auto-generated listing. Any future file drops exposed to unauthenticated enumeration.Medium-HighCWE-548 · CIS Apache 2.4 control 2.5a2dismod autoindex; Options -Indexes in virtualhost config
F2Cleartext HTTP only — no TLS virtual host, no redirect from 80 to 443MediumCWE-319HTTP→HTTPS 301 redirect; TLS virtual host with valid certificate
F3Security headers absent — X-Frame-Options, X-Content-Type-Options (X-XSS-Protection also absent) on all responsesMediumCWE-1021 · CWE-693Header always set X-Frame-Options DENY; X-Content-Type-Options nosniff
F4Service version and OS disclosure — banner returned Apache/2.4.58 (Ubuntu)LowCWE-200ServerTokens Prod; ServerSignature Off
F5mod_status loaded — GET /server-status 403 confirms module present (partial CIS compliance)LowCWE-200Require ip 127.0.0.1 on /server-status; a2dismod status if unused
F6Host user in sudo group with unrestricted command executionMediumCWE-250Remove from sudo; least-privilege; key-only SSH; scoped sudoers
F7Unnecessary services running (snapd, ModemManager)LowCIS minimisation controlsystemctl disable --now snapd ModemManager
// PostgreSQL Server — Baseline Posture — All CIS PostgreSQL 16 Benchmark v2.0.0 Level 1 controls satisfied. Port scan: only 22/tcp reachable externally; 5432/tcp loopback-bound. No world-writable data directories. No privilege escalation paths identified by LinPEAS. scram-sha-256 authentication for all host connections. The same Ubuntu base, hardened correctly, produces zero enumerable findings.
// CVSS caveat — Severity ratings above are first-order estimates using the OWASP qualitative likelihood × impact model; they are not formally CVSS-scored.

Reproducible Methodology

The commands below use $PEER_IP as a placeholder — substitute the target address before running. All commands were recorded to timestamped session logs and every output artefact was SHA-256 hashed at acquisition (see Evidence Chain below).

Reconnaissance — README.md §3.2 / methodology/reconnaissance.md:10-62:

# Full-port SYN scan with service and OS fingerprinting
nmap -sS -sV -O -p- $PEER_IP -oA apache_full

# Directory brute-force
gobuster dir -u http://$PEER_IP/ -w /usr/share/wordlists/dirb/common.txt -o gobuster.txt

# HTTP fingerprinting
whatweb -a 3 http://$PEER_IP -v | tee whatweb.txt
nikto -h $PEER_IP -o nikto.html

Evidence integrity — README.md §3.5 / evidence-chain.md §4:

# At acquisition — manifest over the whole evidence set
# (screenshot filenames abbreviated below; see evidence-chain.md §4 for full list)
sha256sum external_session.log internal_session.log status.txt \
          [status-screenshot] listing_root.html [listing-screenshot] \
          nmap/* gobuster.txt whatweb.txt nikto.html linpeas_out.txt > evidence.sha256

# At reporting / by any reviewer — must print "OK" for every line
sha256sum -c evidence.sha256

# Archive-level digest — verify the bundle as a unit before unpacking
sha256sum apache_pentest.zip > apache_pentest.zip.sha256

Hardening remediation — methodology/countermeasures.md §1:

# Disable directory auto-indexing (remediates CWE-548 / F1)
sudo a2dismod autoindex && sudo systemctl restart apache2

# UFW default-deny with minimal permitted services
sudo ufw default deny incoming
sudo ufw allow 22/tcp
sudo ufw allow 443/tcp
sudo ufw enable

mod_status restriction — methodology/countermeasures.md §1:

# /etc/apache2/conf-available/status-local.conf
<Location /server-status>
    SetHandler server-status
    Require ip 127.0.0.1
</Location>

Wazuh detection rules — README.md §5 (illustrative, rules 100600 and 100601):

<group name="apache,web,recon,attack,">
  <!-- Many 404/403s from one source in a short window = directory/vuln scanning -->
  <rule id="100600" level="10" frequency="50" timeframe="30">
    <if_matched_sid>31108</if_matched_sid>
    <same_source_ip />
    <description>Web reconnaissance: 404/403 burst from one source (Gobuster/Nikto-class scan) — T1595</description>
    <mitre><id>T1595.003</id></mitre>
  </rule>
</group>

<group name="linux,audit,privesc,attack,">
  <rule id="100601" level="12">
    <if_group>audit</if_group>
    <field name="audit.command" type="pcre2">(find .*-perm|sudo -l|linpeas)</field>
    <description>Local privilege-escalation enumeration (LinPEAS-class behaviour) — T1083/T1548</description>
    <mitre><id>T1083</id><id>T1548.003</id></mitre>
  </rule>
</group>

Detection Perspective — The Defender's View

A finding is only half the story. The other half — and the one a SOC cares about — is would anyone have noticed? Every offensive action in the engagement maps to the log evidence it generates and the detection logic that would surface it, mirroring the offence→detection discipline practised in gauntlet and feeding the Wazuh rules in the companion SIEM lab (watchtower — in build, publishes when the lab goes public).

The defining characteristic of this engagement's recon is that it was loud. Nikto alone issued 8,102 requests and Gobuster tested 4,615 paths — that volume is trivially detectable, and the honest defensive finding is that the target had no logging pipeline that would have raised an alert.

Offensive actionLog sourceATT&CKDetection logic
Full-port SYN scan (nmap -sS -p-)Firewall / NetFlow / SuricataT1595.001 / T1046Many SYNs to many (mostly closed) ports from one source in a short window — connection-rate anomaly per source
Directory brute-force (Gobuster, 4,615 paths)Apache access.logT1595.003A burst of 404/403 responses to non-existent paths from a single IP — the canonical web-enumeration signature
Vulnerability scan (Nikto, 8,102 requests)Apache access.logT1595.002High request volume + the default Nikto User-Agent + probes to /.hta, /.htpasswd, test CGI paths
Directory-index discovery (CWE-548)Apache access.logT1083GET / returning HTTP 200 with Index of titles — repeated listing requests = active enumeration
/server-status probeApache access.logT1592Requests to status/admin endpoints; the 403 is logged and is itself the indicator
LinPEAS host enumerationauditd (execve)T1059 / T1083 / T1082A single process rapidly reading /etc/passwd, running find / -perm -4000, sudo -l, and crontab — a textbook local-recon execve burst
sudo privilege use (F6)auditd / auth.logT1548.003Privileged command execution by the host user — baseline and alert on anomalous sudo

Two detections worth writing — the loudest, highest-fidelity signals:

1. Web reconnaissance — 404/403 burst per source. Gobuster and Nikto generate hundreds-to-thousands of failed requests from one IP. A Wazuh correlation rule keyed on the Apache access log catches this with almost no false positives, because legitimate users do not request 4,000 non-existent paths. See rule 100600 in Reproducible Methodology above.

2. Host enumeration — the LinPEAS execve pattern. Once on the host, the enumeration script's behaviour is high-signal: a single parent rapidly invoking find … -perm, sudo -l, and cat /etc/passwd. An auditd-backed Wazuh rule on that execve cluster catches privilege-escalation recon. See rule 100601 in Reproducible Methodology above.

// The honest defensive finding — The Apache host had no detection pipeline at all: no IDS, no log shipping, auditd not forwarding. The noisy scans above would have gone entirely unobserved. The countermeasures harden the attack surface, but a host with this exposure also needs the monitoring layer — a SIEM integration would turn every row in the table above into an alert, closing the loop from "exploitable" to "exploitable and detected."

Evidence Chain

Every artefact is integrity-protected so a reviewer can prove nothing was altered between acquisition and reporting — the same chain-of-custody discipline a court or a client audit would require.

TypeDetail
Session logsexternal_session.log (all external commands) + internal_session.log (concurrent enumeration) — timestamped, append-only during the engagement
Artefactsapache_full.nmap, gobuster.txt, whatweb.txt, nikto.html, linpeas_out.txt, status.txt, listing_root.html
IntegrityAll 24 files in apache_pentest.zip (4.1 MiB) SHA-256 hashed into a single reproducible manifest
ScreenshotsTwo screenshots: mod_status 403 response (F5) and directory listing at web root (F1 — CWE-548 confirmed)

The manifest is itself the verification instrument — any reviewer can re-verify the whole evidence set with one command, and a single changed byte in any artefact fails its line:

# At acquisition — one manifest over the whole evidence set
# (screenshot filenames abbreviated; see evidence-chain.md §4 for the full artefact list)
sha256sum external_session.log internal_session.log status.txt \
          [status-screenshot] listing_root.html [listing-screenshot] \
          nmap/* gobuster.txt whatweb.txt nikto.html linpeas_out.txt > evidence.sha256

# At reporting / by any reviewer — must print "OK" for every line
sha256sum -c evidence.sha256

# Archive-level digest — verify the bundle as a unit before unpacking
sha256sum apache_pentest.zip > apache_pentest.zip.sha256

The forensic reasoning — how integrity, authenticity, and custody are kept distinct; chain of custody applied to digital evidence; independent reviewer verification; and the honest limits of an unsigned manifest — is documented in full in evidence-chain.md.


Skills Demonstrated

SkillEvidence
Network ReconnaissanceFull-port SYN scan with nmap -sS -sV -O -p-. Service and OS fingerprinting.
Web Application EnumerationDirectory brute-force (Gobuster), HTTP fingerprinting (WhatWeb, Nikto v2.5.0).
Host Privilege AnalysisLinPEAS privilege escalation enumeration — sudo, SUID/SGID, cron, service audit.
Vulnerability IdentificationCWE-548 directory listing; mod_status exposure; absent security headers; least-privilege violation.
Risk QuantificationOWASP qualitative likelihood × impact risk scoring across 7 findings.
Database HardeningPostgreSQL 16 built to CIS Level 1 Benchmark v2.0.0; scram-sha-256 auth; UFW isolation.
Evidence IntegrityReproducible SHA-256 manifest (sha256sum -c); dual session logs; structured evidence archive (24 files, 4.1 MiB). Forensic reasoning documented in evidence-chain.md.
Control Framework MappingFindings and countermeasures mapped to ISO/IEC 27002:2022 and CIS Apache 2.4 Benchmark v1.4.0.
Detection Engineering (Purple-Team)Each offensive step mapped to its log source, ATT&CK technique, and a Wazuh detection rule — feeds the companion SIEM lab.

Repository

// GitHub — Full methodology, findings, countermeasures, and research references: github.com/rootdrifter/spectre — one repository in the github.com/rootdrifter portfolio.