Everything Loaded
50 AD users with real misconfigs. 40 customers with PAN + CVV + SSN in a vulnerable fintech app. Wazuh custom rules. OpenRMF STIG checklists. 6 guided exercises. 15-entry POA&M. All ready to run.
What's in Each VM After Scripts Run
Lab Network
Deployment Order
① Windows Server 2022 (CSFC-DC01) — Script 1
Creates 50 users, 10 security groups, 8 OUs, file shares with unencrypted PAN + PII + credentials. Applies intentionally weak password GPO. ~5 mins.
② Ubuntu Webapp VM (CSFC-WEBAPP) — Script 2
Installs PostgreSQL with 40 customers, 10 card records, 15 transactions (including AML flags). Deploys vulnerable Flask fintech app. Sets up weak SSH + anonymous FTP. ~15 mins.
③ Wazuh Server (CSFC-WAZUH) — Script 3 (after Wazuh installed)
Adds 8 custom CSFC detection rules. Configures FIM for sensitive file paths. Creates pre-populated PCI-DSS gap analysis and 15-entry POA&M. ~5 mins.
④ OpenRMF Server (CSFC-OPENRMF) — Script 4
Deploys OpenRMF via Docker Compose. Creates CSFC system package with pre-loaded Windows Server STIG, pre-filled with 22 findings, and POA&M linked to AD misconfigs. ~10 mins.
⑤ Kali Linux (CSFC-KALI) — Copy Script 4
Copy 04_CSFC_GRC_Exercises.sh to Kali. Run it to get the interactive exercise menu. All 6 exercises run from here.
Meet CyberShield Financial Corp
Your fictional employer. A mid-size fintech processing card payments for 40+ countries with a fresh incident, three upcoming audits, and you as the new junior GRC analyst.
.env.production (containing DB credentials, AWS keys, and payment API secrets) to a public GitHub repository. The file was live for 6 hours. Wazuh detected suspicious database queries from IP 41.66.224.10 (Lagos, NG) during that window. Three rapid transactions were inserted at 02:14–02:16 AM. CISO Jane Lee has tasked you with a full compliance review before the Q4 board audit in 8 weeks. You have access to all systems. Start now.Company Profile
Known Problems (Your Finding List)
50 Pre-Built Employees (Highlights)
| Username | Name | Role | Flag |
|---|---|---|---|
| j.whitfield | James Whitfield | CEO | Weak pw |
| j.lee | Jane Lee | CISO | Strong pw |
| local.admin | Local Admin | Shared Acct | Dom Admin! |
| svc.appserver | SVC AppServer | Service Acct | Dom Admin! |
| dev.c2 | Dev Contractor | Contractor | CDE Access! |
| o.employee | Old Employee | Terminated | Still active! |
| test.user | Test User | Test Acct | IT Admin! |
| + 43 more employees · all using Password1 | |||
Red rows = GRC findings you must document & fix
Sample Data Guide
Every database record, file, credential, and transaction pre-loaded in the lab. Reference this to know exactly what exists and where to find each violation.
customers table (40 rows)
| Column | Example Value | Violation | Framework |
|---|---|---|---|
| ssn | 847-23-9134 | PLAIN TEXT PII | GDPR Art 5(1)(f), Art 9 |
| dob | 1985-03-14 | PII unencrypted | GDPR Art 5, Art 25 |
| risk_rating | HIGH (RU, IR, AE) | AML exercise data | BSA / FinCEN |
| account_balance | $892,340.00 | High-value targets | GDPR Art 25 |
payment_cards table (10 rows)
| Column | Example Value | Violation | Framework |
|---|---|---|---|
| card_number | 4532789123456789 | FULL PAN UNMASKED | PCI-DSS Req 3.4.1 CRITICAL |
| cvv | 847 | CVV STORED — PROHIBITED | PCI-DSS Req 3.3.1 CRITICAL |
| expiry_month/year | 09 / 2026 | SAD retention risk | PCI-DSS Req 3.3 |
psql -h 192.168.56.40 -U csfc_readonly -d csfc_production -c "SELECT first_name,ssn,account_balance FROM customers LIMIT 5;" — The read-only user can still read SSNs because permissions are overly broad (another finding!).SMB File Shares on CSFC-DC01 (192.168.56.10)
Q3_transactions_UNENCRYPTED.csv — 1,000 rows of transactions including full PANs (card numbers) and cardholder names in plain text CSV. Accessible to GRP_Finance + GRP_IT_Admins.
Findings: PCI-DSS 3.4.1 GDPR Art 5
Salary_Register_2024.csv — 50 employee records with full name, SSN, date of birth, bank account numbers, and salary. Unencrypted.
Findings: GDPR Art 9 Special Category No encryption
.env.production — The incident file. Contains DB password, AWS access keys, payment gateway API key, JWT secret. This is what was leaked to GitHub.
Findings: CRITICAL — Incident root cause
Network_Topology.txt — Internal IP ranges, server names, and notes about unpatched CVEs. Share mapped to Everyone — any domain user (including contractors) can read.
Findings: CIS Control 3 PCI-DSS 7.2
| System | Username | Password | Finding ID |
|---|---|---|---|
| Web App (Flask) | admin | admin123 | FIND-WEB-005 |
| Web App (Flask) | j.lee | Password1 | FIND-AD-002 |
| PostgreSQL DB | csfc_admin | admin123 | FIND-DB-001 |
| PostgreSQL DB | csfc_readonly | readonly | FIND-DB-002 |
| AD (45 users) | [any user] | Password1 | FIND-AD-002 |
| FTP Anonymous | anonymous | (any email) | FIND-NET-003 |
| Wazuh Dashboard | admin | [set at install] | Change at first login |
| OpenRMF | admin | openrmf1234! | Change after setup |
| Kali Linux | kali | kali | Change immediately |
Pre-Loaded Suspicious Transactions (AML Exercise)
These 6 suspicious transaction patterns are in the database and visible at http://192.168.56.40:5000/transactions/suspicious. Your exercise: determine if each requires a SAR (Suspicious Activity Report) filing under BSA/FinCEN rules.
| Customer | Amount | Country | AML Flag | Why It's Suspicious |
|---|---|---|---|---|
| Amir Al-Rashid | 3× ~$9,700 | 🇦🇪 AE | STRUCTURING | Three wires of $9,800/$9,750/$9,600 within 10 minutes — classic structuring to stay below $10k CTR threshold |
| Nina Petrova | $50,000 | 🇷🇺 RU | LARGE CASH | $50,000 ATM withdrawal from Russia. High-risk country, large cash = SAR required |
| Olga Ivanova | $45,000 | 🇷🇺 RU | SANCTIONS RISK | International wire to Russia — check OFAC SDN list. Account under review (pending status) |
| Dmitri Volkov | $75,000 | 🇷🇺 RU | SANCTIONS RISK | $780k balance + outbound wire to Russia. PEP/sanctions check required. Almost certainly SAR territory |
| Emma Wilson | 3× $2,500 | 🇳🇬🇬🇭🇨🇮 | UNUSUAL PATTERN | 3 transactions in 2 minutes at 02:14 AM across 3 West African countries — fraud/account takeover pattern |
| Leila Hosseini | $45,200 | 🇮🇷 IR | SANCTIONS RISK | Iranian customer — OFAC primary sanctions apply. Transaction should have been blocked pre-processing |
OpenRMF Pre-Loaded STIG Findings
After running Script 4, OpenRMF at http://192.168.56.50:8080 contains a CSFC system package with the Windows Server 2022 STIG loaded and pre-filled with findings that match the AD misconfigs you created in Script 1.
| STIG ID | Finding | Severity | Status | Linked AD Finding |
|---|---|---|---|---|
| V-254239 | Account lockout must be configured | CAT I | OPEN | FIND-AD-003 |
| V-254247 | Min password length must be 14 chars | CAT II | OPEN | FIND-AD-002 |
| V-254248 | Password complexity must be enforced | CAT II | OPEN | FIND-AD-002 |
| V-254249 | Max password age must not exceed 60 days | CAT II | OPEN | FIND-AD-002 |
| V-254335 | Shared service accounts must not be used | CAT II | OPEN | FIND-AD-001 |
| V-254478 | Inactive accounts must be disabled after 35 days | CAT II | OPEN | FIND-AD-005 |
| V-254333 | Security event log must be 1024MB minimum | CAT III | OPEN | FIND-AD-008 |
| V-254200 | Windows updates must be current | CAT I | OPEN | FIND-NET-005 |
Active Directory Population Script
Run this PowerShell script on your Windows Server 2022 Domain Controller after AD DS promotion. Creates 50 users, 10 groups, 8 OUs, file shares with real-looking sensitive data, and intentionally weak policy settings.
01_CSFC_AD_Setup.ps1 · Run on: CSFC-DC01 (192.168.56.10) · As: CSFC\Administrator · Estimated time: 5 minutes- ✓Promote Windows Server to DC (domain: csfc.local) — see previous Setup Guide
- ✓Copy
01_CSFC_AD_Setup.ps1to the server (shared folder, USB, or RDP file transfer) - ✓Open PowerShell as Administrator on DC
- ✓Run:
Set-ExecutionPolicy Bypass -Scope Process -Force - ✓Run:
.\01_CSFC_AD_Setup.ps1— watch for green [+] lines - ✓Verify: open ADUC (dsa.msc) → confirm 50 users across 8 OUs
- ✓Verify: check
C:\CSFC_Data\Finance\Q3_transactions_UNENCRYPTED.csvexists - ✓Take a VM snapshot now! Label: "After-AD-Population"
| OU | Username | Name | Title | Password | Finding |
|---|---|---|---|---|---|
| EXECUTIVE — 5 users | |||||
| Executive | j.whitfield | James Whitfield | CEO | Password1 | Weak |
| Executive | p.sharma | Priya Sharma | CFO | Password1 | Weak |
| IT-Security | j.lee | Jane Lee | CISO | C$FC@dm1n2024! | Strong |
| Executive | m.reed | Marcus Reed | CTO | Password1 | Weak |
| INTENTIONAL FINDINGS — 7 users | |||||
| IT-Security | local.admin | Local Admin | Shared Admin | Password1 | Domain Admin |
| ServiceAccounts | svc.appserver | SVC AppServer | Service Acct | Password1 | Domain Admin |
| ServiceAccounts | svc.backup | SVC Backup | Backup Svc | Password1 | IT Admin |
| Contractors | vendor.admin | Vendor Admin | IT Contractor | Password1 | In IT Admins |
| Contractors | dev.c2 | Dev Contractor2 | Contract Dev | Password1 | CDE Access |
| Finance | o.employee | Old Employee | Terminated | Password1 | Still Enabled |
| IT-Security | test.user | Test User | Test Account | Password1 | IT Admin |
| + 38 regular staff (Finance, Engineering, HR, Operations) — all Password1 | |||||
local.admin is a shared account in Domain Admins. Multiple staff use it — no individual accountability. Non-repudiation failure means you can't prove who did what in a forensic investigation.
45 of 50 accounts use "Password1" — satisfies 0 current complexity requirements (they're all disabled) and appears in every common wordlist. An automated spray attack would own the domain in minutes.
LockoutThreshold = 0 (disabled). Unlimited authentication attempts allowed. Combined with FIND-AD-002, the entire domain is trivially brute-forceable from a single workstation.
dev.c2 (external contractor) is in GRP_CardholderData. PCI-DSS requires CDE access be restricted to those with a documented business need. External contractors should have just-in-time access only.
Vulnerable App + Database
Deploys a realistic fintech web portal backed by a PostgreSQL database. 40 customers with payment cards, AML-flagged transactions, and 6 intentional web vulnerabilities mapped to PCI-DSS findings.
02_CSFC_VulnApp_Setup.sh · Run on: Ubuntu 22.04 (192.168.56.40) · As: sudo · Estimated time: 15 minutesRun Commands
Web App URLs
Login: admin/admin123 or j.lee/Password1
Dashboard shows stats, customer list, suspicious transactions
No auth required. Returns 40 customers with SSN, DOB, balance. Try from Kali with curl.
Returns card number, expiry, and CVV — no auth. PCI-DSS prohibits storing CVV and this is exposed publicly.
Try ' OR '1'='1 to dump all records. Classic unsanitized query injection. PCI-DSS 6.4.
Shows all 6 pre-flagged suspicious transactions with AML flag labels. Requires login.
Run: ftp 192.168.56.40 → login as anonymous → list /pub/csfc_reports/
Wazuh Custom Rules
Installs 8 CSFC-specific detection rules, configures File Integrity Monitoring on sensitive paths, injects pre-built security events, and creates gap analysis + POA&M documents.
03_CSFC_Wazuh_Config.sh · Run on: Wazuh server (192.168.56.20) · After: Wazuh fully installed and Windows agent connectedCustom Detection Rules (8 rules)
Fires when authentication events contain usernames local.admin, vendor.admin, or test.user. Maps to PCI-DSS 8.2.1 (unique IDs required). Shows in Wazuh's PCI-DSS compliance dashboard automatically. Try it: log into the webapp as j.lee, then check Wazuh Security Events.
Fires on Windows Event ID 1102 (security log cleared) or 4719 (audit policy changed). Maps to PCI-DSS Req 10.7. Test it by clearing the Windows Security event log on CSFC-DC01 — Wazuh will immediately fire a high-priority alert.
File Integrity Monitoring watches C:\CSFC_Data\Finance\, C:\CSFC_Data\HR\, and C:\CSFC_Data\Engineering\ in real-time. Any create/modify/delete fires this rule. Maps to PCI-DSS 11.5 (FIM required) and GDPR Art 5. Test: open and save Q3_transactions_UNENCRYPTED.csv.
Detects OR 1=1, UNION SELECT, DROP TABLE, and script> in web server logs. Run the SQLi exercise (Exercise 6) and watch this rule fire. Screenshot the Wazuh alert for your evidence folder — it proves detection capability to auditors.
Fires when database authentication occurs between 10pm–6am. Maps to GDPR Art 32 (appropriate technical measures) and PCI-DSS 10.2.3 (log access to CDE). The pre-injected events at 02:14 AM will show in the dashboard — this is how the GitHub incident was detected.
Pre-Built GRC Documents (on Wazuh server)
Pre-filled with 22 findings across 7 requirements. Shows CSFC at 23% compliance. Your task: complete the remaining requirements and add evidence screenshots from Wazuh./opt/csfc-grc/gap-analysis/PCI-DSS-Gap-Analysis-CSFC.md
15 items with owners, deadlines, severity, and resource estimates. Status all set to OPEN. Work through them in the lab and mark complete as you fix each finding./opt/csfc-grc/poam/CSFC-POAM-2024.md
OpenRMF STIG Setup
Deploys OpenRMF via Docker Compose on its own Ubuntu VM. Creates a CSFC system package with the Windows Server 2022 STIG pre-loaded, 8 findings marked open, and a linked POA&M.
04_CSFC_OpenRMF_Setup.sh · Run on: Ubuntu 22.04 (192.168.56.50) · Requires: Docker + Docker Compose pre-installed- ✓Spin up Ubuntu 22.04 VM with 4GB RAM, 30GB disk — IP: 192.168.56.50
- ✓Install Docker:
curl -fsSL https://get.docker.com | sudo bash - ✓Run Script 4:
sudo bash 04_CSFC_OpenRMF_Setup.sh - ✓Access OpenRMF at
http://192.168.56.50:8080— login: admin / openrmf1234! - ✓Navigate to: Systems → CSFC Production → Windows Server 2022 STIG → view pre-loaded findings
- ✓Check POA&M tab — 8 items should be pre-loaded matching the AD findings
- ✓Take snapshot: "After-OpenRMF-Setup"
OpenRMF Lab Tasks
Create CSFC System Package
Systems → New System → Name: "CSFC Production Environment" → Owner: Jane Lee → Classify: Moderate Impact → Save
Upload Windows Server 2022 STIG
Download from: https://public.cyber.mil/stigs/downloads/ → Search "Windows Server 2022" → Download STIG zip → Upload to your CSFC system package in OpenRMF
Review Pre-Filled Findings
The script pre-marks 8 STIG checks as "Open" matching the AD misconfigs: password policy (V-254247/248/249), account lockout (V-254239), shared accounts (V-254335), inactive accounts (V-254478). Review each.
Generate POA&M
Reports → POA&M → Select your system → Export. This creates a formatted POA&M showing all open findings with STIG IDs, severity, and remediation guidance — exactly what DoD/regulated orgs submit to authorizing officials.
Close a Finding (Exercise)
Fix the AD lockout policy (see Exercise 2) → Re-run CIS-CAT Lite → Upload new results → Mark V-254239 as "Not a Finding" with evidence note. This demonstrates the full remediation workflow.
Network Discovery & Asset Inventory
Map the CSFC lab network, discover every host and service, find exposed ports that shouldn't be reachable, and document findings against CIS Control 1 and PCI-DSS Req 1.
- ✓Ping sweep:
nmap -sn -T4 192.168.56.0/24— list all live hosts - ✓Deep scan DC:
nmap -sV -sC -T4 -p 53,88,135,139,389,445,3268,3389 192.168.56.10 - ✓WebApp scan:
nmap -sV -sC -T4 -p 21,22,80,443,5000,5432 192.168.56.40 - ✓List SMB shares:
smbclient -L //192.168.56.10 -N— find CSFC_Shared (Everyone) - ✓Test anon FTP:
ftp 192.168.56.40→ user: anonymous → check /pub/csfc_reports/ - ✓Run exercise script:
bash 04_CSFC_GRC_Exercises.sh network— shows guided output - ✓Document findings: Create asset inventory spreadsheet (IP, hostname, OS, services, risk)
| Finding ID | Host | Issue | Sev | Control | Fix |
|---|---|---|---|---|---|
| FIND-NET-001 | 192.168.56.10 | RDP exposed on Domain Controller | HIGH | PCI-DSS 1.3.2 | Restrict port 3389 to mgmt VLAN only |
| FIND-NET-002 | 192.168.56.40 | PostgreSQL port exposed to network | HIGH | PCI-DSS 1.2.1 | Bind to localhost: edit postgresql.conf |
| FIND-NET-003 | 192.168.56.40 | Anonymous FTP enabled + writable | HIGH | PCI-DSS 2.2.1 | anonymous_enable=NO in vsftpd.conf |
| FIND-NET-004 | 192.168.56.40 | Flask debug mode / no production WSGI | HIGH | PCI-DSS 6.2.4 | debug=False, deploy with Gunicorn |
| FIND-NET-005 | 192.168.56.10 | SMB signing disabled on DC | MED | CIS Control 12 | Enable via GPO: Digitally sign communications |
Active Directory Compliance Audit
Audit CSFC's AD against PCI-DSS Requirement 8. Find misconfigurations Script 1 intentionally planted. Document each as a finding with evidence, then remediate using the provided PowerShell commands.
- ✓Check password policy:
Get-ADDefaultDomainPasswordPolicy | Format-List - ✓Domain Admins:
Get-ADGroupMember "Domain Admins" | Select Name,SamAccountName - ✓CDE access group:
Get-ADGroupMember "GRP_CardholderData" | Select Name,SamAccountName - ✓Stale accounts:
Search-ADAccount -AccountInactive -TimeSpan 90.00:00:00 -UsersOnly - ✓Service accounts:
Get-ADGroupMember "GRP_IT_Admins" | Where {$_.SamAccountName -like "svc.*"} - ✓Lynis AD scan: From Kali —
bash 04_CSFC_GRC_Exercises.sh adaudit - ✓Document all findings with PowerShell output as screenshots in
/opt/csfc-grc/evidence/
PCI-DSS 8.2.4 requires minimum 12 characters from 1 January 2025 (v4.0). Current policy: 6. This is a mandatory requirement for Level 1 merchants.
LockoutThreshold = 0 means unlimited authentication attempts. PCI-DSS 8.3.9 requires accounts be locked after 10 failed attempts within 30 minutes. Combined with weak passwords, this means the domain is trivially brute-forceable.
o.employee is a former Finance Analyst who left the company. Account is still enabled and in GRP_CardholderData. PCI-DSS 8.3.7 requires disabling within 6 months; best practice is same-day on termination. HR should have triggered this on offboarding.
svc.appserver has Domain Admin rights. Service accounts should have minimum necessary permissions (least privilege). If the application server is compromised, an attacker inherits Domain Admin. This is a privilege escalation path.
Vulnerability Assessment
Run OpenVAS against the CSFC lab environment. Identify unpatched CVEs, misconfigured services, and web vulnerabilities. Document results against PCI-DSS Req 11 — quarterly internal scans are mandatory.
- ✓Start OpenVAS: From Kali browser →
https://localhost:9392→ admin / [set at install] - ✓Scans → Targets → New: Name "CSFC Lab", Hosts: 192.168.56.0/24
- ✓Scans → Tasks → New: Target = CSFC Lab, Config = "Full and Fast", Start
- ✓While scan runs:
bash 04_CSFC_GRC_Exercises.sh vulnscanto see expected findings - ✓Export scan results as PDF (Scans → Reports → Download PDF)
- ✓Triage: For each Critical/High finding — identify CVE, CVSS score, affected system, patch timeline
- ✓Add top 3 findings to POA&M with 14-day (Critical) or 30-day (High) target remediation dates
- ✓Also run Lynis:
sudo lynis audit system --remote 192.168.56.40for OS-level hardening gaps
Expected Scan Results (Simulated)
| Host | CVSS | CVE / ID | Finding | POA&M Timeline |
|---|---|---|---|---|
| 192.168.56.40 | 10.0 | CUSTOM-001 | SQL Injection in /customers endpoint — full DB dump possible | 7 days |
| 192.168.56.40 | 9.8 | CUSTOM-002 | Unauthenticated API returns CVV and SSN — PCI/GDPR violation | 7 days |
| 192.168.56.10 | 9.8 | CVE-2024-38063 | Windows TCP/IP heap overflow — RCE without authentication | 14 days |
| 192.168.56.40 | 8.6 | CVE-2023-25577 | Flask/Werkzeug debug console — interactive RCE at /console | 14 days |
| 192.168.56.40 | 7.5 | CUSTOM-003 | Anonymous FTP writable — data exfiltration / upload of malware | 14 days |
| 192.168.56.40 | 7.0 | CVE-2024-6387 | OpenSSH regreSSHion — signal handler race condition | 30 days |
| 192.168.56.10 | 6.5 | CVE-2023-28252 | Windows Common Log File System privilege escalation | 30 days |
| 192.168.56.40 | 5.0 | CUSTOM-004 | SSH allows root login — lateral movement risk | 60 days |
GDPR Data Discovery & PII Inventory
Find all personal data in the CSFC environment. Map each data type to its legal basis and retention period. Create a Records of Processing Activities (ROPA) as required by GDPR Art 30.
- ✓DB PII scan:
psql -h 192.168.56.40 -U csfc_readonly -d csfc_production -c "SELECT customer_id,first_name,ssn,dob FROM customers LIMIT 5;" - ✓List EU customers:
SELECT first_name,last_name,country FROM customers WHERE country IN ('FR','DE','IT','SE','IE','ES'); - File share DLP scan: Mount share →
grep -rI "SSN\|[0-9]{3}-[0-9]{2}-[0-9]{4}" /mnt/csfc_hr/✓ - ✓Check card data:
SELECT card_id, card_number, cvv FROM payment_cards;— confirm CVV is visible - ✓Run GDPR exercise:
bash 04_CSFC_GRC_Exercises.sh gdpr - ✓Complete the ROPA template below with all 6 processing activities
- ✓Determine: Was EU customer data potentially accessed in the GitHub incident? → 72-hour notification clock starts!
40 customer records contain US Social Security Numbers stored in plain text in PostgreSQL. GDPR Art 5(1)(f) requires "appropriate security including protection against unauthorised processing." Unencrypted SSNs violate this principle and also violate state data breach notification laws in all US states.
HR\Salary_Register_2024.csv contains employee names, SSNs, DOBs, bank accounts, and salaries in a plain CSV on a file share. This is special category data under GDPR Art 9 (financial data, health-adjacent). Requires explicit policy + technical controls.
GDPR Art 30 requires organisations of CSFC's size to maintain a written Record of Processing Activities. No ROPA document was found in the GRC document repository. This is a direct Article 30 violation and would be the first thing a Data Protection Authority auditor asks for.
The .env.production file contained DB credentials. The suspicious transactions at 02:14 AM suggest the attacker may have accessed the customer database (SSNs, DOBs) and payment_cards table (full PAN + CVV). If confirmed, this triggers GDPR Art 33 — 72-hour notification to supervisory authority. Clock starts from "awareness" — Jane Lee was notified at T+6:15.
Complete this ROPA table for CSFC. GDPR Art 30 requires all columns to be filled. The first row is done as an example.
| Activity | Data Types | Purpose | Legal Basis | Retention | Recipients | Risk |
|---|---|---|---|---|---|---|
| Customer Onboarding | Name, email, DOB, SSN, address | KYC / AML compliance | Legal obligation (BSA) | 7 years | Regulators (FinCEN) | MEDIUM |
| Payment Processing | → Your task: fill in PAN, expiry, CVV / contract fulfilment / PCI 5yr retention / payment processor recipient | |||||
| Fraud Detection | → Your task: transaction data, geolocation / legitimate interest / 3 years / internal only | |||||
| Employee HR | → Your task: salary, SSN, DOB, bank account / employment contract / duration + 7 years / HR + payroll | |||||
| Marketing | → Your task: email, name / consent (Art 6(1)(a)) / until withdrawn / email platform | |||||
| Security Logging | → Your task: IP, username, event / legitimate interest / 12 months (PCI-DSS 10.5) / SIEM only | |||||
Incident Response Simulation
Work through the GitHub credential leak incident using NIST SP 800-61 Rev 3 phases. Collect evidence from the database audit log, analyse the attack timeline, and determine GDPR notification obligations.
Incident Timeline
T+0:00 — Sept 1, 14:23 UTC
s.dev runs git push origin main — .env.production goes public on GitHub. Git history shows the commit.
T+0:05 — Sept 1, 14:28 UTC
GitHub Actions CI/CD pipeline triggers. First external bot scans the repository within 5 minutes of the push (this is normal — automated credential scanners operate continuously).
T+2:30 — Sept 1, 16:53 UTC
External IP 41.66.224.10 first appears in CSFC network logs — probing the PostgreSQL port 5432 (exposed to network per FIND-NET-002).
T+3:60 — Sept 1, 18:23 UTC
First successful DB authentication using csfc_admin/admin123. audit_log table shows SELECT on payment_cards — attacker likely exfiltrating card data.
T+4:01 — Sept 1, 18:24–18:26 UTC
3 fraudulent transactions inserted at 02:14, 02:15, 02:16 AM (local time — the audit_log entries you can query from the database).
T+6:10 — Sept 1, 20:33 UTC
Wazuh UNUSUAL_PATTERN rule fires. Alert sent to SOC email distribution list.
T+6:15 — Sept 1, 20:38 UTC — GDPR CLOCK STARTS
Jane Lee (CISO) reads the Wazuh alert. This is "awareness" under GDPR Art 33. The 72-hour notification window begins now. Deadline: Sept 4, 20:38 UTC.
T+7:00 — Sept 1, 21:38 UTC
GitHub repo made private. All credentials in .env.production rotated (DB password, AWS keys, payment API key, JWT secret).
Evidence Collection Commands
- ✓Run all 4 SQL queries above, screenshot results
- ✓Check Wazuh dashboard: Security Events → filter by "UNUSUAL_PATTERN" — find the Sept 1 alerts
- ✓Determine: was payment_cards data (PAN + CVV) accessed? → This determines PCI-DSS notification requirement
- ✓Count EU customer records potentially exposed → This determines GDPR Art 33 notification scope
- ✓Run:
bash 04_CSFC_GRC_Exercises.sh irfor full guided walkthrough
Gaps identified (document these):
❌ No pre-commit hook to prevent credential commits to git
❌ No automated secret scanning (GitHub Advanced Security / GitLeaks not configured)
❌ No .gitignore rule covering .env files in the Engineering repo
❌ Developer security training incomplete — s.dev was unaware of the risk
❌ No incident response playbook existed for credential leak scenario
✅ Wazuh detected unusual transaction pattern (T+6:10)
✅ Database audit_log retained evidence of the access
⚠️ Detection took 6+ hours — should have been minutes with GitHub secret scanning
❌ No UEBA (User Entity Behaviour Analytics) to flag the Nigerian IP accessing DB for first time
Scope: Attacker authenticated as csfc_admin. Had full access to all 40 customers, 10 card records including CVVs, and could read/write/delete all data. 3 fraudulent transactions confirmed inserted.
✅ GitHub repo made private (T+7:00)
✅ DB password rotated (admin123 → new strong password)
✅ AWS access keys revoked in IAM console
✅ Payment API key regenerated with provider
✅ JWT secret rotated (forces all sessions to expire)
❌ Firewall rule to block 41.66.224.10 not added until T+8:00 — too slow
Remove .env from git history: git filter-repo --path .env.production --invert-paths
Scan all repos: gitleaks detect --source . -v
Add .gitignore rule: echo "*.env*" >> .gitignore
Install pre-commit hook: pre-commit install && pre-commit autoupdate
Configure GitHub secret scanning (Settings → Code security → Secret scanning)
Root Cause: Lack of developer security training + no technical controls preventing credential commits
Contributing Factors: PostgreSQL exposed to network (should be localhost only), no secret scanning, weak DB password (admin123) — any scan would have tried it
New Controls Required: Mandatory git pre-commit hooks, GitHub secret scanning, developer security training (OWASP), quarterly phishing + security awareness, bind PostgreSQL to localhost
Board Report: Due within 5 business days. Include: incident scope, data affected, containment actions, root cause, new controls, financial impact estimate.
Art 33 Notification Criteria
Must notify if breach is "likely to result in a risk to the rights and freedoms of natural persons." Given: 6 EU customer records with SSN/DOB/PAN potentially accessed → notification required.
What to Include (Art 33(3))
Web App Vulnerabilities & SQLi
Document web application vulnerabilities in the CSFC portal. Run the SQL injection tests, collect evidence, and write professional GRC findings mapped to PCI-DSS Req 6.4 and OWASP Top 10.
- ✓Test SQLi:
curl "http://192.168.56.40:5000/customers?search=%27+OR+%271%27%3D%271"— should return all 40 customers - ✓Test unauth API (SSN):
curl http://192.168.56.40:5000/api/customers | python3 -m json.tool | grep ssn - ✓Test card API:
curl http://192.168.56.40:5000/api/cards | python3 -m json.tool— confirm CVV visible - ✓Test IDOR: After login, try
http://192.168.56.40:5000/customer/1through/customer/40— all accessible - ✓Wazuh check: Open Wazuh dashboard → verify Rule 100070 fired for the SQLi attempt
- ✓Screenshot all 4 tests as evidence. Write up each finding using the template below.
Web App Finding Template
Risk Register + Heatmap
CSFC's pre-populated risk register with 10 risks scored by likelihood × impact. The heatmap shows the current risk profile — dominated by Critical and High findings.
| ID | Risk | Likelihood | Impact | Score | Rating | Owner | Treatment |
|---|---|---|---|---|---|---|---|
| R-01 | VPN has no MFA — credential stuffing | 4 | 5 | 20 | CRITICAL | Alice Nguyen | Mitigate |
| R-02 | Weak AD password policy (6 chars) | 4 | 4 | 16 | HIGH | Alice Nguyen | Mitigate |
| R-03 | Unpatched systems (CVE-2024-38063) | 3 | 5 | 15 | HIGH | Tom Brecker | Mitigate |
| R-04 | GitHub credential leak (active incident) | 3 | 5 | 15 | HIGH | Jane Lee | Mitigate |
| R-05 | Shadow IT — unsanctioned cloud services | 4 | 4 | 16 | HIGH | Diane Holloway | Mitigate |
| R-06 | No DLP — data exfiltration possible | 2 | 5 | 10 | MEDIUM | Jane Lee | Mitigate |
| R-07 | Incomplete asset inventory | 3 | 3 | 9 | MEDIUM | Alice Nguyen | Mitigate |
| R-08 | GDPR breach notification failure risk | 2 | 4 | 8 | MEDIUM | Jane Lee | Mitigate |
| R-09 | PCI-DSS non-compliance (CVV stored) | 3 | 5 | 15 | HIGH | Tom Brecker | Mitigate |
| R-10 | Third-party vendor breach (supply chain) | 2 | 4 | 8 | MEDIUM | Diane Holloway | Transfer |
POA&M Tracker
15 pre-loaded Plan of Action & Milestones items. Work through each one — fix the finding in the lab, update the status, and add your evidence note. This is your deliverable at the end of the lab.
| # | Finding | Sev | Control | Due | Owner | Status |
|---|---|---|---|---|---|---|
| POA-001 | CVV stored in payment_cards table | CRIT | PCI-DSS 3.3.1 | Nov 1 | Tom Brecker | OPEN |
| POA-002 | No MFA on VPN gateway | CRIT | PCI-DSS 8.3.1 | Nov 15 | Alice Nguyen | OPEN |
| POA-003 | SQL Injection in /customers endpoint | CRIT | PCI-DSS 6.4.1 | Nov 1 | Liam O'Brien | OPEN |
| POA-004 | Unauthenticated /api/customers and /api/cards | CRIT | PCI-DSS 6.4 | Nov 1 | Liam O'Brien | OPEN |
| POA-005 | Contractor dev.c2 in CDE access group | CRIT | PCI-DSS 7.2.1 | Oct 15 | Alice Nguyen | OPEN |
| POA-006 | local.admin in Domain Admins (shared account) | CRIT | PCI-DSS 8.2.1 | Oct 15 | Alice Nguyen | OPEN |
| POA-007 | Weak password policy — min 6 chars, no lockout | HIGH | PCI-DSS 8.2.4 | Nov 1 | Alice Nguyen | OPEN |
| POA-008 | Terminated employee o.employee still active | HIGH | PCI-DSS 8.3.7 | Oct 15 | Rachel Thompson | OPEN |
| POA-009 | Full PAN stored unmasked in database | HIGH | PCI-DSS 3.4.1 | Dec 1 | Tom Brecker | OPEN |
| POA-010 | svc.appserver service account has Domain Admin rights | HIGH | PCI-DSS 8.6.1 | Nov 15 | Alice Nguyen | OPEN |
| POA-011 | Anonymous FTP enabled and writable | HIGH | PCI-DSS 2.2.1 | Nov 1 | Tom Brecker | OPEN |
| POA-012 | SSNs stored in plain text in customers table | HIGH | GDPR Art 5 | Dec 1 | Tom Brecker | OPEN |
| POA-013 | Security event log 1MB (should be 1GB+) | MED | PCI-DSS 10.3.2 | Dec 1 | Alice Nguyen | OPEN |
| POA-014 | Max password age 180 days (PCI requires 90) | MED | PCI-DSS 8.3.6 | Nov 1 | Alice Nguyen | OPEN |
| POA-015 | GDPR ROPA document does not exist | MED | GDPR Art 30 | Nov 15 | Jane Lee | OPEN |
When Things Break
Common issues when running the lab scripts. Find your error, run the fix, and get back on track.
The AD DS role isn't fully installed or the server hasn't fully replicated after promotion. Wait 5 minutes after DC promotion before running the script.