Skip to content

Lab 30: Vulnerability Triage & Virtual Patching

Chapter: 29 — Vulnerability Management | 53 — Zero-Day Response | 24 — Supply Chain Security Difficulty: ⭐⭐⭐⭐☆ Advanced Estimated Time: 4–5 hours Prerequisites: Chapter 29, Chapter 53, Chapter 24, vulnerability scanning fundamentals, web application firewall basics, CVSS scoring concepts


Overview

In this lab you will:

  1. Intake and classify 50 vulnerability scan results using combined CVSS base scores and EPSS exploitation probability — building a risk-prioritized remediation queue that accounts for both severity and real-world exploitability
  2. Calculate CVSS v4.0 Base and Environmental scores manually for five synthetic vulnerabilities — demonstrating mastery of the new v4.0 metric groups including Attack Requirements, Automatable, and Recovery
  3. Compare CVSS-only vs EPSS+CVSS prioritization strategies — identifying vulnerabilities where rankings diverge significantly and articulating the operational impact of each approach on patch scheduling
  4. Develop virtual patching rules using ModSecurity WAF rules, Snort/Suricata IPS signatures, and EDR detection rules for a synthetic zero-day vulnerability — providing immediate protection while awaiting vendor patches
  5. Design an emergency patch deployment strategy with canary groups, staged rollout percentages, rollback criteria, and verification queries — balancing speed of remediation against operational stability

Synthetic Data Only

All data in this lab is 100% synthetic and fictional. All IP addresses use RFC 5737 (192.0.2.x, 198.51.100.x, 203.0.113.x) or RFC 1918 (10.x, 172.16.x, 192.168.x) reserved ranges. All domains use *.example or *.example.com. All credentials are testuser/REDACTED. All CVE identifiers use the CVE-SYNTH- prefix and are entirely fictitious. This lab is for defensive education only — never use these techniques against systems you do not own or without explicit written authorization.


Scenario

Engagement Brief — Meridian Healthcare Systems

Organization: Meridian Healthcare Systems (fictional) Domain: meridian.example.com (SYNTHETIC) Vulnerability Scanner: scanner.meridian.example.com — 10.20.1.10 (SYNTHETIC) SIEM: siem.meridian.example.com — 10.20.1.20 (SYNTHETIC) WAF Cluster: waf.meridian.example.com — 192.0.2.50, 192.0.2.51 (SYNTHETIC) IPS Sensors: ips01.meridian.example.com — 10.20.0.5 (SYNTHETIC) Patch Management Server: wsus.meridian.example.com — 10.20.1.30 (SYNTHETIC) Patient Portal (Web App): portal.meridian.example.com — 198.51.100.10 (SYNTHETIC) EHR API Server: ehr-api.meridian.example.com — 10.20.10.50 (SYNTHETIC) Database Cluster: db01.meridian.example.com — 10.20.20.10 (SYNTHETIC) Database Cluster: db02.meridian.example.com — 10.20.20.11 (SYNTHETIC) EDR Console: edr.meridian.example.com — 10.20.1.40 (SYNTHETIC) Emergency Contact: soc@meridian.example.com (SYNTHETIC)

Summary: Meridian Healthcare Systems operates a hybrid environment with on-premises EHR systems and a cloud-hosted patient portal. A quarterly vulnerability scan has returned 50 findings across production systems, including a critical zero-day in the patient portal's authentication library. The CISO has declared an emergency response and tasked you — the senior vulnerability analyst — with triaging all findings, implementing virtual patches for immediate threats, and managing the emergency patch deployment once the vendor releases a fix.

Regulatory Context: HIPAA requires timely remediation of known vulnerabilities. Critical findings affecting systems with PHI (Protected Health Information) must have compensating controls within 48 hours or risk a reportable incident.


Certification Relevance

Certification Mapping

This lab maps to objectives in the following certifications:

Certification Relevant Domains
CompTIA Security+ (SY0-701) Domain 1: General Security Concepts (12%), Domain 4: Security Operations (28%)
CompTIA CySA+ (CS0-003) Domain 2: Vulnerability Management (22%), Domain 1: Security Operations (33%)
CompTIA CASP+ (CAS-004) Domain 1: Security Architecture (29%), Domain 2: Security Operations (30%)
SC-200 (Microsoft Security Operations Analyst) KQL Detection, Vulnerability Assessment, Threat Mitigation
CISSP Domain 6: Security Assessment and Testing, Domain 7: Security Operations
CEH (Certified Ethical Hacker) Module 5: Vulnerability Analysis, Module 18: IoT & OT Hacking
GIAC GEVA (Enterprise Vulnerability Assessor) Vulnerability Scoring, Prioritization, Remediation Strategy

Prerequisites

Required Tools

Tool Purpose Version
Python 3 + pandas Vulnerability data analysis and scoring 3.10+
ModSecurity / CRS WAF rule development 3.x / CRS 4.x
Snort or Suricata IPS signature writing 3.x / 7.x
curl / httpie HTTP request testing Latest
jq JSON parsing 1.7+
PowerShell Patch deployment scripting 7.4+
KQL environment (Azure Sentinel or demo) Detection query development N/A
Splunk (free tier or sandbox) SPL detection query development 9.x

Required Knowledge

Lab Environment Setup

# Clone the lab environment repository
git clone https://github.com/nexus-secops/lab30-vuln-triage.example.git
cd lab30-vuln-triage

# Install Python dependencies
pip install pandas numpy tabulate jinja2

# Verify ModSecurity test harness
modsec-test --version 2>/dev/null || echo "ModSecurity optional — rule syntax exercises work without runtime"

# Verify Snort/Suricata test harness
snort --version 2>/dev/null || suricata --build-info 2>/dev/null || echo "IPS optional — signature syntax exercises work without runtime"

# Load synthetic vulnerability dataset
python load_vulns.py --dataset synthetic_50.json

Lab Environment Options

This lab can be completed using:

  • Full lab environment — with ModSecurity, Snort/Suricata, and SIEM access for end-to-end testing
  • Syntax-only mode — all WAF/IPS exercises include expected output so you can validate rule syntax without a running engine
  • Paper-based mode — scoring worksheets and deployment templates can be completed as written exercises

Objectives

  1. Classify 50 vulnerabilities into Critical/High/Medium/Low categories using a combined CVSS+EPSS scoring methodology and produce a prioritized remediation queue
  2. Calculate CVSS v4.0 scores manually for five vulnerabilities, demonstrating understanding of Base, Threat, and Environmental metric groups
  3. Quantify the impact of EPSS on vulnerability prioritization by comparing CVSS-only rankings against EPSS+CVSS combined rankings and identifying the top 5 rank-change outliers
  4. Write virtual patching rules (WAF, IPS, EDR) for a synthetic zero-day vulnerability that block exploitation without disrupting legitimate application functionality
  5. Design a staged patch deployment with canary validation, progressive rollout, automated rollback triggers, and post-patch verification queries in both KQL and SPL

Phase 1: Vulnerability Discovery & Intake (45 minutes)

1.1 Understanding the Vulnerability Intake Pipeline

When a vulnerability scanner completes a quarterly scan, the raw output must be ingested, normalized, enriched, and prioritized before remediation can begin. This phase simulates the full intake pipeline.

┌─────────────────────────────────────────────────────────────────────┐
│                 VULNERABILITY INTAKE PIPELINE                       │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  Scanner Output ──► Normalize ──► Enrich ──► Score ──► Prioritize  │
│       │                │            │          │           │         │
│   Raw CVEs        Deduplicate   Add EPSS   CVSS+EPSS   Assign to   │
│   CVSS Base       Map to        Add Asset   Combined    remediation │
│   Affected        assets        context     risk score  queues      │
│   components      Remove FP     Add threat  Rank order  Set SLAs    │
│                                 intel                               │
└─────────────────────────────────────────────────────────────────────┘

1.2 Synthetic Vulnerability Scan Results

Below are the 50 vulnerability findings from the quarterly scan. All CVE identifiers, CVSS scores, and EPSS probabilities are synthetic and fictional.

Vulnerability Dataset — Meridian Healthcare Systems Quarterly Scan

# CVE ID CVSS 3.1 Base EPSS (30-day) Asset Component Description
1 CVE-SYNTH-2026-0042 9.8 0.971 portal.meridian.example.com AuthLib 2.4.1 Authentication bypass via crafted JWT — unauthenticated RCE
2 CVE-SYNTH-2026-0108 9.1 0.892 ehr-api.meridian.example.com Spring Framework 5.3.18 Remote code execution via SpEL injection
3 CVE-SYNTH-2026-0215 9.0 0.034 db01.meridian.example.com PostgreSQL 14.2 Privilege escalation via crafted SQL function — requires auth
4 CVE-SYNTH-2026-0301 8.8 0.756 portal.meridian.example.com jQuery 3.5.1 Stored XSS via DOM manipulation in patient messaging
5 CVE-SYNTH-2026-0044 8.6 0.912 waf.meridian.example.com OpenSSL 3.0.7 Buffer overflow in TLS handshake — DoS or potential RCE
6 CVE-SYNTH-2026-0519 8.4 0.003 db02.meridian.example.com PostgreSQL 14.2 Information disclosure via timing side-channel — requires local access
7 CVE-SYNTH-2026-0623 8.2 0.445 ehr-api.meridian.example.com Jackson Databind 2.13.1 Deserialization RCE via polymorphic type handling
8 CVE-SYNTH-2026-0087 8.1 0.823 portal.meridian.example.com Apache Tomcat 9.0.56 Request smuggling via malformed Transfer-Encoding
9 CVE-SYNTH-2026-0734 8.0 0.067 wsus.meridian.example.com WSUS Service 10.0.19041 Privilege escalation via WSUS update interception — MITM required
10 CVE-SYNTH-2026-0156 7.8 0.534 edr.meridian.example.com EDR Agent 4.2.1 Local privilege escalation via symlink race condition
11 CVE-SYNTH-2026-0845 7.5 0.891 portal.meridian.example.com Node.js 16.14.0 Prototype pollution via recursive merge — DoS
12 CVE-SYNTH-2026-0267 7.5 0.012 db01.meridian.example.com pgAdmin 6.8 CSRF in admin panel — requires authenticated session
13 CVE-SYNTH-2026-0390 7.4 0.678 ehr-api.meridian.example.com Log4j 2.17.0 Information disclosure via crafted log pattern — limited impact
14 CVE-SYNTH-2026-0912 7.2 0.445 portal.meridian.example.com PHP 8.1.3 Type confusion in filter_var — authentication bypass under specific config
15 CVE-SYNTH-2026-0478 7.1 0.023 wsus.meridian.example.com .NET Runtime 6.0.3 Denial of service via crafted XML — requires local network access
16 CVE-SYNTH-2026-0553 7.0 0.834 portal.meridian.example.com Nginx 1.20.2 HTTP/2 rapid reset DoS (variant)
17 CVE-SYNTH-2026-0661 7.0 0.002 db02.meridian.example.com OpenSSH 8.8p1 Double-free in ssh-agent forwarding — requires agent forwarding enabled
18 CVE-SYNTH-2026-0189 6.8 0.567 ehr-api.meridian.example.com Bouncy Castle 1.70 Weak key generation under specific entropy conditions
19 CVE-SYNTH-2026-0742 6.7 0.091 edr.meridian.example.com Windows Defender 4.18.2203 FP bypass via DLL sideloading in trusted directory
20 CVE-SYNTH-2026-0334 6.5 0.445 portal.meridian.example.com Express.js 4.17.3 Path traversal via URL-encoded double-dots in static file handler
21 CVE-SYNTH-2026-0856 6.5 0.823 ehr-api.meridian.example.com Apache Commons Text 1.9 String interpolation injection — data exfiltration via error messages
22 CVE-SYNTH-2026-0123 6.4 0.034 db01.meridian.example.com Redis 6.2.6 Lua sandbox escape — requires authenticated access to Redis CLI
23 CVE-SYNTH-2026-0967 6.3 0.156 wsus.meridian.example.com IIS 10.0 HTTP response splitting via crafted header — limited exploitability
24 CVE-SYNTH-2026-0445 6.1 0.712 portal.meridian.example.com React 17.0.2 Reflected XSS via dangerouslySetInnerHTML misuse in search results
25 CVE-SYNTH-2026-0578 6.1 0.003 edr.meridian.example.com .NET Framework 4.8 XML external entity injection in configuration parser
26 CVE-SYNTH-2026-0201 6.0 0.289 ehr-api.meridian.example.com Hibernate ORM 5.6.7 SQL injection via HQL parameter binding bypass
27 CVE-SYNTH-2026-0839 5.9 0.456 portal.meridian.example.com TLS 1.2 Config POODLE variant — CBC cipher suite weakness
28 CVE-SYNTH-2026-0714 5.8 0.012 db02.meridian.example.com MySQL Connector/J 8.0.28 SSRF via autoDeserialize connection property
29 CVE-SYNTH-2026-0356 5.5 0.678 edr.meridian.example.com Sysmon 14.0 Log evasion via event ID truncation — attacker can suppress telemetry
30 CVE-SYNTH-2026-0492 5.4 0.034 portal.meridian.example.com Bootstrap 4.6.1 DOM-based XSS in tooltip/popover via data attributes
31 CVE-SYNTH-2026-0618 5.3 0.567 ehr-api.meridian.example.com Guava 31.0.1 Temporary file creation race condition — information disclosure
32 CVE-SYNTH-2026-0783 5.3 0.002 wsus.meridian.example.com PowerShell 7.2.1 Command injection via crafted module manifest
33 CVE-SYNTH-2026-0145 5.0 0.345 portal.meridian.example.com Cookie Config Secure flag missing on session cookie — MitM session hijack
34 CVE-SYNTH-2026-0901 5.0 0.001 db01.meridian.example.com pg_stat_statements Information disclosure of query patterns — requires pg_monitor role
35 CVE-SYNTH-2026-0267b 4.8 0.234 ehr-api.meridian.example.com Swagger UI 4.1.3 Reflected XSS via crafted API spec URL
36 CVE-SYNTH-2026-0534 4.7 0.089 edr.meridian.example.com WinRM Service Information disclosure via error response verbosity
37 CVE-SYNTH-2026-0678 4.6 0.012 portal.meridian.example.com CSP Config Missing frame-ancestors directive — clickjacking potential
38 CVE-SYNTH-2026-0812 4.3 0.567 ehr-api.meridian.example.com Spring Security 5.6.2 CSRF token fixation under specific session config
39 CVE-SYNTH-2026-0234 4.3 0.001 db02.meridian.example.com PostgreSQL 14.2 Verbose error messages leak table schema — requires valid credentials
40 CVE-SYNTH-2026-0956 4.0 0.123 wsus.meridian.example.com WSUS Service 10.0.19041 Information disclosure via unauthenticated metadata endpoint
41 CVE-SYNTH-2026-0389 3.7 0.456 portal.meridian.example.com HTTP Headers Missing X-Content-Type-Options header — MIME sniffing
42 CVE-SYNTH-2026-0567 3.5 0.023 edr.meridian.example.com EDR Agent 4.2.1 Excessive log verbosity exposes internal paths
43 CVE-SYNTH-2026-0723 3.3 0.189 ehr-api.meridian.example.com API Config Rate limiting not enforced on /api/v1/auth endpoint
44 CVE-SYNTH-2026-0891 3.1 0.001 db01.meridian.example.com PostgreSQL 14.2 Minor info leak via timing differences in auth response
45 CVE-SYNTH-2026-0134 2.7 0.045 portal.meridian.example.com TLS Config TLS 1.0 enabled (deprecated) — compliance finding
46 CVE-SYNTH-2026-0456 2.4 0.001 wsus.meridian.example.com WSUS Service 10.0.19041 Self-signed certificate on internal management interface
47 CVE-SYNTH-2026-0612 2.1 0.012 edr.meridian.example.com EDR Agent 4.2.1 Unencrypted local IPC channel — requires local admin
48 CVE-SYNTH-2026-0789 1.9 0.001 db02.meridian.example.com PostgreSQL 14.2 Minor memory leak under specific query pattern — DoS unlikely
49 CVE-SYNTH-2026-0345 1.6 0.001 portal.meridian.example.com HTTP Config Server version disclosed in HTTP response header
50 CVE-SYNTH-2026-0501 1.2 0.001 ehr-api.meridian.example.com API Config OPTIONS method responds with verbose Allow header

