Classroom Glossary Public page

NET-301 Week 10 -- Penetration Testing Cross-Cut: Offense Informs Defense

1,295 words

"Every attack leaves a trace. The attacker's job is to minimize the trace. The defender's job is to detect the minimum trace. Understanding the attacker's job is a prerequisite for doing the defender's job well." -- Bejtlich, The Practice of Network Security Monitoring, Ch 1


Lecture (90 min)

10.1 Why Offense Informs Defense

Weeks 6-9 built the NSM infrastructure: Suricata, Zeek, RITA, SIEM, 5G anomaly detection, QUIC visibility gap documentation. Week 10 inverts the lens: students operate an attack chain against a sandboxed lab network and observe what that chain looks like from the defender's side.

The pedagogical goal is not to teach offensive technique. It is to build the calibration that turns NSM output from noise into signal. An analyst who has never run a beaconing C2 client cannot make good decisions about RITA's beacon-detection threshold. An analyst who has never run an nmap scan cannot interpret conn.log scan bursts correctly.

Lab 12 authorization reminder: All exercises in this chapter use an isolated Containerlab network. No external systems are touched. The exercise is authorized within the lab scope. Students must not apply these techniques outside the designated lab environment.

10.2 Network Reconnaissance from the NSM Side

Attack side: nmap -sS 10.0.1.0/24 -T4 — a SYN scan of a /24 subnet.

What this generates in NSM data:

  • Zeek conn.log: 254 connection records to 10.0.1.1 through 10.0.1.254, each with state=S0 (SYN sent, no SYN-ACK received) or state=SF (SYN+SYN-ACK+RST for open ports). Duration is sub-second per host. Total connection burst: ~3,000 half-open connections in under 5 seconds at T4 timing.
  • Suricata alerts: ET rules ET SCAN Nmap SYN Scan and ET SCAN Potential SSH Scan fire by default. The rules use rate-based thresholds (threshold type both, track by_src).
  • Zeek notice.log: Zeek's Scan::Scan_Summary script fires for hosts that scan more than Scan::activate_delay hosts within the window.

What T4 doesn't catch: Slow scan (--T1, 1 packet per 15 seconds) defeats threshold-based detection. Decoy scan (-D RND:10) poisons source-IP attribution but does not hide the scan pattern. OS fingerprinting (-O) generates distinctive IPID and TCP option sequences that Zeek's weird.log may flag.

Implication for NSM: Threshold tuning matters. An nmap -T1 slow scan against 254 hosts over 63 minutes generates 1 connection per 15 seconds -- below most threshold rules. Detection requires statistical baseline analysis (RITA connection-count anomaly, not alert thresholds).

10.3 C2 Infrastructure Design and Beacon Detection

Attack side: Metasploit meterpreter with HTTPS beacon, sleep interval 60s, jitter 30%.

What jitter does to RITA: RITA's beaconing detection scores connections by their inter-arrival-time regularity. A 60-second beacon with 0% jitter produces intervals of exactly 60 seconds -- RITA scores this as high-confidence beaconing. A 30% jitter produces intervals ranging from 42 to 78 seconds -- the coefficient of variation is ~17%, which RITA's default threshold (skew score + madm score) detects less reliably.

The jitter > 25% rule: Red team doctrine treats 25% jitter as the approximate threshold below which RITA reliably detects beaconing, and above which detection is inconsistent. This is empirical; the exact threshold depends on RITA's scoring parameters, but 25-35% is the range where the detection boundary lies.

