Chapter 66

Ransomware Traffic

Modern ransomware (LockBit, Black Basta, ALPHV) follows a multi-phase network pattern: initial access → lateral movement → data exfiltration → encryption key management → encryption. Each phase has observable network signatures. Catching ransomware in its pre-encryption phases — lateral movement, exfiltration — is the only way to stop it before it encrypts data.

Scenario

A Zeek alert fires at 02:15 AM for beaconing from 10.0.0.100 to an external IP on port 443 with CV=0.04 (highly regular, 60-second interval). The analyst recognizes the Cobalt Strike pattern, but it's 3 AM and no one acts for 2 hours. During those 2 hours, the attacker pivots to the file server, exfiltrates 80 GB via FTP to a Mega.nz drop, and begins encrypting at 04:45 AM. The detection worked; the response was too slow. Understanding the full attack timeline from network data is the retrospective.

Ransomware Network Timeline

  Typical Ransomware Attack Network Signatures
  ═══════════════════════════════════════════════════════════════════

  Phase 1 — Initial access:
  └── Phishing email delivery (SMTP from external)
      Or exploitation of internet-facing service
      Or VPN credential brute force (repeated auth failures)

  Phase 2 — C2 establishment:
  └── Regular beaconing: periodic connections to external IP/domain
      JA3 matching known C2 framework
      DNS query for fresh C2 domain (usually DGA or newly registered)

  Phase 3 — Reconnaissance:
  └── LDAP queries to DC (user/group enumeration)
      SMB connections to IPC$ on multiple hosts (share enumeration)
      Kerberoasting (bulk TGS-REQ) for privilege escalation

  Phase 4 — Lateral movement:
  └── PsExec, WMI, or scheduled task across internal network
      SMB fan-out from beachhead host
      Cobalt Strike "jump" commands via SMB named pipe

  Phase 5 — Data exfiltration (double extortion):
  └── Large outbound TCP transfer to cloud storage or attacker VPS
      Common destinations: Mega.nz, Backblaze, SFTP on DO/Linode
      Large bytes_toserver (upload) to single external IP
      FTP, WebDAV, or HTTPS upload
      Timing: often hours before encryption begins

  Phase 6 — Encryption key management:
  └── TLS connection to key management server
      Often the same C2 from Phase 2
      Very small data exchange (just key delivery)

  Phase 7 — Encryption (by this point it's too late):
  └── Local disk activity — not network visible
      SMB file access surge on shared drives (if encrypting shares)
      MASSIVE increase in SMB write operations to file servers

Pre-Encryption Detection

bashransomware-detection.sh
#!/bin/bash
LOG_DIR="${1:-/opt/zeek/logs/current}"

echo "=== Phase 2: C2 Beaconing ==="
awk 'NR>8 && !/^#/' "$LOG_DIR/conn.log" | \
  awk -F'\t' '$5 !~ /^(10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.)/ {
    print $1"\t"$3"\t"$5"\t"$6
  }' | python3 -c "
import sys, math
from collections import defaultdict
flows = defaultdict(list)
for line in sys.stdin:
    parts = line.strip().split('\t')
    if len(parts) >= 4:
        try:
            flows[(parts[1], parts[2], parts[3])].append(float(parts[0]))
        except: pass

for (src, dst, port), ts in flows.items():
    ts.sort()
    if len(ts) < 8: continue
    ivs = [ts[i+1]-ts[i] for i in range(len(ts)-1) if 0 < ts[i+1]-ts[i] < 3600]
    if len(ivs) < 5: continue
    mean = sum(ivs)/len(ivs)
    if mean < 5: continue
    cv = math.sqrt(sum((x-mean)**2 for x in ivs)/len(ivs))/mean
    if cv < 0.15:
        print(f'C2_BEACON cv={cv:.3f} n={len(ts)} int={mean:.0f}s {src}→{dst}:{port}')
" | head -10

echo ""
echo "=== Phase 3: Kerberoasting ==="
awk 'NR>8 && !/^#/' "$LOG_DIR/kerberos.log" 2>/dev/null | \
  awk -F'\t' '$7=="TGS" {print $3}' | sort | uniq -c | sort -rn | \
  awk '$1 > 5 {print "KERBEROAST: " $1 " requests from " $2}'