1.3 Combined Risk Scoring Methodology

CVSS alone does not capture real-world exploitation likelihood. EPSS (Exploit Prediction Scoring System) provides a probability estimate that a vulnerability will be exploited in the wild within the next 30 days. Combining both yields a more operationally useful risk score.

Combined Risk Score Formula

Combined_Risk = (CVSS_Normalized * W_cvss) + (EPSS * W_epss) + Asset_Criticality_Modifier

Where:
  CVSS_Normalized = CVSS_Base / 10.0          (normalize to 0–1 range)
  W_cvss          = 0.4                        (severity weight)
  W_epss          = 0.4                        (exploitation probability weight)
  Asset_Criticality_Modifier:
    PHI-bearing system    = +0.20
    Internet-facing       = +0.15
    Internal-only         = +0.00
    Development/staging   = -0.05

Asset Criticality Classification

Asset Internet-Facing Contains PHI Criticality
portal.meridian.example.com Yes Yes PHI + Internet (+0.35)
ehr-api.meridian.example.com No (API gateway) Yes PHI (+0.20)
db01.meridian.example.com No Yes PHI (+0.20)
db02.meridian.example.com No Yes PHI (+0.20)
waf.meridian.example.com Yes No Internet (+0.15)
wsus.meridian.example.com No No Internal (+0.00)
edr.meridian.example.com No No Internal (+0.00)

1.4 Exercise: Calculate Combined Risk Scores

Task: For each of the 50 vulnerabilities, calculate the Combined Risk Score using the formula above. Then classify each into remediation tiers:

Tier Combined Risk Score Remediation SLA
Critical ≥ 0.80 24 hours (virtual patch immediately)
High 0.60–0.79 7 days
Medium 0.40–0.59 30 days
Low < 0.40 90 days (next quarterly cycle)

Python helper script (calculate all 50):

#!/usr/bin/env python3
"""
Lab 30 — Combined Risk Score Calculator
Meridian Healthcare Systems — Vulnerability Triage
ALL DATA IS SYNTHETIC
"""

import pandas as pd

# Vulnerability dataset (synthetic)
vulns = [
    {"id": 1,  "cve": "CVE-SYNTH-2026-0042",  "cvss": 9.8, "epss": 0.971, "asset": "portal.meridian.example.com",    "modifier": 0.35},
    {"id": 2,  "cve": "CVE-SYNTH-2026-0108",  "cvss": 9.1, "epss": 0.892, "asset": "ehr-api.meridian.example.com",   "modifier": 0.20},
    {"id": 3,  "cve": "CVE-SYNTH-2026-0215",  "cvss": 9.0, "epss": 0.034, "asset": "db01.meridian.example.com",      "modifier": 0.20},
    {"id": 4,  "cve": "CVE-SYNTH-2026-0301",  "cvss": 8.8, "epss": 0.756, "asset": "portal.meridian.example.com",    "modifier": 0.35},
    {"id": 5,  "cve": "CVE-SYNTH-2026-0044",  "cvss": 8.6, "epss": 0.912, "asset": "waf.meridian.example.com",       "modifier": 0.15},
    {"id": 6,  "cve": "CVE-SYNTH-2026-0519",  "cvss": 8.4, "epss": 0.003, "asset": "db02.meridian.example.com",      "modifier": 0.20},
    {"id": 7,  "cve": "CVE-SYNTH-2026-0623",  "cvss": 8.2, "epss": 0.445, "asset": "ehr-api.meridian.example.com",   "modifier": 0.20},
    {"id": 8,  "cve": "CVE-SYNTH-2026-0087",  "cvss": 8.1, "epss": 0.823, "asset": "portal.meridian.example.com",    "modifier": 0.35},
    {"id": 9,  "cve": "CVE-SYNTH-2026-0734",  "cvss": 8.0, "epss": 0.067, "asset": "wsus.meridian.example.com",      "modifier": 0.00},
    {"id": 10, "cve": "CVE-SYNTH-2026-0156",  "cvss": 7.8, "epss": 0.534, "asset": "edr.meridian.example.com",       "modifier": 0.00},
    {"id": 11, "cve": "CVE-SYNTH-2026-0845",  "cvss": 7.5, "epss": 0.891, "asset": "portal.meridian.example.com",    "modifier": 0.35},
    {"id": 12, "cve": "CVE-SYNTH-2026-0267",  "cvss": 7.5, "epss": 0.012, "asset": "db01.meridian.example.com",      "modifier": 0.20},
    {"id": 13, "cve": "CVE-SYNTH-2026-0390",  "cvss": 7.4, "epss": 0.678, "asset": "ehr-api.meridian.example.com",   "modifier": 0.20},
    {"id": 14, "cve": "CVE-SYNTH-2026-0912",  "cvss": 7.2, "epss": 0.445, "asset": "portal.meridian.example.com",    "modifier": 0.35},
    {"id": 15, "cve": "CVE-SYNTH-2026-0478",  "cvss": 7.1, "epss": 0.023, "asset": "wsus.meridian.example.com",      "modifier": 0.00},
    {"id": 16, "cve": "CVE-SYNTH-2026-0553",  "cvss": 7.0, "epss": 0.834, "asset": "portal.meridian.example.com",    "modifier": 0.35},
    {"id": 17, "cve": "CVE-SYNTH-2026-0661",  "cvss": 7.0, "epss": 0.002, "asset": "db02.meridian.example.com",      "modifier": 0.20},
    {"id": 18, "cve": "CVE-SYNTH-2026-0189",  "cvss": 6.8, "epss": 0.567, "asset": "ehr-api.meridian.example.com",   "modifier": 0.20},
    {"id": 19, "cve": "CVE-SYNTH-2026-0742",  "cvss": 6.7, "epss": 0.091, "asset": "edr.meridian.example.com",       "modifier": 0.00},
    {"id": 20, "cve": "CVE-SYNTH-2026-0334",  "cvss": 6.5, "epss": 0.445, "asset": "portal.meridian.example.com",    "modifier": 0.35},
    {"id": 21, "cve": "CVE-SYNTH-2026-0856",  "cvss": 6.5, "epss": 0.823, "asset": "ehr-api.meridian.example.com",   "modifier": 0.20},
    {"id": 22, "cve": "CVE-SYNTH-2026-0123",  "cvss": 6.4, "epss": 0.034, "asset": "db01.meridian.example.com",      "modifier": 0.20},
    {"id": 23, "cve": "CVE-SYNTH-2026-0967",  "cvss": 6.3, "epss": 0.156, "asset": "wsus.meridian.example.com",      "modifier": 0.00},
    {"id": 24, "cve": "CVE-SYNTH-2026-0445",  "cvss": 6.1, "epss": 0.712, "asset": "portal.meridian.example.com",    "modifier": 0.35},
    {"id": 25, "cve": "CVE-SYNTH-2026-0578",  "cvss": 6.1, "epss": 0.003, "asset": "edr.meridian.example.com",       "modifier": 0.00},
    {"id": 26, "cve": "CVE-SYNTH-2026-0201",  "cvss": 6.0, "epss": 0.289, "asset": "ehr-api.meridian.example.com",   "modifier": 0.20},
    {"id": 27, "cve": "CVE-SYNTH-2026-0839",  "cvss": 5.9, "epss": 0.456, "asset": "portal.meridian.example.com",    "modifier": 0.35},
    {"id": 28, "cve": "CVE-SYNTH-2026-0714",  "cvss": 5.8, "epss": 0.012, "asset": "db02.meridian.example.com",      "modifier": 0.20},
    {"id": 29, "cve": "CVE-SYNTH-2026-0356",  "cvss": 5.5, "epss": 0.678, "asset": "edr.meridian.example.com",       "modifier": 0.00},
    {"id": 30, "cve": "CVE-SYNTH-2026-0492",  "cvss": 5.4, "epss": 0.034, "asset": "portal.meridian.example.com",    "modifier": 0.35},
    {"id": 31, "cve": "CVE-SYNTH-2026-0618",  "cvss": 5.3, "epss": 0.567, "asset": "ehr-api.meridian.example.com",   "modifier": 0.20},
    {"id": 32, "cve": "CVE-SYNTH-2026-0783",  "cvss": 5.3, "epss": 0.002, "asset": "wsus.meridian.example.com",      "modifier": 0.00},
    {"id": 33, "cve": "CVE-SYNTH-2026-0145",  "cvss": 5.0, "epss": 0.345, "asset": "portal.meridian.example.com",    "modifier": 0.35},
    {"id": 34, "cve": "CVE-SYNTH-2026-0901",  "cvss": 5.0, "epss": 0.001, "asset": "db01.meridian.example.com",      "modifier": 0.20},
    {"id": 35, "cve": "CVE-SYNTH-2026-0267b", "cvss": 4.8, "epss": 0.234, "asset": "ehr-api.meridian.example.com",   "modifier": 0.20},
    {"id": 36, "cve": "CVE-SYNTH-2026-0534",  "cvss": 4.7, "epss": 0.089, "asset": "edr.meridian.example.com",       "modifier": 0.00},
    {"id": 37, "cve": "CVE-SYNTH-2026-0678",  "cvss": 4.6, "epss": 0.012, "asset": "portal.meridian.example.com",    "modifier": 0.35},
    {"id": 38, "cve": "CVE-SYNTH-2026-0812",  "cvss": 4.3, "epss": 0.567, "asset": "ehr-api.meridian.example.com",   "modifier": 0.20},
    {"id": 39, "cve": "CVE-SYNTH-2026-0234",  "cvss": 4.3, "epss": 0.001, "asset": "db02.meridian.example.com",      "modifier": 0.20},
    {"id": 40, "cve": "CVE-SYNTH-2026-0956",  "cvss": 4.0, "epss": 0.123, "asset": "wsus.meridian.example.com",      "modifier": 0.00},
    {"id": 41, "cve": "CVE-SYNTH-2026-0389",  "cvss": 3.7, "epss": 0.456, "asset": "portal.meridian.example.com",    "modifier": 0.35},
    {"id": 42, "cve": "CVE-SYNTH-2026-0567",  "cvss": 3.5, "epss": 0.023, "asset": "edr.meridian.example.com",       "modifier": 0.00},
    {"id": 43, "cve": "CVE-SYNTH-2026-0723",  "cvss": 3.3, "epss": 0.189, "asset": "ehr-api.meridian.example.com",   "modifier": 0.20},
    {"id": 44, "cve": "CVE-SYNTH-2026-0891",  "cvss": 3.1, "epss": 0.001, "asset": "db01.meridian.example.com",      "modifier": 0.20},
    {"id": 45, "cve": "CVE-SYNTH-2026-0134",  "cvss": 2.7, "epss": 0.045, "asset": "portal.meridian.example.com",    "modifier": 0.35},
    {"id": 46, "cve": "CVE-SYNTH-2026-0456",  "cvss": 2.4, "epss": 0.001, "asset": "wsus.meridian.example.com",      "modifier": 0.00},
    {"id": 47, "cve": "CVE-SYNTH-2026-0612",  "cvss": 2.1, "epss": 0.012, "asset": "edr.meridian.example.com",       "modifier": 0.00},
    {"id": 48, "cve": "CVE-SYNTH-2026-0789",  "cvss": 1.9, "epss": 0.001, "asset": "db02.meridian.example.com",      "modifier": 0.20},
    {"id": 49, "cve": "CVE-SYNTH-2026-0345",  "cvss": 1.6, "epss": 0.001, "asset": "portal.meridian.example.com",    "modifier": 0.35},
    {"id": 50, "cve": "CVE-SYNTH-2026-0501",  "cvss": 1.2, "epss": 0.001, "asset": "ehr-api.meridian.example.com",   "modifier": 0.20},
]