Domain fronting: The meterpreter payload is configured with a legitimate CDN domain (e.g., a major cloud provider's CDN) as the SNI/Host header, while the actual destination is the C2 server IP behind the same CDN. Zeek's ssl.log shows server_name = legitimate-cdn.com. The C2 domain never appears in NSM logs.

NSM detection for domain fronting:

  • Mismatch between SNI and CN: ssl.log server_name vs. ssl.log subject -- if the certificate subject doesn't match the SNI, the connection is suspect. Zeek's ssl_certificate_expired and ssl_unknown_issuer notices fire for self-signed certs but not for legitimate CDN certificates.
  • JA3 hash: Meterpreter's embedded TLS library has a distinctive JA3 hash. If the JA3 appears for a connection to a CDN that normally serves browser traffic, the fingerprint mismatch is a hunt trigger.
  • Byte-count ratio: C2 beacons typically have very small request bodies and small response bodies (keepalive + task delivery). An HTTPS session to a CDN with consistently sub-1KB request/response pairs is anomalous vs. normal CDN traffic.

10.4 Lateral Movement Signatures in Zeek

SMB traversal -- Zeek smb_files.log:

# Identify hosts writing executable files over SMB
zeek-cut ts id.orig_h id.resp_h action name < smb_files.log \
  | awk '$4 == "SMB::FILE_OPEN" && $5 ~ /\.exe$|\.dll$|\.bat$/' \
  | sort -k2

Lateral movement via PsExec, WMI remote exec, or CobaltStrike jump psexec generates SMB file-write records in smb_files.log for the service binary being staged to ADMIN$ or C$.

WinRM -- Zeek dce_rpc.log:

# WinRM over HTTP(S) port 5985/5986 -- look for DCE/RPC calls
zeek-cut ts id.orig_h id.resp_h endpoint operation < dce_rpc.log \
  | grep -i "WS-Management\|winrm\|Execute"

Pass-the-Hash vs. Kerberoasting:

Technique Network signature Zeek log
Pass-the-Hash (NTLM) NTLM Type 1/2/3 exchange; no Kerberos ticket ntlm.log (NTLMSSP auth to SMB/WinRM/HTTP)
Overpass-the-Hash (PTH → Kerberos) Kerberos AS-REQ with RC4 encryption type (etype 23) kerberos.log: request_type=AS, cipher=rc4-hmac
Kerberoasting Kerberos TGS-REQ for service tickets; RC4 etype 23 or AES kerberos.log: request_type=TGS, high frequency of service ticket requests

Zeek Kerberos anomaly detection:

# Kerberoasting detection: many TGS requests from one source in short window
event zeek_init()
    {
    SumStats::create([$name="kerberoasting",
                      $epoch=5mins,
                      $reducers=set(SumStats::SUM),
                      $threshold=30.0,
                      $threshold_crossed(key: SumStats::Key, result: SumStats::Result) = {
                          NOTICE([$note=NetSec::Kerberoasting_Activity,
                                  $msg=fmt("Kerberoasting: %s made %d TGS requests in 5 min",
                                           key$host, result$sum)]);
                      }]);
    }

event kerberos_request(c: connection, msg: KRB::KDC_Request) &priority=5
    {
    if ( msg$msg_type == KRB::AS_REQ || msg$msg_type == KRB::TGS_REQ )
        SumStats::observe("kerberoasting", [$host=c$id$orig_h], [$num=1]);
    }

10.5 Exfiltration over DNS

Attack side: iodine DNS tunnel -- encodes arbitrary data in DNS query labels; decodes server responses as data.

What this generates in Zeek dns.log:

# High-entropy subdomain labels: length >30 chars, high character diversity
zeek-cut ts id.orig_h query qtype_name < dns.log \
  | awk 'length($3) > 30' | head -20

Entropy-based detection:

import math

def label_entropy(label: str) -> float:
    if not label:
        return 0.0
    freq = {}
    for c in label:
        freq[c] = freq.get(c, 0) + 1
    probs = [f / len(label) for f in freq.values()]
    return -sum(p * math.log2(p) for p in probs)

# iodine labels typically have entropy > 3.5 bits/char
# Normal domain labels average 2.5-3.2 bits/char
ENTROPY_THRESHOLD = 3.5

RITA DNS tunneling detection:

rita show-exploded-dns hunt_dataset --long-hostnames

RITA flags FQDNs where individual subdomain labels exceed length thresholds, combined with large TXT response sizes. The iodine default configuration uses TXT records for downlink data, generating TXT responses of 200+ bytes -- anomalous vs. legitimate SPF/DKIM TXT records.

10.6 Evasion Technique Catalog

Technique What it evades What it doesn't evade NSM gap
QUIC/HTTP3 for C2 (Ch 9) JA3, HTTP-level detection, URL logging Flow metadata, SNI (for now) QUIC visibility gap
Certificate pinning JA3 mismatch detection Flow metadata, byte-count analysis TLS inspection bypass
Encrypted SNI (ECH) SNI-based blocking and alerting Flow metadata ECH adoption is partial as of 2026
Jitter > 25% RITA beacon scoring Long-session detection, byte-count anomaly Threshold calibration
Domain fronting C2 domain in logs JA3 mismatch, byte-count ratio anomaly CDN traffic analysis
Slow scan (T1) Threshold-based scan alerts Statistical baseline anomaly over days Baseline window
Process-hollowing (endpoint) Network-layer detection (no new process) Endpoint telemetry (EDR) Network-only NSM blind spot

The defense implication: No single NSM data type closes all evasion paths. The defense-in-depth model requires: (a) network flow metadata for long-session and byte-count analysis; (b) DNS log analysis for tunneling and exfiltration; (c) TLS metadata for JA3 and SNI-based detection; (d) endpoint telemetry (EDR) for evasions that are network-invisible.


Architecture Comparison Sidebar: NSM Detection Coverage by Attack Phase

Attack phase Suricata (signature) Zeek (log analytics) RITA (statistical) Endpoint (EDR)
Reconnaissance (nmap) High (ET SCAN rules) Medium (notice.log scan) Low (threshold-based) None
Initial access (exploit) High (ET EXPLOIT rules) Medium (protocol anomaly) None High
C2 (HTTPS beacon, low jitter) Medium (JA3, byte ratio) Medium (ssl.log analysis) High (beacon score) High
C2 (QUIC, jitter >25%) Low (QUIC SNI only) Low (conn.log flow only) Medium (flow metadata) High
Lateral movement (SMB) Medium (ET SMB rules) High (smb_files.log) Low High
Exfiltration (DNS tunnel) Medium (size/rate rules) High (entropy analysis) High (RITA DNS) Medium
Exfiltration (QUIC/ECH) Very low Very low Medium (flow size) High

Reading the table: Network-only NSM has high coverage for conventional reconnaissance and SMB lateral movement, medium coverage for C2, and very low coverage for QUIC + ECH exfiltration. The gaps point to where endpoint telemetry integration is not optional but mandatory for a Belt-5 NSM posture.


Reflection Prompts

  1. RITA uses coefficient of variation (CoV) and median absolute deviation (madm) to score beaconing candidates. Explain why madm is more robust than standard deviation for beacon interval analysis when an attacker uses jitter. What distribution of interval times does jitter produce, and why does that distribution break standard deviation as a measure of regularity?
  2. The Kerberoasting detection Zeek script triggers on 30 TGS requests in 5 minutes from one host. A legitimate service account (a backup agent, a monitoring system) might generate 50+ Kerberos TGS requests per 5-minute window during normal operation. How would you tune the detection to reduce false positives while preserving detection of actual Kerberoasting activity?
  3. The evasion catalog shows that process-hollowing leaves no network-layer trace. A defender using only Zeek and Suricata would miss it entirely. What is the minimum endpoint telemetry integration that would detect process-hollowing, and what network-side indicator (if any) typically co-occurs with process-hollowing-based C2?