echo ""
echo "=== Phase 4: Lateral movement (SMB fan-out) ==="
awk 'NR>8 && !/^#/' "$LOG_DIR/conn.log" | \
  awk -F'\t' '$6=="445" && $5 ~ /^(10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.)/ {
    print $3"\t"$5
  }' | sort -u | awk -F'\t' '{print $1}' | sort | uniq -c | sort -rn | \
  awk '$1 > 5 {print "SMB_FANOUT: " $1 " targets from " $2}'

echo ""
echo "=== Phase 5: Data exfiltration (large outbound transfer) ==="
awk 'NR>8 && !/^#/' "$LOG_DIR/conn.log" | \
  awk -F'\t' '
    $5 !~ /^(10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.)/ &&
    $9+0 > 50000000 {
      printf "EXFIL %.0fMB %s → %s:%s\n", $9/1048576, $3, $5, $6
    }' | sort -rn | head -10

echo ""
echo "=== Phase 5: Cloud storage upload (Mega, Backblaze, Dropbox, etc.) ==="
awk 'NR>8 && !/^#/' "$LOG_DIR/ssl.log" | \
  awk -F'\t' '$8 ~ /(mega|backblaze|dropbox|onedrive|drive\.google|wetransfer)/ {
    print $1"\t"$3"\t"$8
  }' | head -20

echo ""
echo "=== Phase 6: Small TLS connections post-lateral-movement (key delivery) ==="
awk 'NR>8 && !/^#/' "$LOG_DIR/conn.log" | \
  awk -F'\t' '
    $5 !~ /^(10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.)/ &&
    $9+0 > 0 && $9+0 < 10000 && $10+0 < 10000 {
      print $3"\t"$5"\t"$6"\t"$9"\t"$10
    }' | sort | uniq -c | sort -rn | head -10
Common mistake: alerting only on encryption-phase indicators (SMB mass write)

Many ransomware detections focus on the encryption phase: a sudden surge of SMB write operations to file servers, high disk activity, or SIEM rules that fire when many files get renamed to .locked extensions. These detections are correct — but they fire too late. By the time encryption starts, the attacker has been in the network for hours (often days), completed lateral movement, and already exfiltrated data. Detecting encryption is useful for containment, but it cannot prevent data theft and provides no opportunity for pre-encryption remediation. Effective ransomware defense requires detecting Phase 2 (C2 beaconing) or Phase 3 (Kerberoasting, lateral movement). C2 beaconing detection at Phase 2 gives you hours or days of lead time before encryption. An SOC that fires on beaconing at 2 AM and responds within 30 minutes can eject the attacker before the first byte of exfiltration. The same SOC that only alerts on encryption at 4 AM is doing containment, not prevention.

Q & A

Q: During a ransomware incident, how do I use network data to determine the data exfiltration scope?

Exfiltration scope determination from network data, step by step: (1) Identify the exfiltration connection: find the large outbound TCP/TLS connection(s) in Zeek conn.log (bytes_toserver > 10 MB to external IP). Look for the destination IP — it's usually a cloud storage service or attacker VPS. (2) Identify the timeline: when did the exfiltration start and end? The conn.log timestamps tell you. (3) Map to source hosts: which internal host(s) made the large transfer? This tells you which machines the attacker staged data from. (4) Correlate with SMB activity: Zeek conn.log + the SMB log show which file servers the staging host connected to just before exfiltration — these are the data sources. (5) Calculate volume: add up bytes_toserver across all exfiltration connections. This gives you an upper bound on data volume. (6) Arkime PCAP retrieval: if you have Arkime, retrieve the actual TLS session PCAP. If TLS 1.2 with known session key (from SSLKEYLOGFILE), you may be able to decrypt and see the file listing or cloud API requests that reveal exactly what was uploaded. Without decryption, volume is your primary metric. The exfiltration report to legal/notification teams needs this timeline and volume data — network forensics is often the most reliable source for exfil scope because endpoint logs may have been wiped by the attacker.