# Calculate combined risk scores
df = pd.DataFrame(vulns)
df["cvss_norm"] = df["cvss"] / 10.0
df["combined_risk"] = (df["cvss_norm"] * 0.4) + (df["epss"] * 0.4) + df["modifier"]

# Classify into tiers
def classify_tier(score):
    if score >= 0.80:
        return "Critical"
    elif score >= 0.60:
        return "High"
    elif score >= 0.40:
        return "Medium"
    else:
        return "Low"

df["tier"] = df["combined_risk"].apply(classify_tier)

# Sort by combined risk descending
df_sorted = df.sort_values("combined_risk", ascending=False)

# Display results
print("=" * 90)
print("MERIDIAN HEALTHCARE SYSTEMS — VULNERABILITY TRIAGE REPORT")
print("=" * 90)
print(f"\n{'#':<4} {'CVE':<24} {'CVSS':<6} {'EPSS':<7} {'Combined':<10} {'Tier':<10} {'Asset'}")
print("-" * 90)
for _, row in df_sorted.iterrows():
    print(f"{row['id']:<4} {row['cve']:<24} {row['cvss']:<6.1f} {row['epss']:<7.3f} "
          f"{row['combined_risk']:<10.3f} {row['tier']:<10} {row['asset']}")

# Summary
print(f"\n{'=' * 90}")
print("TIER SUMMARY")
print(f"{'=' * 90}")
for tier in ["Critical", "High", "Medium", "Low"]:
    count = len(df[df["tier"] == tier])
    print(f"  {tier:<10}: {count:>3} vulnerabilities")
print(f"  {'Total':<10}: {len(df):>3} vulnerabilities")

1.5 Deliverables — Phase 1

Phase 1 Deliverables

  • [ ] Completed combined risk score calculation for all 50 vulnerabilities
  • [ ] Tier classification (Critical/High/Medium/Low) for each vulnerability
  • [ ] Sorted remediation queue — highest combined risk first
  • [ ] Written justification for at least 3 vulnerabilities where you disagree with the automated classification (e.g., a High CVSS that you would downgrade due to asset context, or a Medium you would upgrade due to threat intelligence)
  • [ ] Identification of the top 5 vulnerabilities requiring immediate action

Phase 2: CVSS v4.0 Scoring Exercise (45 minutes)

2.1 CVSS v4.0 Overview

CVSS v4.0 introduced significant changes from v3.1, including new metric groups and refined definitions. Understanding these changes is essential for accurate manual scoring.

┌─────────────────────────────────────────────────────────────────────┐
│                     CVSS v4.0 METRIC GROUPS                         │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  BASE METRICS (Exploitability + Impact)                             │
│  ├── Attack Vector (AV): Network/Adjacent/Local/Physical           │
│  ├── Attack Complexity (AC): Low/High                               │
│  ├── Attack Requirements (AT): None/Present  [NEW in v4.0]         │
│  ├── Privileges Required (PR): None/Low/High                       │
│  ├── User Interaction (UI): None/Passive/Active  [refined v4.0]    │
│  ├── Vulnerable System Impact (VC/VI/VA): None/Low/High            │
│  └── Subsequent System Impact (SC/SI/SA): None/Low/High [NEW]      │
│                                                                     │
│  THREAT METRICS                                                     │
│  └── Exploit Maturity (E): Unreported/PoC/Attacked [replaces RL]   │
│                                                                     │
│  ENVIRONMENTAL METRICS                                              │
│  ├── Modified Base Metrics (MAV, MAC, MAT, MPR, MUI, etc.)        │
│  ├── Confidentiality/Integrity/Availability Requirements           │
│  └── (CR/IR/AR): Low/Medium/High                                   │
│                                                                     │
│  SUPPLEMENTAL METRICS [NEW — informational only, no score impact]  │
│  ├── Safety (S): Negligible/Present                                 │
│  ├── Automatable (AU): No/Yes                                       │
│  ├── Recovery (R): Automatic/User/Irrecoverable                    │
│  ├── Value Density (V): Diffuse/Concentrated                       │
│  ├── Vulnerability Response Effort (RE): Low/Moderate/High         │
│  └── Provider Urgency (U): Clear/Green/Amber/Red                   │
└─────────────────────────────────────────────────────────────────────┘

2.2 Vulnerability Descriptions for Manual Scoring

Score each of the following five synthetic vulnerabilities using CVSS v4.0. For each, provide the full vector string and calculated score.

Vulnerability A: CVE-SYNTH-2026-0042 — Authentication Bypass via Crafted JWT

Description: The AuthLib library version 2.4.1 used in the Meridian patient portal (portal.meridian.example.com) contains a critical flaw in JWT signature verification. When an RS256-signed JWT is presented with the algorithm header changed to "none", the library accepts the token without verifying the signature. An unauthenticated attacker can craft a JWT with arbitrary claims (including admin role) and send it to any authenticated endpoint. No user interaction is required. The vulnerable component is the authentication gateway, and successful exploitation grants full access to the patient portal and all patient health records accessible through it. The vulnerability is being actively exploited in the wild. The patient portal is internet-facing and processes PHI.

Scoring Worksheet A:

CVSS v4.0 Base Metrics:
  Attack Vector (AV):          ___  (Network / Adjacent / Local / Physical)
  Attack Complexity (AC):      ___  (Low / High)
  Attack Requirements (AT):    ___  (None / Present)
  Privileges Required (PR):    ___  (None / Low / High)
  User Interaction (UI):       ___  (None / Passive / Active)

  Vulnerable System Impact:
    Confidentiality (VC):      ___  (None / Low / High)
    Integrity (VI):            ___  (None / Low / High)
    Availability (VA):         ___  (None / Low / High)

  Subsequent System Impact:
    Confidentiality (SC):      ___  (None / Low / High)
    Integrity (SI):            ___  (None / Low / High)
    Availability (SA):         ___  (None / Low / High)

Threat Metrics:
  Exploit Maturity (E):        ___  (Unreported / PoC / Attacked)

Environmental Metrics:
  Confidentiality Req (CR):    ___  (Low / Medium / High)
  Integrity Req (IR):          ___  (Low / Medium / High)
  Availability Req (AR):       ___  (Low / Medium / High)

Supplemental Metrics:
  Safety (S):                  ___  (Negligible / Present)
  Automatable (AU):            ___  (No / Yes)
  Recovery (R):                ___  (Automatic / User / Irrecoverable)
  Value Density (V):           ___  (Diffuse / Concentrated)

CVSS v4.0 Vector String: CVSS:4.0/AV:___/AC:___/AT:___/PR:___/UI:___/VC:___/VI:___/VA:___/SC:___/SI:___/SA:___
Base Score: ___
Base + Threat Score: ___
Base + Threat + Environmental Score (Overall): ___

Vulnerability B: CVE-SYNTH-2026-0623 — Deserialization RCE via Polymorphic Type Handling

Description: Jackson Databind version 2.13.1 in the EHR API server (ehr-api.meridian.example.com) enables default typing, allowing polymorphic deserialization of untrusted input. An attacker with a valid API key (Low privileges) can send a crafted JSON payload containing a malicious gadget chain that achieves remote code execution on the API server. The attack requires the presence of specific gadget libraries on the classpath (Attack Requirements: Present). No user interaction is needed. Successful exploitation gives full control of the EHR API server, which has direct access to the database tier containing patient records. A proof-of-concept exploit exists in public repositories but active exploitation has not been confirmed.

Scoring Worksheet B:

CVSS v4.0 Base Metrics:
  Attack Vector (AV):          ___
  Attack Complexity (AC):      ___
  Attack Requirements (AT):    ___
  Privileges Required (PR):    ___
  User Interaction (UI):       ___

  Vulnerable System Impact:
    Confidentiality (VC):      ___
    Integrity (VI):            ___
    Availability (VA):         ___

  Subsequent System Impact:
    Confidentiality (SC):      ___
    Integrity (SI):            ___
    Availability (SA):         ___

Threat Metrics:
  Exploit Maturity (E):        ___

Environmental Metrics:
  Confidentiality Req (CR):    ___
  Integrity Req (IR):          ___
  Availability Req (AR):       ___

CVSS v4.0 Vector String: CVSS:4.0/AV:___/AC:___/AT:___/PR:___/UI:___/VC:___/VI:___/VA:___/SC:___/SI:___/SA:___
Base Score: ___
Base + Threat Score: ___
Base + Threat + Environmental Score (Overall): ___

Description: The EDR agent version 4.2.1 on endpoint edr.meridian.example.com contains a time-of-check-time-of-use (TOCTOU) vulnerability in its update mechanism. A local user with low-level access can create a symbolic link from the EDR agent's temporary update directory to a system directory. During the update process, the agent writes files with SYSTEM privileges to the symlink target. Exploitation requires precise timing (Attack Complexity: High) and the update process must be triggered (Attack Requirements: Present). Successful exploitation grants SYSTEM-level access on the local endpoint. No other systems are directly impacted. No public exploit is known.

Scoring Worksheet C:

CVSS v4.0 Base Metrics:
  Attack Vector (AV):          ___
  Attack Complexity (AC):      ___
  Attack Requirements (AT):    ___
  Privileges Required (PR):    ___
  User Interaction (UI):       ___

  Vulnerable System Impact:
    Confidentiality (VC):      ___
    Integrity (VI):            ___
    Availability (VA):         ___

  Subsequent System Impact:
    Confidentiality (SC):      ___
    Integrity (SI):            ___
    Availability (SA):         ___

Threat Metrics:
  Exploit Maturity (E):        ___

Environmental Metrics:
  Confidentiality Req (CR):    ___
  Integrity Req (IR):          ___
  Availability Req (AR):       ___

CVSS v4.0 Vector String: CVSS:4.0/AV:___/AC:___/AT:___/PR:___/UI:___/VC:___/VI:___/VA:___/SC:___/SI:___/SA:___
Base Score: ___
Base + Threat Score: ___
Base + Threat + Environmental Score (Overall): ___

Vulnerability D: CVE-SYNTH-2026-0445 — Reflected XSS via dangerouslySetInnerHTML

Description: The Meridian patient portal (portal.meridian.example.com) uses React 17.0.2 with dangerouslySetInnerHTML in the search results component. User-supplied search terms are reflected into the page without proper sanitization, enabling reflected cross-site scripting. The attack requires a user to click a malicious link (User Interaction: Active). Successful exploitation allows session hijacking and PHI exfiltration from the victim's browser session. The vulnerable system itself has low confidentiality and integrity impact (client-side only), but the subsequent system impact is high because stolen session tokens can access PHI through the portal API. Active exploitation has been observed in phishing campaigns.

Scoring Worksheet D:

CVSS v4.0 Base Metrics:
  Attack Vector (AV):          ___
  Attack Complexity (AC):      ___
  Attack Requirements (AT):    ___
  Privileges Required (PR):    ___
  User Interaction (UI):       ___

  Vulnerable System Impact:
    Confidentiality (VC):      ___
    Integrity (VI):            ___
    Availability (VA):         ___

  Subsequent System Impact:
    Confidentiality (SC):      ___
    Integrity (SI):            ___
    Availability (SA):         ___

Threat Metrics:
  Exploit Maturity (E):        ___

Environmental Metrics:
  Confidentiality Req (CR):    ___
  Integrity Req (IR):          ___
  Availability Req (AR):       ___

CVSS v4.0 Vector String: CVSS:4.0/AV:___/AC:___/AT:___/PR:___/UI:___/VC:___/VI:___/VA:___/SC:___/SI:___/SA:___
Base Score: ___
Base + Threat Score: ___
Base + Threat + Environmental Score (Overall): ___

Vulnerability E: CVE-SYNTH-2026-0356 — Log Evasion via Event ID Truncation

Description: Sysmon version 14.0 on the EDR console (edr.meridian.example.com) contains a flaw where event IDs exceeding a certain length are silently truncated, causing events to be misclassified or dropped. An attacker with local access and low privileges on any monitored endpoint can craft process creation commands that exploit this truncation to evade Sysmon logging. The attack is low complexity and requires no special conditions. The direct impact to the vulnerable system is low — only integrity is affected (log tampering). However, subsequent systems (the entire SIEM monitoring pipeline) lose visibility, creating a high subsequent integrity impact. No public exploit exists, but the technique is straightforward.

Scoring Worksheet E:

CVSS v4.0 Base Metrics:
  Attack Vector (AV):          ___
  Attack Complexity (AC):      ___
  Attack Requirements (AT):    ___
  Privileges Required (PR):    ___
  User Interaction (UI):       ___

  Vulnerable System Impact:
    Confidentiality (VC):      ___
    Integrity (VI):            ___
    Availability (VA):         ___

  Subsequent System Impact:
    Confidentiality (SC):      ___
    Integrity (SI):            ___
    Availability (SA):         ___

Threat Metrics:
  Exploit Maturity (E):        ___

Environmental Metrics:
  Confidentiality Req (CR):    ___
  Integrity Req (IR):          ___
  Availability Req (AR):       ___

