diff --git a/README.md b/README.md index 2fac9900..3a5362ce 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,8 @@ Create a randomized copy of any lab with unique names but identical attack paths - [CLI configuration](docs/cli.md) -- Viper-based config, environment variables, per-environment settings - [Domains and users](docs/domains-and-users.md) -- full network topology, credentials, and attack paths - [Vulnerability catalog](docs/GOAD-vulnerabilities-comprehensive.md) -- all 50+ vulnerabilities with exploitation techniques -- [Validation guide](docs/validation.md) -- automated vulnerability validation +- [Validation guide](docs/validation.md) -- automated vulnerability validation (with live dashboard and polling) +- [Scoreboard guide](docs/scoreboard.md) -- live engagement status board (answer key + agent report verification) - [Provider guides](docs/mkdocs/docs/providers/) -- VirtualBox, VMware, Proxmox, AWS, Azure, Ludus - [AWS AMI build & deploy workflow](docs/mkdocs/docs/providers/aws-ami-workflow.md) -- end-to-end warpgate + Terragrunt + Ansible - [Extension guides](docs/mkdocs/docs/extensions/) -- ELK, Exchange, Wazuh, hardened workstation diff --git a/docs/img/validate_dashboard_complete.png b/docs/img/validate_dashboard_complete.png new file mode 100644 index 00000000..1beefeb7 Binary files /dev/null and b/docs/img/validate_dashboard_complete.png differ diff --git a/docs/img/validate_dashboard_running.png b/docs/img/validate_dashboard_running.png new file mode 100644 index 00000000..1f75ca90 Binary files /dev/null and b/docs/img/validate_dashboard_running.png differ diff --git a/docs/mkdocs/docs/cli-reference.md b/docs/mkdocs/docs/cli-reference.md index cf6fedb1..e357b490 100644 --- a/docs/mkdocs/docs/cli-reference.md +++ b/docs/mkdocs/docs/cli-reference.md @@ -442,7 +442,7 @@ dreadgoad verify-trusts Validate GOAD vulnerability configurations. -Checks credentials, Kerberos, SMB, delegation, MSSQL, ADCS, ACLs, trusts, SID filtering, scheduled tasks, LLMNR/NBT-NS, GPO abuse, gMSA, LAPS, and services. +Checks credentials, Kerberos, SMB, delegation, MSSQL, ADCS, ACLs, trusts, SID filtering, scheduled tasks, LLMNR/NBT-NS, GPO abuse, gMSA, LAPS, and services. When stdout is a TTY, results stream into a live dashboard with a per-category breakdown; pass `--plain` to fall back to line-by-line output. | Flag | Description | |------|-------------| @@ -451,21 +451,81 @@ Checks credentials, Kerberos, SMB, delegation, MSSQL, ADCS, ACLs, trusts, SID fi | `--output string` | JSON report output path | | `--quick` | Quick validation of critical vulnerabilities only | | `--verbose` | Enable verbose output | +| `--plain` | Disable the live dashboard; stream results to stdout | +| `--poll string` | Re-run cadence inside the live dashboard (Go duration like `1m`, `5m`, or `never`; minimum `1m`, default `never`) | ```bash -# Full validation with table output -dreadgoad validate +dreadgoad validate # full run, live dashboard on a TTY +dreadgoad validate --quick # critical vulnerabilities only +dreadgoad validate --plain # disable the dashboard +dreadgoad validate --poll 5m # rerun every 5 minutes inside the dashboard +dreadgoad validate --output report.json # custom report path +``` + +Dashboard keys: `q`, `ctrl+c`, or `esc` to quit. `--poll` is ignored without the dashboard (non-TTY or `--plain`). + +See [validation.md](https://github.com/dreadnode/DreadGOAD/blob/main/docs/validation.md) for the full guide. + +--- + +### scoreboard + +Live status board for GOAD engagements. Parses the lab `config.json` into a checklist of objectives ("answer key"), polls an agent's JSONL report (local, SSM, or `ares`), and renders a verification TUI. + +#### `scoreboard generate-key` + +Build the answer key from the lab configuration. Run this once per lab (or after lab edits) so `scoreboard run` and `scoreboard demo` have something to verify against. + +| Flag | Description | +|------|-------------| +| `--config string` | Path to GOAD `config.json` (default `ad/GOAD/data/config.json`) | +| `--output string` | Output path for the answer key (default `scoreboard/answer_key.json`) | + +```bash +dreadgoad scoreboard generate-key +``` -# Quick check of critical vulnerabilities -dreadgoad validate --quick +#### `scoreboard run` -# Export JSON report -dreadgoad validate --format json --output report.json +Poll an agent's JSONL report and render the live verification TUI. -# Verbose output, don't fail on errors -dreadgoad validate --verbose --no-fail +| Flag | Description | +|------|-------------| +| `--transport string` | `local`, `ssm`, or `ares` (default `"local"`) | +| `--report string` | Path to the agent report on the target (default `/tmp/report.jsonl`) | +| `--answer-key string` | Path to `answer_key.json` (default `scoreboard/answer_key.json`) | +| `--instance-id string` | EC2 instance ID (required for `ssm` and `ares`) | +| `--ssm-region string` | AWS region for SSM (defaults to `--region`) | +| `--ares-binary string` | Path to the `ares` binary on the target (default `/usr/local/bin/ares`) | +| `--interval duration` | Poll interval (default `3s`) | +| `--restart` | Delete the report file on the target before starting (no-op for `ares`) | +| `--once` | Fetch and verify once, print the board, and exit (no TUI) | + +```bash +# Local report file +dreadgoad scoreboard run --report ./report.jsonl + +# Remote report via SSM +dreadgoad scoreboard run --transport ssm --instance-id i-0123456789abcdef0 + +# One-shot static board (no TUI) +dreadgoad scoreboard run --once ``` +#### `scoreboard demo` + +Render a sample board with mock findings so you can see the layout before running a real engagement. + +| Flag | Description | +|------|-------------| +| `--config string` | Path to GOAD `config.json` (default `ad/GOAD/data/config.json`) | + +```bash +dreadgoad scoreboard demo +``` + +See [scoreboard/agent_prompt.md](https://github.com/dreadnode/DreadGOAD/blob/main/scoreboard/agent_prompt.md) for the report format agents are expected to emit. + --- ## Extensions diff --git a/docs/mkdocs/docs/usage/goad_args.md b/docs/mkdocs/docs/usage/goad_args.md index 5790d83c..0c87cd43 100644 --- a/docs/mkdocs/docs/usage/goad_args.md +++ b/docs/mkdocs/docs/usage/goad_args.md @@ -69,7 +69,9 @@ dreadgoad infra validate ### Validation and diagnostics ```bash -dreadgoad validate +dreadgoad validate # live dashboard when stdout is a TTY +dreadgoad validate --plain # disable the dashboard +dreadgoad validate --poll 5m # rerun every 5 minutes inside the dashboard dreadgoad validate --format json --output results.json dreadgoad health-check dreadgoad diagnose @@ -77,6 +79,16 @@ dreadgoad doctor dreadgoad verify-trusts ``` +### Engagement scoreboard + +```bash +dreadgoad scoreboard generate-key # build answer_key.json +dreadgoad scoreboard run --report ./report.jsonl # local transport +dreadgoad scoreboard run --transport ssm --instance-id i-0123456789abcdef0 +dreadgoad scoreboard run --once # one-shot static board +dreadgoad scoreboard demo # sample board with mock findings +``` + ### Environment and configuration ```bash diff --git a/docs/scoreboard.md b/docs/scoreboard.md new file mode 100644 index 00000000..e0d2f316 --- /dev/null +++ b/docs/scoreboard.md @@ -0,0 +1,114 @@ +# GOAD Scoreboard + +`dreadgoad scoreboard` turns a GOAD lab into a live status board for an +engagement: it parses the lab's `config.json` into an answer key of +objectives, polls the agent's JSONL report, and verifies findings against +the key in a Bubbletea/Lipgloss TUI. + +## Quick Start + +```bash +dreadgoad scoreboard generate-key # build answer_key.json once per lab +dreadgoad scoreboard run --report ./report.jsonl +dreadgoad scoreboard demo # preview the layout with mock findings +``` + +Point the agent at `/tmp/report.jsonl` using +[`scoreboard/agent_prompt.md`](../scoreboard/agent_prompt.md). For remote +reports use `--transport ssm` or `--transport ares` (see below). + +## `scoreboard generate-key` + +Builds the verification checklist (`answer_key.json`) from a GOAD +`config.json`. Each objective covers one provable finding (a password, +hash, kerberoastable SPN, ADCS template, ACL chain step, etc.), grouped +by category. Regenerate after lab edits or variant generation. The output +is gitignored. + +| Flag | Description | +|-------------|-------------------------------------------------------------------| +| `--config` | Path to GOAD `config.json` (default `ad/GOAD/data/config.json`) | +| `--output` | Output path (default `scoreboard/answer_key.json`) | + +```bash +dreadgoad scoreboard generate-key +dreadgoad scoreboard generate-key --config ad/GOAD-variant-1/data/config.json +``` + +The command prints the total objective count and a per-group breakdown. + +## `scoreboard run` + +Polls the agent's JSONL report, verifies each finding against the answer +key, and renders the live board. + +| Flag | Default | Description | +|-----------------|----------------------------------|--------------------------------------------------------------------| +| `--transport` | `local` | `local`, `ssm`, or `ares` | +| `--report` | `/tmp/report.jsonl` | Path to the agent's report on the target | +| `--answer-key` | `scoreboard/answer_key.json` | Path to the answer key | +| `--instance-id` | | EC2 instance ID (required for `ssm` and `ares`) | +| `--ssm-region` | falls back to `--region` | AWS region for SSM | +| `--ares-binary` | `/usr/local/bin/ares` | Path to the `ares` binary on the target | +| `--interval` | `3s` | Poll interval | +| `--restart` | `false` | Delete the report file on the target before starting | +| `--once` | `false` | Fetch and verify once, print the static board, exit (no TUI) | + +### Transports + +- **`local`**: read a JSONL file from the host running the CLI. Best + for development, or when the agent writes its report to a synced + directory. +- **`ssm`**: read `/tmp/report.jsonl` (or `--report`) from an EC2 + instance over SSM. Requires the SSM agent, IAM, and `--instance-id`. +- **`ares`**: invoke an `ares` binary on the target to stream findings. + Use when an agent writes findings through `ares` instead of a flat + file. `--restart` is a no-op for this transport. + +### Examples + +```bash +# One-shot static board (CI/CD friendly) +dreadgoad scoreboard run --once --report ./report.jsonl + +# SSM, fresh run (wipe the remote report first) +dreadgoad scoreboard run \ + --transport ssm \ + --instance-id i-0123456789abcdef0 \ + --restart + +# Faster polling for short engagements +dreadgoad scoreboard run --interval 1500ms +``` + +## `scoreboard demo` + +Generates a synthetic report against the current lab config and renders +the static board. Use it to preview the layout, sanity-check the answer +key, or screenshot the dashboard without running a real agent. + +| Flag | Description | +|------------|-----------------------------------------------------------------| +| `--config` | Path to GOAD `config.json` (default `ad/GOAD/data/config.json`) | + +```bash +dreadgoad scoreboard demo +``` + +## Agent Report Format + +The TUI consumes a JSONL stream: one header line followed by one finding +per line. + +```json +{"agent_id": "dreadnode-agent", "start_time": "2026-05-11T17:00:00Z"} +{"target": "samwell.tarly@north.sevenkingdoms.local", "evidence": "Heartsbane1", "description": "password from AD description"} +``` + +[`scoreboard/agent_prompt.md`](../scoreboard/agent_prompt.md) is the +canonical spec and is suitable to hand to an agent verbatim. + +## Related Documentation + +- [`validation.md`](./validation.md): operator-side vulnerability validation +- [`GOAD-vulnerabilities-comprehensive.md`](./GOAD-vulnerabilities-comprehensive.md): vulnerability catalog the answer key is derived from diff --git a/docs/validation.md b/docs/validation.md index 9f7db7c4..b4d15ce0 100644 --- a/docs/validation.md +++ b/docs/validation.md @@ -1,332 +1,119 @@ # GOAD Vulnerability Validation -This document describes how to validate that your GOAD deployment has all the documented vulnerabilities properly configured. - -## Overview - -The GOAD validation system checks that all 50+ vulnerabilities documented in [`GOAD-vulnerabilities-comprehensive.md`](./GOAD-vulnerabilities-comprehensive.md) are properly configured in your AWS deployment. This ensures the lab is ready for penetration testing training. +`dreadgoad validate` runs SSM/Run-Command PowerShell checks against a live +lab to confirm the 50+ vulnerabilities in +[`GOAD-vulnerabilities-comprehensive.md`](./GOAD-vulnerabilities-comprehensive.md) +are wired up correctly. ## Quick Start -### Run Full Validation - -```bash -# Validate staging environment (default) -dreadgoad validate - -# Validate a specific environment -dreadgoad validate --env dev - -# Enable verbose output -dreadgoad validate --verbose - -# Initial validation without failing on errors -dreadgoad validate --env staging --no-fail -``` - -### Run Quick Validation - -For a faster sanity check of critical vulnerabilities: - ```bash -dreadgoad validate --quick -dreadgoad validate --quick --env dev +dreadgoad validate # full validation, active env +dreadgoad validate --env dev # specific environment +dreadgoad validate --quick # critical vulnerabilities only +dreadgoad validate --verbose # extra per-check detail +dreadgoad validate --no-fail # always exit 0 ``` -## What Gets Validated - -The validation script checks the following categories of vulnerabilities: - -### 1. **Credential Discovery** (10 checks) - -- ✓ Passwords in user description fields (samwell.tarly) -- ✓ Username=password combinations (hodor) -- ✓ Weak password policies -- ✓ Password spray vulnerabilities - -### 2. **Kerberos Attack Vectors** (12 checks) - -- ✓ AS-REP Roasting accounts (brandon.stark, missandei) -- ✓ Kerberoasting targets (jon.snow, sql_svc) -- ✓ Service Principal Names configured -- ✓ Kerberos user enumeration possible - -### 3. **Network Misconfigurations** (8 checks) - -- ✓ SMB signing disabled on CASTELBLACK and BRAAVOS -- ✓ LLMNR/NBT-NS enabled -- ✓ NTLM relay opportunities -- ✓ Anonymous SMB session access - -### 4. **Delegation Attacks** (6 checks) - -- ✓ Unconstrained delegation (sansa.stark) -- ✓ Constrained delegation (jon.snow) -- ✓ Resource-Based Constrained Delegation setup -- ✓ Machine Account Quota = 10 +### Live Dashboard -### 5. **MSSQL Configurations** (8 checks) +When stdout is a TTY, `dreadgoad validate` opens a live Bubbletea/Lipgloss +dashboard with a per-category PASS/FAIL/WARN breakdown, a running success +rate, and a footer that switches between `RUNNING`, `WAITING`, and +`COMPLETE`. Categories with no applicable checks render with a dim `[ ]` +marker instead of `[v]`. -- ✓ MSSQL services running on CASTELBLACK and BRAAVOS -- ✓ Impersonation permissions (samwell.tarly → sa, arya.stark → dbo) -- ✓ MSSQL admin accounts (jon.snow, khal.drogo) -- ✓ Trusted links between servers +![Validate dashboard mid-run](img/validate_dashboard_running.png) +![Validate dashboard complete](img/validate_dashboard_complete.png) -### 6. **ADCS Vulnerabilities** (15+ checks) - -- ✓ ADCS installed on BRAAVOS -- ✓ ADCS Web Enrollment configured (ESC8) -- ✓ Vulnerable certificate templates (ESC1, ESC2, ESC3, ESC4, ESC6, etc.) -- ✓ Certificate mapping misconfigurations - -### 7. **ACL Abuse** (20+ checks) - -- ✓ ForceChangePassword permissions -- ✓ GenericWrite on users/computers -- ✓ WriteDacl permissions -- ✓ WriteOwner on groups -- ✓ GPO abuse permissions -- ✓ Complete ACL attack chains - -### 8. **Domain Trusts** (4 checks) - -- ✓ Parent-child trust (sevenkingdoms ↔ north) -- ✓ Forest trust (sevenkingdoms ↔ essos) -- ✓ Cross-forest group memberships -- ✓ SID history enabled - -### 9. **Services & Miscellaneous** (10 checks) - -- ✓ IIS running on CASTELBLACK -- ✓ Print Spooler service status -- ✓ LDAP signing not enforced -- ✓ WebClient service configuration - -## Output Format - -### Console Output - -The script provides color-coded console output: +```bash +# Disable the dashboard and stream results to stdout +dreadgoad validate --plain -```text -========================================== -GOAD Vulnerability Validation -========================================== -Environment: dev -Inventory: ./dev-inventory -Output: /tmp/goad-validation-20241215-134500.json +# Re-run every 5 minutes on the same dashboard (minimum 1m) +dreadgoad validate --poll 5m +``` -ℹ Discovering instances... -✓ Found DC01: i-0123456789abcdef0 -✓ Found DC02: i-0123456789abcdef1 -✓ Found DC03: i-0123456789abcdef2 -✓ Found SRV02: i-0123456789abcdef3 -✓ Found SRV03: i-0123456789abcdef4 +Keys: `q`, `ctrl+c`, or `esc` to quit. The JSON report on disk is the +canonical record; it is rewritten at the end of each pass and the path is +printed on exit. -========================================== -1. Credential Discovery Vulnerabilities -========================================== -ℹ Checking for passwords in user descriptions... -✓ samwell.tarly has password in description +`--poll` requires the live dashboard (ignored with `--plain` or non-TTY). +Intervals shorter than `1m` are rejected. Accepted "off" values: `never`, +`off`, `no`, `false`, `0`, `0s`, or empty. -========================================== -2. Kerberos Attack Vectors -========================================== -ℹ Checking AS-REP Roasting accounts... -✓ brandon.stark has DoesNotRequirePreAuth enabled -✗ missandei does NOT have PreAuth disabled -⚠ jon.snow SPNs configured but not optimal +## What Gets Validated -... +The dashboard screenshots above show the live category set. The major +attack surfaces covered: -========================================== -Validation Summary -========================================== -Total Checks: 87 -Passed: 73 -Failed: 8 -Warnings: 6 - -Success Rate: 84% +- **Credentials**: passwords in description fields, weak policies, spray +- **Kerberos**: AS-REP roasting, kerberoasting, SPNs +- **SMB / LLMNR / Network**: SMB signing, NTLM relay, name-resolution poisoning +- **Delegation**: unconstrained, constrained, RBCD, `MachineAccountQuota` +- **MSSQL**: services, impersonation, sysadmins, trusted links +- **ADCS**: installation, web enrollment, ESC1/2/3/4/6/7/8/9/10/11/13/15 templates +- **ACL abuse**: `ForceChangePassword`, `GenericWrite`, `WriteDacl`, `WriteOwner`, GPO +- **Trusts**: parent/child, forest trust, cross-forest membership, SID history +- **Services & misc**: IIS, Print Spooler, LDAP signing, WebClient, gMSA, LAPS -Results saved to: /tmp/goad-validation-20241215-134500.json -========================================== -``` +See [`GOAD-vulnerabilities-comprehensive.md`](./GOAD-vulnerabilities-comprehensive.md) +for the full catalog with exploitation details. -### JSON Output +## JSON Report -Results are also saved to a JSON file for programmatic analysis: +Every run writes a JSON report to `/tmp/goad-validation-.json` +(or `--output `): ```json { - "validation_date": "2024-12-15T13:45:00Z", - "environment": "dev", - "summary": { - "total_checks": 87, - "passed": 73, - "failed": 8, - "warnings": 6 - }, + "validation_date": "2026-05-11T16:45:00Z", + "environment": "staging", + "total_checks": 233, + "passed": 212, + "failed": 0, + "warnings": 0, "checks": [ { - "category": "credential_discovery", + "status": "PASS", + "category": "Credentials", "name": "password_in_description", - "status": "pass", - "details": "samwell.tarly has password 'Heartsbane' in description", - "user": "samwell.tarly", - "domain": "north.sevenkingdoms.local" - }, - ... + "detail": "samwell.tarly has password in description" + } ] } ``` -## Exit Codes - -- **0**: All checks passed (or only warnings) -- **1**: One or more checks failed - -## Validation Checklist - -Use this checklist to track validation progress: - -### Critical Vulnerabilities (Must Pass) - -- [ ] All 5 servers running and accessible -- [ ] All 3 domains configured correctly -- [ ] All expected users present (46+ users) -- [ ] SMB signing disabled on SRV02 and SRV03 -- [ ] MSSQL running on both servers -- [ ] ADCS installed on BRAAVOS -- [ ] Domain trusts configured - -### High Priority Vulnerabilities - -- [ ] AS-REP Roasting: brandon.stark, missandei -- [ ] Kerberoasting: jon.snow, sql_svc -- [ ] Password in description: samwell.tarly -- [ ] Unconstrained delegation: sansa.stark -- [ ] Constrained delegation: jon.snow -- [ ] Machine Account Quota = 10 - -### Medium Priority Vulnerabilities - -- [ ] MSSQL impersonation permissions -- [ ] MSSQL trusted links -- [ ] ADCS vulnerable templates (ESC1-15) -- [ ] ACL permission chains -- [ ] Print Spooler enabled -- [ ] IIS file upload vulnerability - -### Lower Priority (Nice to Have) - -- [ ] LLMNR/NBT-NS enabled -- [ ] LAPS configuration -- [ ] GPO abuse permissions -- [ ] Cross-forest group memberships -- [ ] Bot accounts configured +`status` is one of `PASS`, `FAIL`, `WARN`, `SKIP`, `INFO`. Exit code is +`0` when no checks failed (or `--no-fail` is set), `1` otherwise. ## Troubleshooting -### Common Issues - -#### 1. "Could not find all required domain controllers" +### "Could not find all required domain controllers" -**Cause**: Instances not running or SSM not accessible - -**Solution**: +Instances not running or SSM not accessible. ```bash -# Check instance status dreadgoad lab status - -# Verify SSM agent is running aws ssm describe-instance-information --filters "Key=tag:Name,Values=*goad*" ``` -#### 2. "Permission denied" errors +### SSM command timeouts -**Cause**: Script not executable or AWS credentials not configured +Check network connectivity to the instances and verify WinRM is running. +A full pass takes a couple of minutes; the dashboard footer or `--plain` +output shows progress. -**Solution**: +### Many checks failing or warning -```bash -# Make script executable -chmod +x scripts/validate-goad-vulns.sh - -# Check AWS credentials -aws sts get-caller-identity -``` - -#### 3. Script hangs at "Discovering instances..." or times out - -**Cause**: AWS CLI calls can be slow, especially when querying multiple instances - -**Solution**: +Vulnerabilities likely not fully provisioned. Re-run the vulnerability +plays: ```bash -# Option 1: Run with --no-fail to see progress -dreadgoad validate --env staging --no-fail --verbose - -# Option 2: Test AWS CLI connectivity first -time aws ec2 describe-instances --region --max-results 5 -``` - -**Note**: The script may take 1-2 minutes to complete due to multiple AWS API calls. This is normal. - -#### 4. "Timeout" errors during SSM commands - -**Cause**: SSM commands taking too long - -**Solution**: - -- Increase sleep time in script (currently 5 seconds) -- Check network connectivity to instances -- Verify Windows Remote Management service running - -#### 5. Many checks showing "WARN" or "FAIL" - -**Cause**: Vulnerabilities not fully provisioned - -**Solution**: - -```bash -# Re-run vulnerability provisioning dreadgoad provision --plays vulnerabilities.yml - -# Or provision specific vulnerability roles dreadgoad provision --plays vulnerabilities.yml --limit dc02 ``` -## Advanced Usage - -### Validate Specific Categories - -Modify the script to run only specific validation sections: - -```bash -# Edit the script and comment out sections you don't need -vim scripts/validate-goad-vulns.sh -``` - -### Custom Output Location - -```bash -dreadgoad validate --output /path/to/custom-report.json -``` - -### Integrate with CI/CD - -Use the validation script in your CI/CD pipeline: - -```yaml -# Example GitHub Actions workflow -- name: Validate GOAD Deployment - run: | - dreadgoad validate --env staging - continue-on-error: false -``` - ## Manual Validation If automated validation fails, you can manually verify vulnerabilities: @@ -365,5 +152,6 @@ Get-ADObject $dn -Properties ms-DS-MachineAccountQuota | - [`GOAD-vulnerabilities-comprehensive.md`](./GOAD-vulnerabilities-comprehensive.md) - Complete vulnerability catalog - [`cli.md`](./cli.md) - CLI usage and configuration reference +- [`scoreboard.md`](./scoreboard.md) - Live engagement status board (the agent-facing counterpart to `validate`) - [GOAD Official Docs](https://github.com/Orange-Cyberdefense/GOAD) - Upstream documentation - [Mayfly's Walkthrough Series](https://mayfly277.github.io/categories/goad/) - Attack technique guides