CVSS v4.0 Vector String: CVSS:4.0/AV:___/AC:___/AT:___/PR:___/UI:___/VC:___/VI:___/VA:___/SC:___/SI:___/SA:___
Base Score: ___
Base + Threat Score: ___
Base + Threat + Environmental Score (Overall): ___

2.3 Deliverables — Phase 2

Phase 2 Deliverables

  • [ ] Completed CVSS v4.0 scoring worksheets for all 5 vulnerabilities
  • [ ] Full vector strings with all applicable metric groups
  • [ ] Written explanation for each metric choice (minimum 1 sentence per metric)
  • [ ] Comparison: How do your v4.0 scores compare to the v3.1 scores in the scan results? Identify any significant differences and explain why v4.0 produces a different score.

Phase 3: EPSS-Based Prioritization (30 minutes)

3.1 EPSS Fundamentals

The Exploit Prediction Scoring System (EPSS) uses machine learning to estimate the probability that a vulnerability will be exploited in the wild within the next 30 days. Unlike CVSS (which measures severity), EPSS measures likelihood of exploitation.

Key properties:

  • Range: 0.0 (0%) to 1.0 (100%) probability
  • Percentile: Relative ranking compared to all scored CVEs
  • Updated daily — scores change as threat landscape evolves
  • Based on: vulnerability age, CVSS metrics, public exploit availability, mentions on social media/dark web, vendor, CWE type, and more

3.2 Exercise: CVSS-Only vs EPSS+CVSS Ranking Comparison

Task: Create two ranked lists of the 50 vulnerabilities and compare them.

Ranking Method 1 — CVSS Only: Sort all 50 vulnerabilities by CVSS 3.1 Base Score (descending). Break ties by CVE ID.

Ranking Method 2 — EPSS+CVSS Combined: Use the Combined Risk Score from Phase 1 (which incorporates EPSS, CVSS, and asset criticality).

Python comparison script:

#!/usr/bin/env python3
"""
Lab 30 — CVSS vs EPSS+CVSS Ranking Comparison
ALL DATA IS SYNTHETIC
"""

import pandas as pd

# (Reuse vulns list from Phase 1)
# ... assume vulns list is loaded ...

df = pd.DataFrame(vulns)
df["cvss_norm"] = df["cvss"] / 10.0
df["combined_risk"] = (df["cvss_norm"] * 0.4) + (df["epss"] * 0.4) + df["modifier"]

# CVSS-only ranking
df["rank_cvss"] = df["cvss"].rank(ascending=False, method="min").astype(int)

# Combined risk ranking
df["rank_combined"] = df["combined_risk"].rank(ascending=False, method="min").astype(int)

# Calculate rank change
df["rank_change"] = df["rank_cvss"] - df["rank_combined"]

# Find biggest movers
biggest_movers = df.reindex(df["rank_change"].abs().sort_values(ascending=False).index).head(10)

print("=" * 100)
print("TOP 10 RANK-CHANGE OUTLIERS (CVSS-only rank vs EPSS+CVSS combined rank)")
print("=" * 100)
print(f"\n{'CVE':<24} {'CVSS':<6} {'EPSS':<7} {'Combined':<10} {'CVSS Rank':<11} {'Combined Rank':<15} {'Change'}")
print("-" * 100)
for _, row in biggest_movers.iterrows():
    direction = "UP" if row["rank_change"] > 0 else "DOWN"
    print(f"{row['cve']:<24} {row['cvss']:<6.1f} {row['epss']:<7.3f} "
          f"{row['combined_risk']:<10.3f} {row['rank_cvss']:<11} {row['rank_combined']:<15} "
          f"{'+' if row['rank_change'] > 0 else ''}{int(row['rank_change'])} ({direction})")

print("\n" + "=" * 100)
print("ANALYSIS QUESTIONS")
print("=" * 100)
print("""
1. Which vulnerabilities moved UP significantly in priority when EPSS was included?
   → These are lower-CVSS vulns that are actively being exploited in the wild.
   → They represent the biggest blind spot in CVSS-only approaches.

2. Which vulnerabilities moved DOWN significantly?
   → These are high-CVSS vulns with very low exploitation probability.
   → They are theoretically severe but practically unlikely to be exploited.

3. What operational impact does this have on your patch schedule?
   → Consider: developer time, change windows, risk tolerance.
""")

3.3 Key Outlier Analysis

Identify and analyze the following specific outlier patterns:

Pattern 1: High CVSS, Low EPSS (Over-prioritized by CVSS alone)

CVE CVSS EPSS CVSS Rank Combined Rank Analysis
CVE-SYNTH-2026-0215 9.0 0.034 3 ? PostgreSQL priv-esc requires auth — low real-world exploitation
CVE-SYNTH-2026-0519 8.4 0.003 6 ? Timing side-channel requires local access — extremely hard to exploit
CVE-SYNTH-2026-0734 8.0 0.067 9 ? WSUS interception requires MITM position — high barrier
CVE-SYNTH-2026-0661 7.0 0.002 16 ? OpenSSH double-free requires agent forwarding — rare config

Exercise Question: For each of these, would you override the automated ranking? Under what circumstances would a high-CVSS, low-EPSS vulnerability still warrant emergency treatment?

Pattern 2: Lower CVSS, High EPSS (Under-prioritized by CVSS alone)

CVE CVSS EPSS CVSS Rank Combined Rank Analysis
CVE-SYNTH-2026-0845 7.5 0.891 11 ? Node.js prototype pollution — trivial to exploit, widely targeted
CVE-SYNTH-2026-0553 7.0 0.834 16 ? Nginx HTTP/2 rapid reset — mass scanning observed
CVE-SYNTH-2026-0856 6.5 0.823 20 ? Commons Text interpolation — active campaign targeting Java apps
CVE-SYNTH-2026-0356 5.5 0.678 29 ? Sysmon log evasion — actively used by APT groups

Exercise Question: How would you explain to a CISO why a CVSS 5.5 vulnerability should be patched before a CVSS 9.0 vulnerability?

3.4 Deliverables — Phase 3

Phase 3 Deliverables

  • [ ] Complete dual-ranked list (CVSS-only and EPSS+CVSS combined) for all 50 vulnerabilities
  • [ ] Top 5 rank-change outliers identified and analyzed (both UP and DOWN movers)
  • [ ] Written one-paragraph executive summary explaining why EPSS+CVSS produces better outcomes than CVSS alone
  • [ ] Decision matrix: Under what specific conditions would you override EPSS-based prioritization? (List at least 3 conditions)

Phase 4: Virtual Patching (60 minutes)

4.1 Zero-Day Scenario: CVE-SYNTH-2026-0042

ZERO-DAY ALERT — CVE-SYNTH-2026-0042

Vulnerability: Authentication bypass via crafted JWT in AuthLib 2.4.1 Affected System: portal.meridian.example.com — 198.51.100.10 (SYNTHETIC) CVSS 3.1: 9.8 (Critical) | EPSS: 0.971 | Combined Risk: 1.19 (Critical) Vendor Patch: NOT AVAILABLE — zero-day Active Exploitation: Confirmed — threat intel reports active campaigns HIPAA Impact: PHI system — compensating controls required within 48 hours Status: Virtual patching is the ONLY option until vendor releases a fix

Exploitation Details (Synthetic — Educational Only)

Vulnerable Code Path:

POST /api/v1/auth/token HTTP/1.1
Host: portal.meridian.example.com
Content-Type: application/json

{
  "token": "eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzdWIiOiJhZG1pbiIsInJvbGUiOiJzdXBlcmFkbWluIiwiaWF0IjoxNzEzNTIwMDAwfQ."
}

Decoded JWT Header:

{
  "alg": "none",
  "typ": "JWT"
}

Decoded JWT Payload:

{
  "sub": "admin",
  "role": "superadmin",
  "iat": 1713520000
}

Attack Pattern:

  1. Attacker crafts JWT with "alg": "none" — bypasses signature verification
  2. Attacker sets arbitrary claims (role: superadmin)
  3. Token is sent to any authenticated API endpoint
  4. AuthLib accepts the token without verifying the (absent) signature
  5. Attacker gains full administrative access to the patient portal

Indicators of Compromise (Synthetic):

  • JWT tokens with "alg": "none" or "alg": "None" or "alg": "NONE" in the header
  • JWT tokens with empty or missing signature segment (trailing dot with no data)
  • Unusual admin-level API calls from external IP addresses
  • Access to PHI endpoints from accounts that don't normally access them
  • HTTP requests with Authorization: Bearer eyJhbGciOiJub25lI... where the base64-decoded header contains algorithm "none"

4.2 Exercise: WAF Rules (ModSecurity)

Write ModSecurity rules to block exploitation of CVE-SYNTH-2026-0042. Your rules must:

  1. Detect and block JWTs with alg: none (case-insensitive)
  2. Detect and block JWTs with missing or empty signature segments
  3. Log blocked attempts with sufficient detail for forensic analysis
  4. NOT block legitimate RS256-signed JWTs

Template — ModSecurity Rules:

# ============================================================
# Virtual Patch: CVE-SYNTH-2026-0042
# AuthLib JWT Algorithm None Authentication Bypass
# Meridian Healthcare Systems — portal.meridian.example.com
# ALL DATA IS SYNTHETIC — EDUCATIONAL ONLY
#
# Deploy to: /etc/modsecurity/rules/virtual-patches/
# Effective: Immediately upon deployment
# Expiry: Remove after vendor patch applied and verified
# ============================================================

# Rule 1: Block JWT with "alg":"none" in Authorization header
# The JWT header is base64url-encoded. "alg":"none" variants encode to:
#   eyJhbGciOiJub25lIi  (alg: none)
#   eyJhbGciOiJOb25lIi  (alg: None)
#   eyJhbGciOiJOT05FIi  (alg: NONE)
#   eyJhbGciOiJuT25FIi  (alg: nOnE) — and other case variants

SecRule REQUEST_HEADERS:Authorization "@rx (?i)bearer\s+eyJhbGciOi(?:Jub25lIi|JOb25lIi|JOT05FIi|[A-Za-z0-9+/=]*bm9uZ[A-Za-z0-9+/=]*)" \
    "id:930001,\
    phase:1,\
    deny,\
    status:403,\
    log,\
    msg:'CVE-SYNTH-2026-0042: JWT alg:none detected in Authorization header',\
    tag:'virtual-patch/CVE-SYNTH-2026-0042',\
    tag:'attack-authentication',\
    tag:'OWASP_CRS/WEB_ATTACK/JWT_BYPASS',\
    severity:'CRITICAL',\
    logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}'"

# Rule 2: Block JWT with missing signature segment in Authorization header
# Valid JWT: header.payload.signature (3 segments separated by dots)
# Attack JWT: header.payload. (empty signature) or header.payload (no third segment)

SecRule REQUEST_HEADERS:Authorization "@rx (?i)bearer\s+[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.?\s*$" \
    "id:930002,\
    phase:1,\
    deny,\
    status:403,\
    log,\
    msg:'CVE-SYNTH-2026-0042: JWT with empty/missing signature detected',\
    tag:'virtual-patch/CVE-SYNTH-2026-0042',\
    tag:'attack-authentication',\
    severity:'CRITICAL',\
    chain"
    SecRule REQUEST_HEADERS:Authorization "!@rx \.[A-Za-z0-9_-]{10,}\s*$" \
        "logdata:'Matched Data: JWT signature segment missing or too short'"

# Rule 3: Block JWT alg:none in request body (for POST /api/v1/auth/token)
# Some implementations accept the token in the request body

SecRule REQUEST_BODY "@rx (?i)eyJhbGciOi(?:Jub25lIi|JOb25lIi|JOT05FIi)" \
    "id:930003,\
    phase:2,\
    deny,\
    status:403,\
    log,\
    msg:'CVE-SYNTH-2026-0042: JWT alg:none detected in request body',\
    tag:'virtual-patch/CVE-SYNTH-2026-0042',\
    tag:'attack-authentication',\
    severity:'CRITICAL',\
    logdata:'Matched Data: %{MATCHED_VAR} found within request body'"

# Rule 4: Rate-limit authentication endpoints to slow brute-force JWT fuzzing
# Allow max 10 auth requests per minute per IP

SecRule REQUEST_URI "@rx ^/api/v1/auth/" \
    "id:930004,\
    phase:1,\
    pass,\
    nolog,\
    setvar:'ip.auth_counter=+1',\
    expirevar:'ip.auth_counter=60'"

SecRule IP:AUTH_COUNTER "@gt 10" \
    "id:930005,\
    phase:1,\
    deny,\
    status:429,\
    log,\
    msg:'CVE-SYNTH-2026-0042: Auth endpoint rate limit exceeded (>10/min)',\
    tag:'virtual-patch/CVE-SYNTH-2026-0042',\
    tag:'rate-limiting',\
    severity:'WARNING'"

Student Task: Review the rules above, then:

  1. Identify gaps: What attack variants could bypass these rules? (Hint: consider URL-encoding, chunked transfer encoding, case variations in base64)
  2. Write Rule 6: A rule that inspects the decoded JWT header (if your WAF supports Lua/transforms) to catch ALL case variants of "alg":"none"
  3. Write Rule 7: A rule that blocks requests to PHI endpoints (/api/v1/patients/*, /api/v1/records/*) when the JWT was issued more than 24 hours ago (to limit the blast radius of stolen tokens)
  4. Test plan: Document how you would test these rules without disrupting production traffic

4.3 Exercise: IPS Signatures (Snort/Suricata)

Write network-level IPS signatures to detect exploitation of CVE-SYNTH-2026-0042.

Template — Snort/Suricata Rules:

# ============================================================
# Virtual Patch: CVE-SYNTH-2026-0042 — IPS Signatures
# AuthLib JWT Algorithm None Authentication Bypass
# Meridian Healthcare Systems
# ALL DATA IS SYNTHETIC — EDUCATIONAL ONLY
# ============================================================

# Signature 1: Detect JWT alg:none in HTTP Authorization header
alert http $EXTERNAL_NET any -> 198.51.100.10 any (
    msg:"CVE-SYNTH-2026-0042 - JWT alg:none in Authorization header";
    flow:established,to_server;
    http.header;
    content:"Authorization";
    content:"Bearer ";
    content:"eyJhbGciOiJub25lIi";    # base64("{"alg":"none"")
    sid:2026004201;
    rev:1;
    classtype:web-application-attack;
    metadata:cve CVE-SYNTH-2026-0042, severity critical, deployment perimeter;
    reference:url,advisory.meridian.example.com/CVE-SYNTH-2026-0042;
)

# Signature 2: Detect JWT alg:None variant (capitalized)
alert http $EXTERNAL_NET any -> 198.51.100.10 any (
    msg:"CVE-SYNTH-2026-0042 - JWT alg:None variant in Authorization header";
    flow:established,to_server;
    http.header;
    content:"Authorization";
    content:"Bearer ";
    content:"eyJhbGciOiJOb25lIi";    # base64("{"alg":"None"")
    sid:2026004202;
    rev:1;
    classtype:web-application-attack;
    metadata:cve CVE-SYNTH-2026-0042, severity critical, deployment perimeter;
)

# Signature 3: Detect JWT alg:NONE variant (all caps)
alert http $EXTERNAL_NET any -> 198.51.100.10 any (
    msg:"CVE-SYNTH-2026-0042 - JWT alg:NONE variant in Authorization header";
    flow:established,to_server;
    http.header;
    content:"Authorization";
    content:"Bearer ";
    content:"eyJhbGciOiJOT05FIi";    # base64("{"alg":"NONE"")
    sid:2026004203;
    rev:1;
    classtype:web-application-attack;
    metadata:cve CVE-SYNTH-2026-0042, severity critical, deployment perimeter;
)

# Signature 4: Detect JWT with empty signature (generic — catches all alg:none bypasses)
# Pattern: two base64url segments followed by a trailing dot with no/minimal signature
alert http $EXTERNAL_NET any -> 198.51.100.10 any (
    msg:"CVE-SYNTH-2026-0042 - JWT with empty/missing signature";
    flow:established,to_server;
    http.header;
    content:"Authorization";
    content:"Bearer ";
    pcre:"/Bearer\s+[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.?\s*$/";
    sid:2026004204;
    rev:1;
    classtype:web-application-attack;
    metadata:cve CVE-SYNTH-2026-0042, severity critical, deployment perimeter;
)

# Signature 5: Detect rapid authentication attempts (possible JWT fuzzing)
alert http $EXTERNAL_NET any -> 198.51.100.10 any (
    msg:"CVE-SYNTH-2026-0042 - Rapid auth attempts (possible JWT fuzzing)";
    flow:established,to_server;
    http.uri;
    content:"/api/v1/auth/";
    threshold:type both, track by_src, count 20, seconds 60;
    sid:2026004205;
    rev:1;
    classtype:attempted-recon;
    metadata:cve CVE-SYNTH-2026-0042, severity high, deployment perimeter;
)

Student Task:

  1. Write Signature 6: Detect POST requests to /api/v1/auth/token with a JSON body containing a JWT that has "alg" set to "none" (inspect the request body, not just headers)
  2. Write Signature 7: Detect successful authentication responses (HTTP 200) to external IPs that were preceded by a blocked JWT attempt from the same source IP within 5 minutes (correlation signature — this indicates the attacker found a bypass)
  3. Write Signature 8: Detect access to PHI endpoints (/api/v1/patients/, /api/v1/records/) from source IPs that are NOT in the known-good IP list (geographic anomaly detection)

4.4 Exercise: EDR Detection Rules

Write endpoint detection rules that identify post-exploitation activity related to CVE-SYNTH-2026-0042.

EDR Detection Rules:

# ============================================================
# EDR Detection: CVE-SYNTH-2026-0042 Post-Exploitation
# Meridian Healthcare Systems
# ALL DATA IS SYNTHETIC — EDUCATIONAL ONLY
# ============================================================

# Rule 1: Detect unusual process spawned by web application server
- name: "CVE-SYNTH-2026-0042 - Web Server Child Process Anomaly"
  description: "Detects unusual child processes spawned by the Tomcat/Node.js process on the patient portal server, indicating possible post-exploitation RCE"
  platform: windows
  severity: critical
  condition:
    parent_process_name:
      - "java.exe"        # Tomcat
      - "node.exe"        # Node.js
    process_name:
      - "cmd.exe"
      - "powershell.exe"
      - "pwsh.exe"
      - "wscript.exe"
      - "cscript.exe"
      - "certutil.exe"
      - "bitsadmin.exe"
      - "mshta.exe"
    host: "portal-srv01.meridian.example.com"  # SYNTHETIC
  action: alert_and_isolate
  mitre_attack:
    - T1059.001  # PowerShell
    - T1059.003  # Windows Command Shell

# Rule 2: Detect mass PHI data access after authentication bypass
- name: "CVE-SYNTH-2026-0042 - Mass PHI Record Access"
  description: "Detects a single session accessing an abnormally high number of patient records, indicating possible data exfiltration after auth bypass"
  platform: application
  severity: critical
  condition:
    endpoint: "/api/v1/patients/*"
    method: "GET"
    unique_record_count_per_session: "> 50"
    time_window: "5m"
  action: alert_and_block_session
  mitre_attack:
    - T1530  # Data from Cloud Storage
    - T1005  # Data from Local System

# Rule 3: Detect token reuse from multiple geographic locations
- name: "CVE-SYNTH-2026-0042 - JWT Token Geographic Anomaly"
  description: "Detects the same JWT token being used from multiple distinct source IP ranges within a short time window, indicating token theft and reuse"
  platform: application
  severity: high
  condition:
    same_jwt_hash: true
    distinct_source_ip_count: "> 2"
    time_window: "15m"
  action: alert_and_revoke_token
  mitre_attack:
    - T1550.001  # Application Access Token

Student Task:

  1. Write Rule 4: Detect file system changes in web application directories that could indicate webshell deployment after RCE
  2. Write Rule 5: Detect outbound network connections from the portal server to known-bad IP ranges or unusual ports (data exfiltration)
  3. Write Rule 6: Detect credential dumping attempts on the portal server (post-exploitation lateral movement preparation)

4.5 Deliverables — Phase 4

Phase 4 Deliverables

  • [ ] Complete ModSecurity ruleset (Rules 1-7) for CVE-SYNTH-2026-0042
  • [ ] Complete Snort/Suricata signature set (Signatures 1-8)
  • [ ] Complete EDR detection rules (Rules 1-6)
  • [ ] Gap analysis: What exploitation paths are NOT covered by your virtual patching rules?
  • [ ] Testing plan: How would you validate these rules without impacting production?
  • [ ] Bypass analysis: Document at least 3 ways an attacker might bypass your virtual patches and how you would detect those bypasses

Phase 5: Emergency Patch Deployment (45 minutes)

5.1 Scenario: Vendor Patch Released

VENDOR ADVISORY — AuthLib 2.4.2 Released

Date: 2026-04-12 (SYNTHETIC) Advisory: SYNTH-SA-2026-042 Affected Version: AuthLib 2.4.1 and earlier Fixed Version: AuthLib 2.4.2 Fix: Strict algorithm validation — rejects "none" algorithm entirely; enforces allowlist of acceptable algorithms (RS256, RS384, RS512, ES256, ES384, ES512) Breaking Changes: Applications that intentionally used "none" algorithm for local/test tokens will break. All JWTs must now have valid signatures. Deployment Notes: Library update only — no database migration, no configuration changes required beyond updating the dependency version.

5.2 Deployment Strategy Design

Template — Emergency Patch Deployment Plan:

╔══════════════════════════════════════════════════════════════════════╗
║          EMERGENCY PATCH DEPLOYMENT PLAN                             ║
║          CVE-SYNTH-2026-0042 — AuthLib 2.4.2                        ║
║          Meridian Healthcare Systems (SYNTHETIC)                     ║
╠══════════════════════════════════════════════════════════════════════╣
║                                                                      ║
║  DEPLOYMENT PHASES                                                   ║
║                                                                      ║
║  Phase A: Pre-Deployment Validation (30 min)                        ║
║  ├── [ ] Download AuthLib 2.4.2 from vendor repository              ║
║  ├── [ ] Verify package hash: sha256:abc123... (SYNTHETIC)          ║
║  ├── [ ] Verify GPG signature from vendor signing key               ║
║  ├── [ ] Run automated test suite against updated library            ║
║  ├── [ ] Test JWT authentication flow in staging environment         ║
║  ├── [ ] Verify no regression in legitimate RS256 token handling     ║
║  └── [ ] Obtain emergency change approval (CAB fast-track)          ║
║                                                                      ║
║  Phase B: Canary Deployment (30 min)                                ║
║  ├── Target: 1 portal server (portal-canary01.meridian.example.com) ║
║  ├── Traffic: 5% of production load via load balancer weight         ║
║  ├── [ ] Deploy updated AuthLib 2.4.2 to canary server              ║
║  ├── [ ] Monitor: HTTP 5xx rate (threshold: < 0.1%)                 ║
║  ├── [ ] Monitor: Authentication success rate (threshold: > 99.5%)  ║
║  ├── [ ] Monitor: Response latency p99 (threshold: < 500ms)         ║
║  ├── [ ] Monitor: Error logs for JWT rejection false positives       ║
║  └── [ ] Hold window: 30 minutes of clean metrics before proceeding ║
║                                                                      ║
║  Phase C: Staged Rollout (60 min)                                   ║
║  ├── Stage 1: 25% of production servers (15 min hold)               ║
║  ├── Stage 2: 50% of production servers (15 min hold)               ║
║  ├── Stage 3: 75% of production servers (15 min hold)               ║
║  └── Stage 4: 100% of production servers (30 min monitoring)        ║
║                                                                      ║
║  Phase D: Post-Deployment Verification (30 min)                     ║
║  ├── [ ] Confirm AuthLib version 2.4.2 on ALL portal servers        ║
║  ├── [ ] Run exploit verification — confirm alg:none rejected       ║
║  ├── [ ] Run legitimate auth flow — confirm no regression           ║
║  ├── [ ] Remove virtual patch WAF rules (staged removal)            ║
║  ├── [ ] Remove virtual patch IPS signatures (after 48hr soak)      ║
║  └── [ ] Update vulnerability scanner — mark CVE as remediated      ║
║                                                                      ║
║  ROLLBACK CRITERIA (automatic rollback if ANY trigger hit)          ║
║  ├── HTTP 5xx rate > 1% for 5 consecutive minutes                   ║
║  ├── Authentication success rate < 98%                               ║
║  ├── Response latency p99 > 2000ms for 5 minutes                    ║
║  ├── Any critical error in application logs                          ║
║  └── Manual trigger by deployment lead                               ║
║                                                                      ║
║  ROLLBACK PROCEDURE                                                  ║
║  ├── 1. Revert AuthLib to 2.4.1 on affected servers                ║
║  ├── 2. Re-enable virtual patch WAF/IPS rules                       ║
║  ├── 3. Notify SOC team — virtual patching resumes                  ║
║  ├── 4. Investigate failure root cause                               ║
║  └── 5. Schedule retry with fix within 24 hours                     ║
║                                                                      ║
╚══════════════════════════════════════════════════════════════════════╝

5.3 Exercise: Deployment Automation Scripts

Task: Write the deployment automation scripts for each phase.

Canary deployment script:

#!/bin/bash
# ============================================================
# Emergency Patch Deployment — Canary Phase
# CVE-SYNTH-2026-0042 — AuthLib 2.4.2
# ALL DATA IS SYNTHETIC — EDUCATIONAL ONLY
# ============================================================

set -euo pipefail

# Configuration (SYNTHETIC)
CANARY_HOST="portal-canary01.meridian.example.com"   # SYNTHETIC
PACKAGE_URL="https://packages.meridian.example.com/authlib/2.4.2/authlib-2.4.2.tar.gz"  # SYNTHETIC
EXPECTED_SHA256="a1b2c3d4e5f6..."  # SYNTHETIC — replace with real hash
ROLLBACK_VERSION="2.4.1"
MONITORING_DURATION=1800  # 30 minutes in seconds
METRICS_ENDPOINT="https://metrics.meridian.example.com/api/v1/query"  # SYNTHETIC

echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] Starting canary deployment for AuthLib 2.4.2"

# Step 1: Download and verify package
echo "[STEP 1] Downloading package..."
curl -sL "$PACKAGE_URL" -o /tmp/authlib-2.4.2.tar.gz

ACTUAL_SHA256=$(sha256sum /tmp/authlib-2.4.2.tar.gz | awk '{print $1}')
if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then
    echo "[CRITICAL] Package hash mismatch! Expected: $EXPECTED_SHA256, Got: $ACTUAL_SHA256"
    echo "[CRITICAL] Aborting deployment — possible supply chain compromise"
    exit 1
fi
echo "[STEP 1] Package hash verified: $ACTUAL_SHA256"

# Step 2: Deploy to canary server
echo "[STEP 2] Deploying to canary: $CANARY_HOST"
ssh deployer@"$CANARY_HOST" << 'DEPLOY_EOF'
    # Backup current version
    cp -r /opt/portal/lib/authlib /opt/portal/lib/authlib.bak

    # Extract new version
    tar xzf /tmp/authlib-2.4.2.tar.gz -C /opt/portal/lib/

    # Verify installed version
    VERSION=$(/opt/portal/lib/authlib/version.sh)
    if [ "$VERSION" != "2.4.2" ]; then
        echo "[ERROR] Version mismatch after install: $VERSION"
        # Rollback
        rm -rf /opt/portal/lib/authlib
        mv /opt/portal/lib/authlib.bak /opt/portal/lib/authlib
        exit 1
    fi

    # Restart application (graceful — drain existing connections)
    systemctl reload portal-app
    echo "[DEPLOY] AuthLib 2.4.2 deployed to canary"
DEPLOY_EOF

# Step 3: Monitor canary metrics
echo "[STEP 3] Monitoring canary for $((MONITORING_DURATION / 60)) minutes..."

MONITOR_START=$(date +%s)
MONITOR_END=$((MONITOR_START + MONITORING_DURATION))

while [ "$(date +%s)" -lt "$MONITOR_END" ]; do
    ELAPSED=$(( ($(date +%s) - MONITOR_START) / 60 ))
    echo "[MONITOR] Elapsed: ${ELAPSED}m / $((MONITORING_DURATION / 60))m"

    # Check HTTP 5xx rate
    ERROR_RATE=$(curl -s "$METRICS_ENDPOINT" \
        --data-urlencode "query=rate(http_responses_total{host=\"$CANARY_HOST\",status=~\"5..\"}[5m])" \
        | jq -r '.data.result[0].value[1] // "0"')

    if (( $(echo "$ERROR_RATE > 0.001" | bc -l) )); then
        echo "[ROLLBACK] Error rate exceeded threshold: $ERROR_RATE > 0.1%"
        ssh deployer@"$CANARY_HOST" "rm -rf /opt/portal/lib/authlib && mv /opt/portal/lib/authlib.bak /opt/portal/lib/authlib && systemctl reload portal-app"
        echo "[ROLLBACK] Canary rolled back to AuthLib $ROLLBACK_VERSION"
        exit 1
    fi

    # Check auth success rate
    AUTH_RATE=$(curl -s "$METRICS_ENDPOINT" \
        --data-urlencode "query=rate(auth_success_total{host=\"$CANARY_HOST\"}[5m]) / rate(auth_attempts_total{host=\"$CANARY_HOST\"}[5m])" \
        | jq -r '.data.result[0].value[1] // "1"')

    if (( $(echo "$AUTH_RATE < 0.995" | bc -l) )); then
        echo "[ROLLBACK] Auth success rate below threshold: $AUTH_RATE < 99.5%"
        ssh deployer@"$CANARY_HOST" "rm -rf /opt/portal/lib/authlib && mv /opt/portal/lib/authlib.bak /opt/portal/lib/authlib && systemctl reload portal-app"
        echo "[ROLLBACK] Canary rolled back to AuthLib $ROLLBACK_VERSION"
        exit 1
    fi

    echo "[MONITOR] Error rate: ${ERROR_RATE} | Auth rate: ${AUTH_RATE} — within thresholds"
    sleep 60
done

echo "[SUCCESS] Canary monitoring complete — all metrics within thresholds"
echo "[NEXT] Proceed to staged rollout (Phase C)"

Staged rollout script:

#!/bin/bash
# ============================================================
# Emergency Patch Deployment — Staged Rollout
# CVE-SYNTH-2026-0042 — AuthLib 2.4.2
# ALL DATA IS SYNTHETIC — EDUCATIONAL ONLY
# ============================================================

set -euo pipefail

# Server groups (SYNTHETIC)
declare -a STAGE_1=(
    "portal-web01.meridian.example.com"
    "portal-web02.meridian.example.com"
)
declare -a STAGE_2=(
    "portal-web03.meridian.example.com"
    "portal-web04.meridian.example.com"
)
declare -a STAGE_3=(
    "portal-web05.meridian.example.com"
    "portal-web06.meridian.example.com"
)
declare -a STAGE_4=(
    "portal-web07.meridian.example.com"
    "portal-web08.meridian.example.com"
)

HOLD_DURATION=900  # 15 minutes per stage

deploy_stage() {
    local STAGE_NAME=$1
    shift
    local SERVERS=("$@")

    echo "========================================"
    echo "[STAGE] Deploying $STAGE_NAME: ${SERVERS[*]}"
    echo "========================================"

    for SERVER in "${SERVERS[@]}"; do
        echo "[DEPLOY] Updating $SERVER..."
        ssh deployer@"$SERVER" << 'EOF'
            cp -r /opt/portal/lib/authlib /opt/portal/lib/authlib.bak
            tar xzf /tmp/authlib-2.4.2.tar.gz -C /opt/portal/lib/
            systemctl reload portal-app
EOF
        echo "[DEPLOY] $SERVER updated"
    done

    echo "[HOLD] Monitoring for $((HOLD_DURATION / 60)) minutes..."
    sleep "$HOLD_DURATION"

    # Check aggregate metrics before proceeding
    echo "[CHECK] Verifying stage metrics..."
    # (monitoring logic similar to canary phase)
}

deploy_stage "Stage 1 (25%)" "${STAGE_1[@]}"
deploy_stage "Stage 2 (50%)" "${STAGE_2[@]}"
deploy_stage "Stage 3 (75%)" "${STAGE_3[@]}"
deploy_stage "Stage 4 (100%)" "${STAGE_4[@]}"

echo "========================================"
echo "[COMPLETE] All servers updated to AuthLib 2.4.2"
echo "[NEXT] Proceed to post-deployment verification (Phase D)"
echo "========================================"

5.4 Exercise: Rollback Verification Queries

Write queries to verify rollback state if deployment fails.

KQL — Verify Rollback Success:

// Verify AuthLib version across all portal servers after rollback
// ALL DATA IS SYNTHETIC
DeviceFileEvents
| where Timestamp > ago(1h)
| where DeviceName startswith "portal-"
    and DeviceName endswith ".meridian.example.com"
| where FolderPath has "authlib"
| where ActionType == "FileModified" or ActionType == "FileCreated"
| summarize LatestEvent = max(Timestamp),
            FileCount = count()
    by DeviceName, FolderPath
| extend LibraryVersion = extract(@"authlib[/\\](\d+\.\d+\.\d+)", 1, FolderPath)
| project DeviceName, LibraryVersion, LatestEvent, FileCount
| order by DeviceName asc

SPL — Verify Rollback Success:

index=endpoint sourcetype=file_monitor
    host="portal-*.meridian.example.com"
    file_path="*authlib*"
    action IN ("modified", "created")
    earliest=-1h
| stats latest(_time) as latest_event count as file_count by host file_path
| rex field=file_path "authlib[/\\\\](?<library_version>\d+\.\d+\.\d+)"
| table host library_version latest_event file_count
| sort host

5.5 Deliverables — Phase 5

Phase 5 Deliverables

  • [ ] Complete deployment plan document with all four phases (A-D)
  • [ ] Canary deployment script with metric monitoring and auto-rollback
  • [ ] Staged rollout script with hold windows and verification
  • [ ] Rollback procedure and verification queries (KQL and SPL)
  • [ ] Communication template: draft the stakeholder notification for each deployment phase (1 paragraph each)
  • [ ] Risk assessment: What could go wrong during emergency patching? List 5 risks and mitigations.

Phase 6: Patch Verification & Validation (30 minutes)

6.1 Post-Patch Verification Queries

After the patch is deployed, you must verify three things:

  1. Patch applied: Every portal server is running AuthLib 2.4.2
  2. No systems missed: Identify any servers still running the vulnerable version
  3. No exploitation during patch window: Detect any successful exploitation that occurred between vulnerability disclosure and patch completion

6.2 KQL Detection Queries

// ============================================================
// Query 1: Verify patch deployment — all servers on AuthLib 2.4.2
// Meridian Healthcare Systems — ALL DATA IS SYNTHETIC
// ============================================================

let ExpectedVersion = "2.4.2";
let PortalServers = dynamic([
    "portal-canary01.meridian.example.com",
    "portal-web01.meridian.example.com",
    "portal-web02.meridian.example.com",
    "portal-web03.meridian.example.com",
    "portal-web04.meridian.example.com",
    "portal-web05.meridian.example.com",
    "portal-web06.meridian.example.com",
    "portal-web07.meridian.example.com",
    "portal-web08.meridian.example.com"
]);
SoftwareInventory
| where Timestamp > ago(24h)
| where DeviceName in (PortalServers)
| where SoftwareName =~ "authlib"
| summarize LatestVersion = arg_max(Timestamp, SoftwareVersion)
    by DeviceName
| extend PatchStatus = iff(SoftwareVersion == ExpectedVersion, "PATCHED", "VULNERABLE")
| project DeviceName, SoftwareVersion, PatchStatus, Timestamp
| order by PatchStatus desc, DeviceName asc
// ============================================================
// Query 2: Find servers that missed the patch
// ALL DATA IS SYNTHETIC
// ============================================================

let ExpectedVersion = "2.4.2";
SoftwareInventory
| where Timestamp > ago(24h)
| where SoftwareName =~ "authlib"
| where DeviceName startswith "portal-"
    and DeviceName endswith ".meridian.example.com"
| summarize arg_max(Timestamp, SoftwareVersion) by DeviceName
| where SoftwareVersion != ExpectedVersion
| project DeviceName,
          CurrentVersion = SoftwareVersion,
          ExpectedVersion = ExpectedVersion,
          LastScanTime = Timestamp,
          DaysVulnerable = datetime_diff('day', now(), Timestamp)
| extend Urgency = case(
    DaysVulnerable > 7, "CRITICAL — Overdue",
    DaysVulnerable > 3, "HIGH — Approaching SLA",
    DaysVulnerable > 1, "MEDIUM — Within SLA",
    "LOW — Recently scanned"
)
| order by DaysVulnerable desc
// ============================================================
// Query 3: Detect exploitation attempts during patch window
// Looks for JWT alg:none attacks between disclosure and full patch
// ALL DATA IS SYNTHETIC
// ============================================================

let DisclosureTime = datetime(2026-04-10T08:00:00Z);  // SYNTHETIC
let PatchCompleteTime = datetime(2026-04-12T16:00:00Z);  // SYNTHETIC
//
// Look for indicators of compromise during the patch window
//
union
(
    // Indicator 1: WAF blocks of JWT alg:none (from virtual patches)
    CommonSecurityLog
    | where TimeGenerated between (DisclosureTime .. PatchCompleteTime)
    | where DeviceVendor == "ModSecurity" or DeviceVendor == "WAF"
    | where Message has "CVE-SYNTH-2026-0042"
    | where Activity == "BLOCK"
    | summarize BlockedAttempts = count(),
                UniqueSourceIPs = dcount(SourceIP),
                FirstAttempt = min(TimeGenerated),
                LastAttempt = max(TimeGenerated)
        by SourceIP
    | extend EventType = "WAF_BLOCK"
),
(
    // Indicator 2: Successful authentications with suspicious JWT patterns
    SigninLogs
    | where TimeGenerated between (DisclosureTime .. PatchCompleteTime)
    | where AppDisplayName =~ "Meridian Patient Portal"
    | where ResultType == 0  // Successful auth
    | where AuthenticationDetails has "none" or AuthenticationDetails has "alg"
    | summarize SuccessfulAuths = count(),
                UniqueUsers = dcount(UserPrincipalName)
        by SourceIP = IPAddress, UserPrincipalName
    | extend EventType = "SUSPICIOUS_AUTH"
),
(
    // Indicator 3: Unusual PHI access patterns during patch window
    AuditLogs
    | where TimeGenerated between (DisclosureTime .. PatchCompleteTime)
    | where OperationName has_any ("PatientRecordAccess", "PHIExport", "BulkQuery")
    | summarize RecordsAccessed = count(),
                UniquePatients = dcount(TargetResources)
        by InitiatedBy = tostring(InitiatedBy.user.userPrincipalName),
           SourceIP = tostring(InitiatedBy.user.ipAddress)
    | where RecordsAccessed > 50  // Threshold: normal max is ~20/session
    | extend EventType = "MASS_PHI_ACCESS"
),
(
    // Indicator 4: IPS alerts for CVE-SYNTH-2026-0042
    CommonSecurityLog
    | where TimeGenerated between (DisclosureTime .. PatchCompleteTime)
    | where DeviceVendor in ("Snort", "Suricata")
    | where Message has "CVE-SYNTH-2026-0042" or Message has "2026004"
    | summarize AlertCount = count(),
                UniqueSourceIPs = dcount(SourceIP)
        by SourceIP, Message
    | extend EventType = "IPS_ALERT"
)
| project EventType, SourceIP, details = pack_all()
| order by EventType asc
// ============================================================
// Query 4: Post-patch validation — confirm exploit is blocked
// Send test alg:none JWT and verify it is rejected
// ALL DATA IS SYNTHETIC
// ============================================================

// After patching, look for HTTP 401/403 responses to JWT alg:none test
WebLogs
| where Timestamp > ago(1h)
| where ServerHost startswith "portal-"
    and ServerHost endswith ".meridian.example.com"
| where UrlPath has "/api/v1/auth/"
| where RequestHeaders has "eyJhbGciOiJub25lIi"  // base64 of alg:none
| project Timestamp, ServerHost, SourceIP, HttpStatusCode, UrlPath
| summarize TestResults = count() by ServerHost, HttpStatusCode
| extend ValidationResult = case(
    HttpStatusCode == 401, "PASS — Exploit correctly rejected",
    HttpStatusCode == 403, "PASS — Exploit correctly blocked by WAF",
    HttpStatusCode == 200, "FAIL — Exploit still works! CRITICAL!",
    strcat("REVIEW — Unexpected status: ", tostring(HttpStatusCode))
)

6.3 SPL Detection Queries

`comment("============================================================")`
`comment("Query 1: Verify patch deployment — all servers on AuthLib 2.4.2")`
`comment("Meridian Healthcare Systems — ALL DATA IS SYNTHETIC")`
`comment("============================================================")`

index=endpoint sourcetype=software_inventory
    host="portal-*.meridian.example.com"
    software_name="authlib"
    earliest=-24h
| stats latest(_time) as last_scan latest(software_version) as current_version by host
| eval expected_version="2.4.2"
| eval patch_status=if(current_version==expected_version, "PATCHED", "VULNERABLE")
| table host current_version expected_version patch_status last_scan
| sort - patch_status host
`comment("============================================================")`
`comment("Query 2: Find servers that missed the patch")`
`comment("ALL DATA IS SYNTHETIC")`
`comment("============================================================")`

index=endpoint sourcetype=software_inventory
    host="portal-*.meridian.example.com"
    software_name="authlib"
    earliest=-24h
| stats latest(_time) as last_scan latest(software_version) as current_version by host
| where current_version!="2.4.2"
| eval days_vulnerable=round((now()-last_scan)/86400, 1)
| eval urgency=case(
    days_vulnerable>7, "CRITICAL - Overdue",
    days_vulnerable>3, "HIGH - Approaching SLA",
    days_vulnerable>1, "MEDIUM - Within SLA",
    1==1, "LOW - Recently scanned")
| table host current_version days_vulnerable urgency last_scan
| sort - days_vulnerable
`comment("============================================================")`
`comment("Query 3: Detect exploitation attempts during patch window")`
`comment("ALL DATA IS SYNTHETIC")`
`comment("============================================================")`

index=waf OR index=proxy OR index=ids
    sourcetype IN ("modsecurity", "snort", "suricata", "web_access")
    earliest="04/10/2026:08:00:00" latest="04/12/2026:16:00:00"
    ("CVE-SYNTH-2026-0042" OR "eyJhbGciOiJub25lIi" OR "alg.*none" OR sid=2026004*)
| eval event_type=case(
    sourcetype=="modsecurity", "WAF_BLOCK",
    sourcetype IN ("snort","suricata"), "IPS_ALERT",
    sourcetype=="web_access" AND status==200, "SUSPICIOUS_AUTH",
    1==1, "OTHER")
| stats count as attempts dc(src_ip) as unique_source_ips
    earliest(_time) as first_seen latest(_time) as last_seen
    values(src_ip) as source_ips
    by event_type
| sort - attempts
`comment("============================================================")`
`comment("Query 4: Detect mass PHI access during patch window")`
`comment("ALL DATA IS SYNTHETIC")`
`comment("============================================================")`

index=web sourcetype=access_combined
    host="portal-*.meridian.example.com"
    uri_path IN ("/api/v1/patients/*", "/api/v1/records/*")
    status=200
    earliest="04/10/2026:08:00:00" latest="04/12/2026:16:00:00"
| stats count as records_accessed dc(uri_path) as unique_endpoints
    earliest(_time) as first_access latest(_time) as last_access
    by src_ip useragent
| where records_accessed > 50
| eval risk=case(
    records_accessed>500, "CRITICAL - Possible mass exfiltration",
    records_accessed>200, "HIGH - Abnormal access volume",
    records_accessed>50, "MEDIUM - Elevated access",
    1==1, "LOW")
| table src_ip records_accessed unique_endpoints risk first_access last_access useragent
| sort - records_accessed
`comment("============================================================")`
`comment("Query 5: Post-patch validation — confirm exploit is blocked")`
`comment("ALL DATA IS SYNTHETIC")`
`comment("============================================================")`

index=web sourcetype=access_combined
    host="portal-*.meridian.example.com"
    uri_path="/api/v1/auth/*"
    earliest=-1h
| search "eyJhbGciOiJub25lIi"
| stats count by host status
| eval validation_result=case(
    status==401, "PASS - Exploit correctly rejected",
    status==403, "PASS - Exploit correctly blocked by WAF",
    status==200, "FAIL - Exploit still works! CRITICAL!",
    1==1, "REVIEW - Unexpected status: ".status)
| table host status validation_result count

6.4 Patch Compliance Dashboard Specification

Task: Design a dashboard that shows real-time patch compliance status. Define the following panels:

┌──────────────────────────────────────────────────────────────────────┐
│                PATCH COMPLIANCE DASHBOARD                             │
│                CVE-SYNTH-2026-0042 — AuthLib 2.4.2                   │
├─────────────────────────┬────────────────────────────────────────────┤
│                         │                                            │
│   PATCH STATUS          │   DEPLOYMENT TIMELINE                     │
│   ┌─────────────────┐   │   ┌────────────────────────────────────┐  │
│   │  Patched: 7/9   │   │   │ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░  78%           │  │
│   │  Pending: 2/9   │   │   │ Canary → 25% → 50% → 75% → 100%  │  │
│   │  Failed:  0/9   │   │   └────────────────────────────────────┘  │
│   └─────────────────┘   │                                            │
│                         │                                            │
├─────────────────────────┼────────────────────────────────────────────┤
│                         │                                            │
│   EXPLOITATION ATTEMPTS │   VIRTUAL PATCH EFFECTIVENESS              │
│   During Patch Window   │   ┌────────────────────────────────────┐  │
│   ┌─────────────────┐   │   │ WAF Blocks:  1,247                 │  │
│   │  Blocked: 1,302 │   │   │ IPS Alerts:     55                 │  │
│   │  Suspicious: 3  │   │   │ False Positives:  2                │  │
│   │  Confirmed: 0   │   │   │ Bypass Attempts:  0                │  │
│   └─────────────────┘   │   └────────────────────────────────────┘  │
│                         │                                            │
├─────────────────────────┴────────────────────────────────────────────┤
│                                                                      │
│   SERVER-LEVEL DETAIL                                                │
│   ┌──────────────────────────────────────────────────────────────┐  │
│   │ Server                          │ Version │ Status │ Patched │  │
│   │ portal-canary01.meridian.ex...  │ 2.4.2   │ ✓      │ 14:00  │  │
│   │ portal-web01.meridian.ex...     │ 2.4.2   │ ✓      │ 14:35  │  │
│   │ portal-web02.meridian.ex...     │ 2.4.2   │ ✓      │ 14:35  │  │
│   │ portal-web03.meridian.ex...     │ 2.4.2   │ ✓      │ 14:50  │  │
│   │ portal-web04.meridian.ex...     │ 2.4.2   │ ✓      │ 14:50  │  │
│   │ portal-web05.meridian.ex...     │ 2.4.2   │ ✓      │ 15:05  │  │
│   │ portal-web06.meridian.ex...     │ 2.4.2   │ ✓      │ 15:05  │  │
│   │ portal-web07.meridian.ex...     │ 2.4.1   │ ✗      │ —      │  │
│   │ portal-web08.meridian.ex...     │ 2.4.1   │ ✗      │ —      │  │
│   └──────────────────────────────────────────────────────────────┘  │
│                                                                      │
└──────────────────────────────────────────────────────────────────────┘

6.5 Deliverables — Phase 6

Phase 6 Deliverables

  • [ ] KQL queries for patch verification (4 queries — tested and producing expected output)
  • [ ] SPL queries for patch verification (5 queries — tested and producing expected output)
  • [ ] Dashboard specification with panel definitions, data sources, and refresh intervals
  • [ ] Written report: "Patch Window Exposure Analysis" — documenting any exploitation that occurred during the vulnerability window (use synthetic data)
  • [ ] Lessons learned document: What would you do differently to reduce the patch window next time?

Challenge Questions

Challenge Questions (Advanced)

Challenge 1: EPSS Threshold Decision

Your organization has a limited patch window of 4 hours per month. You have 200 vulnerabilities in the queue. Using EPSS data, you determine that only 15 vulnerabilities have EPSS > 0.5. Your CISO asks: "Should we patch only the EPSS > 0.5 vulnerabilities and defer the rest?" Write a 2-paragraph response that addresses the statistical and operational considerations. Include the concepts of false negative risk, regulatory exposure, and the base rate problem.

Challenge 2: Virtual Patch Lifecycle

A virtual patch (WAF rule) for CVE-SYNTH-2026-0042 has been in production for 90 days. The vendor patch was applied 60 days ago. The security team wants to remove the virtual patch rules to reduce WAF complexity. Design a decision framework for virtual patch retirement that accounts for: (a) patch verification confidence, (b) the possibility of patch regression during future updates, (c) defense-in-depth value, and (d) WAF performance impact.

Challenge 3: Supply Chain Vulnerability

During your analysis, you discover that AuthLib 2.4.2 (the "fix") was compiled with a version of GCC that has a known code generation bug (CVE-SYNTH-2026-9999). This bug could theoretically cause the JWT validation to be optimized away under specific compiler flags. How would you verify that the compiled library actually enforces the algorithm check? What additional supply chain controls would you recommend?

Challenge 4: CVSS v4.0 Disagreement

Your vulnerability scanner reports CVE-SYNTH-2026-0042 as CVSS 9.8 (v3.1). Your manual CVSS v4.0 analysis produces a score of 10.0 when accounting for Supplemental metrics (Automatable: Yes, Safety: Present in healthcare context). However, the NVD publishes it as v4.0 8.7 because they did not consider the Environmental metrics. Which score should your organization use for SLA purposes, and why? Design a policy that handles CVSS score disagreements.

Challenge 5: Zero-Day Dilemma

At hour 12 of the zero-day response, your threat intel team reports that the exploit for CVE-SYNTH-2026-0042 is being sold on dark web forums for $50,000. The virtual patch is in place but an attacker could theoretically bypass the WAF by fragmenting the JWT across multiple HTTP/2 frames. You have two options: (a) take the patient portal offline until the vendor patch is ready (estimated 36 hours), or (b) keep it running with virtual patches and enhanced monitoring. The portal handles 10,000 patient appointment bookings per day. Write a risk-based decision memo (1 page) recommending one option, with quantified risk analysis.


Scoring Rubric

Scoring Rubric — 250 Points Total

Phase 1: Vulnerability Discovery & Intake (40 points)

Criteria Points Description
Correct combined risk scores (all 50) 15 All calculations accurate within ±0.01
Correct tier classification 10 All 50 vulns assigned to correct tier
Sorted remediation queue 5 Correctly ordered by combined risk score
Written justifications (3+) 5 Thoughtful analysis of classification overrides
Top 5 identification 5 Correct identification with supporting rationale

Phase 2: CVSS v4.0 Scoring Exercise (45 points)

Criteria Points Description
Vuln A scoring (all metrics) 9 Correct metric selections with justification
Vuln B scoring (all metrics) 9 Correct metric selections with justification
Vuln C scoring (all metrics) 9 Correct metric selections with justification
Vuln D scoring (all metrics) 9 Correct metric selections with justification
Vuln E scoring (all metrics) 9 Correct metric selections with justification

Phase 3: EPSS-Based Prioritization (30 points)

Criteria Points Description
Dual-ranked list (complete) 10 Both CVSS-only and combined rankings for all 50
Top 5 outlier analysis 10 Correctly identified outliers with insightful analysis
Executive summary 5 Clear, persuasive, technically accurate
Decision matrix 5 At least 3 valid override conditions documented

Phase 4: Virtual Patching (60 points)

Criteria Points Description
ModSecurity rules (7 rules) 20 Syntactically correct, operationally effective
Snort/Suricata signatures (8 sigs) 15 Syntactically correct, proper flow/content
EDR detection rules (6 rules) 10 Logical, covers post-exploitation indicators
Gap analysis 5 Identifies at least 2 uncovered attack paths
Testing plan 5 Realistic, non-disruptive testing methodology
Bypass analysis 5 At least 3 bypass vectors with detection strategies

Phase 5: Emergency Patch Deployment (40 points)

Criteria Points Description
Deployment plan (all phases A-D) 15 Complete, realistic, operationally sound
Automation scripts 10 Functional scripts with error handling
Rollback procedure + queries 5 Complete rollback with verification
Communication templates 5 Professional, complete, appropriate audience
Risk assessment (5 risks) 5 Realistic risks with practical mitigations

Phase 6: Patch Verification & Validation (35 points)

Criteria Points Description
KQL queries (4 queries) 10 Syntactically correct, operationally useful
SPL queries (5 queries) 10 Syntactically correct, operationally useful
Dashboard specification 5 Complete panel definitions with data sources
Patch window exposure analysis 5 Thorough analysis using synthetic data
Lessons learned 5 Actionable, specific, demonstrates learning

Scoring Thresholds

Score Grade Assessment
225–250 Expert Ready for senior vulnerability management roles
200–224 Proficient Solid understanding — ready for independent work
175–199 Competent Good foundation — needs mentored practice
150–174 Developing Understands concepts — needs more hands-on experience
< 150 Foundational Review prerequisite materials and retry

Answer Key

Phase 1 Answer Key — Top 10 Combined Risk Scores (click to expand)

Combined Risk Score Calculation Examples:

# CVE CVSS EPSS CVSS Norm Asset Modifier Combined Risk Tier
1 CVE-SYNTH-2026-0042 9.8 0.971 0.98 +0.35 (0.98×0.4)+(0.971×0.4)+0.35 = 1.130 Critical
2 CVE-SYNTH-2026-0108 9.1 0.892 0.91 +0.20 (0.91×0.4)+(0.892×0.4)+0.20 = 0.921 Critical
5 CVE-SYNTH-2026-0044 8.6 0.912 0.86 +0.15 (0.86×0.4)+(0.912×0.4)+0.15 = 0.859 Critical
4 CVE-SYNTH-2026-0301 8.8 0.756 0.88 +0.35 (0.88×0.4)+(0.756×0.4)+0.35 = 1.004 Critical
8 CVE-SYNTH-2026-0087 8.1 0.823 0.81 +0.35 (0.81×0.4)+(0.823×0.4)+0.35 = 1.003 Critical
11 CVE-SYNTH-2026-0845 7.5 0.891 0.75 +0.35 (0.75×0.4)+(0.891×0.4)+0.35 = 1.006 Critical
16 CVE-SYNTH-2026-0553 7.0 0.834 0.70 +0.35 (0.70×0.4)+(0.834×0.4)+0.35 = 0.964 Critical
13 CVE-SYNTH-2026-0390 7.4 0.678 0.74 +0.20 (0.74×0.4)+(0.678×0.4)+0.20 = 0.767 High
14 CVE-SYNTH-2026-0912 7.2 0.445 0.72 +0.35 (0.72×0.4)+(0.445×0.4)+0.35 = 0.816 Critical
7 CVE-SYNTH-2026-0623 8.2 0.445 0.82 +0.20 (0.82×0.4)+(0.445×0.4)+0.20 = 0.706 High

Key Insight: CVE-SYNTH-2026-0845 (CVSS 7.5) ranks higher than CVE-SYNTH-2026-0215 (CVSS 9.0) because its EPSS of 0.891 indicates active exploitation, while the PostgreSQL vulnerability (EPSS 0.034) is rarely exploited in practice despite its high severity score.

Key Insight: CVE-SYNTH-2026-0519 (CVSS 8.4) drops dramatically in combined ranking because its EPSS of 0.003 indicates virtually zero real-world exploitation — the timing side-channel attack requires local access and is extremely difficult to execute reliably.

Phase 2 Answer Key — CVSS v4.0 Scoring (click to expand)

Vulnerability A: CVE-SYNTH-2026-0042

Attack Vector (AV): Network — exploitable remotely over the internet
Attack Complexity (AC): Low — no special conditions or race windows
Attack Requirements (AT): None — no prerequisite configuration required
Privileges Required (PR): None — unauthenticated attack
User Interaction (UI): None — no user action required

Vulnerable System Impact:
  Confidentiality (VC): High — full access to portal data
  Integrity (VI): High — can modify any portal data
  Availability (VA): High — can disrupt portal operations

Subsequent System Impact:
  Confidentiality (SC): High — access to backend PHI via portal API
  Integrity (SI): High — can modify patient records via API
  Availability (SA): Low — backend systems have independent availability

Threat Metrics:
  Exploit Maturity (E): Attacked — confirmed active exploitation

Environmental Metrics:
  Confidentiality Req (CR): High — PHI data requires maximum confidentiality
  Integrity Req (IR): High — patient record integrity is critical
  Availability Req (AR): High — patient portal availability affects care delivery

Supplemental Metrics:
  Safety (S): Present — healthcare context, patient safety implications
  Automatable (AU): Yes — trivially scriptable, no human interaction needed
  Recovery (R): User — requires manual incident response and token revocation
  Value Density (V): Concentrated — high-value PHI data in one place

Vector: CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:L/E:A/CR:H/IR:H/AR:H/S:P/AU:Y/R:U/V:C
Base Score: 10.0
Base + Threat Score: 10.0
Overall Score: 10.0

Vulnerability B: CVE-SYNTH-2026-0623

AV: Network | AC: Low | AT: Present (requires gadget libs on classpath)
PR: Low (valid API key required) | UI: None

VC: High | VI: High | VA: High
SC: High (direct DB access) | SI: High | SA: Low

E: PoC (public PoC exists but no confirmed active exploitation)
CR: High | IR: High | AR: Medium

Vector: CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:L/E:P/CR:H/IR:H/AR:M
Base Score: 8.7
Base + Threat Score: 8.4
Overall Score: 8.6

Vulnerability C: CVE-SYNTH-2026-0156

AV: Local | AC: High (precise timing required) | AT: Present (update must be triggered)
PR: Low (local user access) | UI: None

VC: High | VI: High | VA: High (SYSTEM access)
SC: None (local endpoint only) | SI: None | SA: None

E: Unreported (no public exploit)
CR: Medium | IR: Medium | AR: Medium

Vector: CVSS:4.0/AV:L/AC:H/AT:P/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:U/CR:M/IR:M/AR:M
Base Score: 5.9
Base + Threat Score: 5.2
Overall Score: 5.2

Note: CVSS v3.1 scored this 7.8 — v4.0 is significantly lower due to AT:Present
and AC:High, which v3.1 did not fully account for.

Vulnerability D: CVE-SYNTH-2026-0445

AV: Network | AC: Low | AT: None
PR: None | UI: Active (user must click malicious link)

VC: Low (client-side XSS — limited direct impact) | VI: Low | VA: None
SC: High (session hijacking → PHI access) | SI: Low | SA: None

E: Attacked (observed in phishing campaigns)
CR: High (PHI) | IR: Medium | AR: Low

Vector: CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:L/VI:L/VA:N/SC:H/SI:L/SA:N/E:A/CR:H/IR:M/AR:L
Base Score: 6.9
Base + Threat Score: 6.9
Overall Score: 7.1

Note: CVSS v3.1 scored this 6.1. v4.0 is higher because the Subsequent System
impact (SC:High) captures the session hijacking → PHI access chain that v3.1
did not model well.

Vulnerability E: CVE-SYNTH-2026-0356

AV: Local | AC: Low | AT: None
PR: Low | UI: None

VC: None | VI: Low (log tampering) | VA: None
SC: None | SI: High (SIEM pipeline loses visibility) | SA: None

E: Unreported (no public exploit, but technique is simple)
CR: Low | IR: High (log integrity is critical for detection) | AR: Low

Vector: CVSS:4.0/AV:L/AC:L/AT:N/PR:L/UI:N/VC:N/VI:L/VA:N/SC:N/SI:H/SA:N/E:U/CR:L/IR:H/AR:L
Base Score: 5.3
Base + Threat Score: 4.8
Overall Score: 5.1

Note: The high Environmental score for IR captures the critical importance
of log integrity in a healthcare monitoring environment.
Phase 3 Answer Key — EPSS Outlier Analysis (click to expand)

Top 5 Rank-Change Outliers (UP movers — underestimated by CVSS alone):

CVE CVSS Rank Combined Rank Change Analysis
CVE-SYNTH-2026-0845 (Node.js) ~11 ~6 +5 UP EPSS 0.891 — mass scanning; CVSS 7.5 underestimates real risk
CVE-SYNTH-2026-0553 (Nginx) ~16 ~7 +9 UP EPSS 0.834 — active DDoS campaigns; CVSS 7.0 underestimates
CVE-SYNTH-2026-0856 (Commons Text) ~20 ~12 +8 UP EPSS 0.823 on a CVSS 6.5 — campaign targeting Java apps
CVE-SYNTH-2026-0356 (Sysmon) ~29 ~18 +11 UP EPSS 0.678 on a CVSS 5.5 — used by APT groups for evasion
CVE-SYNTH-2026-0445 (React XSS) ~24 ~15 +9 UP EPSS 0.712 on CVSS 6.1 — active phishing campaigns

Top 5 Rank-Change Outliers (DOWN movers — overestimated by CVSS alone):

CVE CVSS Rank Combined Rank Change Analysis
CVE-SYNTH-2026-0215 (PostgreSQL) ~3 ~17 -14 DOWN CVSS 9.0 but EPSS only 0.034 — requires auth, rarely exploited
CVE-SYNTH-2026-0519 (PostgreSQL) ~6 ~30 -24 DOWN CVSS 8.4 but EPSS 0.003 — timing side-channel, local only
CVE-SYNTH-2026-0734 (WSUS) ~9 ~28 -19 DOWN CVSS 8.0 but EPSS 0.067 — MITM requirement, rare attack
CVE-SYNTH-2026-0661 (OpenSSH) ~16 ~33 -17 DOWN CVSS 7.0 but EPSS 0.002 — requires agent forwarding, rare
CVE-SYNTH-2026-0267 (pgAdmin) ~11 ~31 -20 DOWN CVSS 7.5 but EPSS 0.012 — CSRF in admin, requires auth session

Executive Summary (model answer):

CVSS-only prioritization would have Meridian Healthcare patching CVE-SYNTH-2026-0215 (PostgreSQL privilege escalation, CVSS 9.0) before CVE-SYNTH-2026-0845 (Node.js prototype pollution, CVSS 7.5). However, the Node.js vulnerability has an EPSS of 0.891 — meaning there is an 89.1% probability it will be exploited within 30 days — compared to only 3.4% for the PostgreSQL issue. In operational terms, patching by CVSS alone would leave a highly-targeted, easily-exploitable internet-facing vulnerability open while resources are spent on a rarely-exploited internal database issue.

The combined EPSS+CVSS approach, weighted with asset criticality modifiers, produces a prioritization that aligns remediation effort with actual risk. This does not mean ignoring high-CVSS, low-EPSS vulnerabilities — they remain in the remediation queue — but it ensures that limited patching windows are used to maximum risk-reduction effect. For a healthcare organization bound by HIPAA, this data-driven approach is both defensible to auditors and operationally superior.

Phase 4 Answer Key — Virtual Patching Gaps (click to expand)

Gap Analysis — Uncovered Attack Paths:

  1. HTTP/2 frame fragmentation: The ModSecurity rules inspect the assembled HTTP request, but an attacker could fragment the JWT across multiple HTTP/2 frames. If the WAF does not reassemble frames before inspection, the alg:none pattern may not match. Mitigation: Ensure WAF performs full HTTP/2 frame reassembly; add a rule that inspects reassembled content.

  2. JWT in non-standard locations: The rules cover Authorization header and request body, but the application might accept JWTs in query parameters (?token=...), cookies, or custom headers (X-Auth-Token). Mitigation: Add rules covering all JWT input vectors used by the application.

  3. Base64 padding variants: Standard base64 and base64url encoding produce different outputs for the same input. The rules match specific base64url patterns, but an attacker might use standard base64 with padding characters (=). Mitigation: Add rule variants covering both base64 and base64url encodings.

  4. Chunked Transfer-Encoding evasion: If the request body is sent with chunked encoding, the WAF may inspect each chunk individually rather than the reassembled body, missing the pattern. Mitigation: Configure WAF to reassemble chunked requests before rule evaluation.

  5. Algorithm confusion (RS256 → HS256): Beyond alg:none, an attacker might change alg from RS256 to HS256 and use the public key as the HMAC secret. This is a different attack (CVE-2015-2951 pattern) not covered by the alg:none rules. Mitigation: Add rules that block any JWT where the algorithm does not match the expected RS256/ES256 allowlist.


ATT&CK Techniques Mapped

Technique ID Technique Name Lab Phase Context
T1190 Exploit Public-Facing Application Phase 4 JWT alg:none exploitation of patient portal
T1078.004 Valid Accounts: Cloud Accounts Phase 4 Forged JWT grants admin access
T1550.001 Use Alternate Authentication Material: Application Access Token Phase 4, 6 Crafted JWT used for authentication bypass
T1059.001 Command and Scripting Interpreter: PowerShell Phase 4 Post-exploitation command execution
T1059.003 Command and Scripting Interpreter: Windows Command Shell Phase 4 Post-exploitation command execution
T1005 Data from Local System Phase 4, 6 PHI data exfiltration after auth bypass
T1530 Data from Cloud Storage Phase 6 Mass access to patient records
T1562.001 Impair Defenses: Disable or Modify Tools Phase 2, 3 Sysmon log evasion (CVE-SYNTH-2026-0356)
T1070.003 Indicator Removal: Clear Command History Phase 4 Post-exploitation evidence cleanup
T1210 Exploitation of Remote Services Phase 2 Deserialization RCE (CVE-SYNTH-2026-0623)
T1068 Exploitation for Privilege Escalation Phase 2 Local priv-esc (CVE-SYNTH-2026-0156)
T1195.002 Supply Chain Compromise: Compromise Software Supply Chain Challenge 3 Compiler-level supply chain concern
T1189 Drive-by Compromise Phase 2 Reflected XSS exploitation (CVE-SYNTH-2026-0445)
T1499.003 Endpoint DoS: Application Exhaustion Flood Phase 1 HTTP/2 rapid reset DoS (CVE-SYNTH-2026-0553)
T1110.001 Brute Force: Password Guessing Phase 4 Rate limiting on auth endpoints

Cross-References

Chapter Relevance
Chapter 29: Vulnerability Management Core vulnerability management lifecycle — scanning, assessment, remediation
Chapter 53: Zero-Day Response Zero-day incident response procedures — virtual patching, emergency remediation
Chapter 24: Supply Chain Security Third-party library vulnerabilities — dependency management, SBOM
Chapter 5: Detection Engineering at Scale KQL/SPL detection query development methodology
Chapter 6: SIEM Architecture & Optimization SIEM query optimization for vulnerability monitoring
Chapter 10: Incident Response Engineering Emergency response procedures for critical vulnerabilities
Lab Relevance
Lab 18: Threat Hunting with KQL & SPL KQL/SPL query development fundamentals
Lab 28: API Security Testing API vulnerability assessment — JWT testing
Lab 29: Zero Trust Architecture Authentication and access control validation
Lab 3: IR Simulation Incident response procedures
Scenario Relevance
SC-009 through SC-096 Attack scenarios involving vulnerability exploitation
Tool Relevance
Detection Query Browser Pre-built KQL/SPL detection queries for common vulnerabilities
ATT&CK Gap Analysis Map coverage gaps for vulnerability exploitation techniques

Lab Revision History

Version Date Changes
1.0 2026-04-12 Initial release — 6 phases, 50 synthetic vulnerabilities, CVSS v4.0 scoring, virtual patching, deployment automation