diff --git a/.gitignore b/.gitignore index b809c33..990d8ce 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,20 @@ secrets-found.* breach-data/ stealer-logs/ +# Claude Code local config (contains operational/engagement details) +CLAUDE.md + +# Engagement findings — contain real vuln details, credentials, internal infra +findings/ + +# Captured engagement artifacts +refreshSession.js +mcp-proxy.jar + +# Local-only skills (engagement/program specific) +skills/hackerone/ +skills/report-template/ + # API keys / config that shouldn't ship .env .env.local diff --git a/CHANGELOG.md b/CHANGELOG.md index 75b9893..faab4e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,29 @@ and the project uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html). --- +## [Unreleased] + +### `offensive-osint` — feat: HackerOne hacktivity reference agent (§29.3) + +- Added `skills/offensive-osint/scripts/h1_reference.py` — stdlib-only Python script (no API key required) that queries HackerOne's public GraphQL API for disclosed reports, surfacing community-validated findings during recon. +- Supports: top-voted sort (community-validated techniques), top-bounty sort (business-impact framing), keyword search with cursor pagination (50 results/page), client-side severity and CWE filters, program-specific lookups, JSON output for piping. +- Documents three empirically discovered H1 GraphQL server crashes worked around in the script: named variables + substate filter + report fields, `disclosed_at` field + substate filter, sort + substate filter + report fields. +- Added §29.3 "HackerOne Disclosed Reports Reference" to `offensive-osint` with usage recipes for session-start baseline loading, tech-stack keyword search, pre-probe attack-class reference, and report-writing comparables. +- Added trigger phrases: `hackerone reference`, `h1 hacktivity`, `disclosed reports`, `community bug reports`, `prior disclosures`, `bug bounty reference`. +- Added smoke-test prompt #33. + +### `osint-methodology` — refactor: trimmed from 1,694 to 455 lines (v2.2) + +- Removed duplicate implementation content already covered by `offensive-osint` (§11–§15, §27–§29 original). +- Compressed 9 implementation-detail sections (Identity Fabric, API, JS, Mobile, Cloud, WAF/CDN, Vuln Prioritization, Phishing) into a single §11 pointer block — each now a 2-sentence description + companion skill reference. +- Collapsed §16–§21 (Cryptocurrency, Image/Video/Chronolocation, Threat Actor, People, Infrastructure OSINT, Automation, Synthetic Media) into a single §13 specialty domains section (~20 lines total). +- Retained full methodology core: confidence levels + upgrade workflows (§2), 5-stage pipeline + priority order + time budgets (§7), asset graph taxonomy + triage rules (§8), severity rubric + escalation rules (§9), OpSec + detectability + back-off (§6), breach × identity correlation (§12), anti-patterns (§14). +- Trimmed §30 Bug Bounty Submission (~90 lines → ~15) and §31 Client Deliverable Templates (~150 lines → ~20); retained essential structures (report skeleton, risk translation matrix). +- Renumbered: §26 Anti-Patterns → §14; §30 Bug Bounty → §15; §31 Deliverables → §16; §32 Self-Test → §17; §33 Changelog → §18. +- Updated skill self-test to 12 prompts aligned with new section numbers. + +--- + ## [2.1] — 2026-04-27 Comprehensive expansion based on a 32-prompt smoke-test gap analysis. PASS rate moved from C-grade (1 PASS / 9 PARTIAL / 22 FAIL) to A-grade (31 PASS / 1 PARTIAL / 0 FAIL). diff --git a/README.md b/README.md index b1c4c76..2b72531 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # claude-osint -> 2 paired Claude skills · **90+ recon modules** · 48 secret-regex patterns · 80+ dorks · 9 read-only credential validators · 27 attack-path templates · 5,500+ lines of structured tradecraft. Drop-in `SKILL.md` files that turn Claude into a god-mode external recon operator for authorized red-team and bug-bounty engagements. +> 2 paired Claude skills · **90+ recon modules** · 48 secret-regex patterns · 80+ dorks · 9 read-only credential validators · 27 attack-path templates · 4,600+ lines of structured tradecraft. Drop-in `SKILL.md` files that turn Claude into a god-mode external recon operator for authorized red-team and bug-bounty engagements. Built by **[ElementalSoul](https://github.com/elementalsouls)** — GenAI Security Research. @@ -12,12 +12,12 @@ Built by **[ElementalSoul](https://github.com/elementalsouls)** — GenAI Securi `claude-osint` is a paired set of skills for the [Claude skills system](https://docs.claude.com/en/docs/claude-code/skills). Each skill is a structured `SKILL.md` file that primes Claude with expert-level methodology for one half of the offensive recon problem: -- **`osint-methodology`** — *how to think.* Strategic + procedural. Asset-graph discipline, severity rubric, time budgeting, identity-fabric mapping, deliverable templates. -- **`offensive-osint`** — *what to reach for.* Tactical arsenal. Probe paths, regexes, payloads, scoring rules, curl one-liners, tool URLs. +- **`osint-methodology`** - *how to think.* Strategic + procedural. Asset-graph discipline, severity rubric, time budgeting, identity-fabric mapping, deliverable templates. +- **`offensive-osint`** - *what to reach for.* Tactical arsenal. Probe paths, regexes, payloads, scoring rules, curl one-liners, tool URLs. Drop both into your Claude environment and it behaves like a senior recon analyst: it knows the techniques, the tooling, the edge cases, and the escalation paths — and it stays in scope. -~5,500 lines of structured tradecraft · 96.9% PASS on a 32-prompt self-evaluation · ~85–90% practitioner coverage for the recon phase of authorized engagements. +~4,600 lines of structured tradecraft · 96.9% PASS on a 32-prompt self-evaluation · ~85–90% practitioner coverage for the recon phase of authorized engagements. --- @@ -26,14 +26,15 @@ Drop both into your Claude environment and it behaves like a senior recon analys ``` claude-osint/ ├── skills/ -│ ├── osint-methodology/SKILL.md # how to think (1,694 lines) +│ ├── osint-methodology/SKILL.md # how to think (455 lines) │ └── offensive-osint/ │ ├── SKILL.md # what to reach for (4,168 lines) -│ └── scripts/secret_scan.py # stdlib-only secret scanner +│ ├── scripts/secret_scan.py # stdlib-only secret scanner +│ └── scripts/h1_reference.py # HackerOne disclosed-reports reference agent ├── docs/ # architecture · coverage · install · usage ├── examples/ # 4 end-to-end engagement walk-throughs ├── tests/smoke-test-prompts.md # 32-prompt self-evaluation -└── assets/banner.svg +└── assets/banner.png ``` Each skill directory is self-contained. Drop into `~/.claude/skills/` and Claude auto-triggers on relevant phrases. @@ -105,6 +106,7 @@ Each skill directory is self-contained. Drop into `~/.claude/skills/` and Claude | 9 read-only credential validators (Postman / AWS / GitHub / Slack / Anthropic / OpenAI / npm / Atlassian / DataDog) | arsenal | | Post-discovery enumeration workflows (IAM enum · repo enum · workspace enum · JWT triage) | arsenal | | `secret_scan.py` runnable helper (stdlib-only, JSONL output) | arsenal | +| `h1_reference.py` — HackerOne disclosed-reports reference agent (no API key, top-voted / top-bounty / keyword / program filter) | arsenal | | 80+ dork corpus across 9 categories | arsenal | ### Breach Intelligence @@ -315,12 +317,22 @@ Both skills include a soft scope-check when you ask Claude to act against an unv ## About -Operational tradecraft accumulated across external attack-surface engagements, codified into Claude skills. Engagement-platform agnostic — slot into any ASM / ticketing / asset-graph platform you already use, or none. +Operational tradecraft accumulated across external attack-surface engagements, codified into Claude skills. Engagement-platform agnostic - slot into any ASM / ticketing / asset-graph platform you already use, or none. **Author:** [ElementalSoul](https://github.com/elementalsouls) + **Original framework:** [SnailSploit/offensive-checklist](https://github.com/SnailSploit/offensive-checklist) (v1.x) -**Inspired by:** [Bellingcat's Online Investigations Toolkit](https://www.bellingcat.com/resources/2024/09/24/bellingcat-online-investigations-toolkit/) · [IntelTechniques](https://inteltechniques.com/tools/) · [OSINT Framework](https://osintframework.com/) -**Tool inventory:** [ProjectDiscovery](https://github.com/projectdiscovery) · [Six2dez reconftw](https://github.com/six2dez/reconftw) · [SecLists](https://github.com/danielmiessler/SecLists) · [Assetnote Wordlists](https://wordlists.assetnote.io/) + +**Inspired by:** [Bellingcat's Online Investigations Toolkit](https://www.bellingcat.com/resources/2024/09/24/bellingcat-online-investigations-toolkit/) +· [IntelTechniques](https://inteltechniques.com/tools/) +· [OSINT Framework](https://osintframework.com/) + +**Tool inventory:** +. [ProjectDiscovery](https://github.com/projectdiscovery) +· [Six2dez reconftw](https://github.com/six2dez/reconftw) +· [SecLists](https://github.com/danielmiessler/SecLists) +· [Assetnote Wordlists](https://wordlists.assetnote.io/) + **License:** [MIT](LICENSE) — use freely, attribution appreciated. --- diff --git a/skills/offensive-osint/SKILL.md b/skills/offensive-osint/SKILL.md index 62888fa..8e02bd4 100644 --- a/skills/offensive-osint/SKILL.md +++ b/skills/offensive-osint/SKILL.md @@ -124,6 +124,12 @@ triggers: - Teams federation - SharePoint enum - OneDrive enum + - hackerone reference + - h1 hacktivity + - disclosed reports + - community bug reports + - prior disclosures + - bug bounty reference --- # Offensive OSINT — External Red-Team Arsenal @@ -1672,7 +1678,7 @@ puredns resolve <(awk -v d="$D" '{print $1"."d}' assetnote-best-dns-wordlist.txt - For `staging.*` / `dev.*` / `uat.*` → seed for §16.5 always-on HTTP checks (often weaker auth + debug endpoints). - For `intranet.*` / `eapps.*` / `sclepro.*` → public-intranet finding (often MEDIUM; per §40). -**Real-engagement validation:** in the `shreecement.com` smoke test, prefix-sweep found `vpn.`, `api.`, `intranet.`, `staging.`, `support.`, `eapps.`, `sclepro.`, `autodiscover.` — all of which crt.sh missed (or returned 502 for). Treat passive + active as **complementary, not alternatives**. +**Real-engagement validation:** in an internal smoke test, prefix-sweep found `vpn.`, `api.`, `intranet.`, `staging.`, `support.`, `eapps.`, `sclepro.`, `autodiscover.` — all of which crt.sh missed (or returned 502 for). Treat passive + active as **complementary, not alternatives**. --- @@ -3069,6 +3075,45 @@ while IFS= read -r CVE; do echo "$CVE | EPSS:$EPSS | $KEV_FLAG" done < cves.txt | sort -t: -k2 -nr +### 29.3 HackerOne Disclosed Reports Reference + +Use `skills/offensive-osint/scripts/h1_reference.py` (no API key required, public GraphQL) to pull community-validated findings as reference while testing. Run it at session start for the target's tech stack or attack type. + +**Key modes:** +```bash +# Top voted community reports — best validated techniques +python3 skills/offensive-osint/scripts/h1_reference.py --top-voted --limit 25 + +# Highest bounty reports — business-impact framing reference +python3 skills/offensive-osint/scripts/h1_reference.py --top-bounty --limit 10 + +# Keyword search across pages (50 results/page) +python3 skills/offensive-osint/scripts/h1_reference.py --top-voted --query "SSRF" --pages 10 +python3 skills/offensive-osint/scripts/h1_reference.py --top-voted --query "auth bypass|OAuth|OIDC" --pages 5 +python3 skills/offensive-osint/scripts/h1_reference.py --top-voted --query "open redirect" --pages 5 + +# Filter by severity (client-side) +python3 skills/offensive-osint/scripts/h1_reference.py --top-bounty --severity critical high --pages 3 + +# Program-specific disclosures (requires program handle) +python3 skills/offensive-osint/scripts/h1_reference.py --program taxact --pages 5 +python3 skills/offensive-osint/scripts/h1_reference.py --lookup-program taxact # resolve handle → team ID + +# JSON output for piping / jq +python3 skills/offensive-osint/scripts/h1_reference.py --top-voted --query "XSS" --pages 5 --json | jq '.[].report.url' +``` + +**When to run:** +- At session start: `--top-voted` to load high-signal baseline +- After identifying target's tech stack: `--query "" --pages 10` +- Before probing a specific attack class: `--query "SSRF|XXE|SSTI" --pages 5` +- For report writing: `--query "" --top-bounty` to find comparable severity/bounty + +**H1 GraphQL quirks (documented):** +- Max 50 results/page regardless of `first:` value — use `--pages` for breadth +- `disclosed_at` field crashes H1 server when combined with substate filter — omitted +- Sort + substate filter combo crashes — script auto-routes around this + --- ## 30. Cryptocurrency OSINT @@ -4162,7 +4207,7 @@ Drop these prompts into a fresh Claude session to verify the skill loads correct ## 50. Changelog -- **v2.1.1 (2026-04-27)** — battle-test gap fixes from real-engagement smoke run on `shreecement.com`. Added: §15.0.1 HudsonRock Cavalier direct-API recipe (curl + PowerShell, full JSON shape, free-tier redaction caveats, rate-limit guidance). §15.2 expanded with legacy-mail-decommissioned escalation pattern (NXDOMAIN legacy mail + breach corpus + autodiscover-confirmed cloud migration → CRITICAL SSO_EXPOSURE). §16.14 expanded with DMARC reporting-vendor table (Kratikal kdmarc / dmarcian / Valimail / Agari / EasyDMARC / DMARC Analyzer / Postmark) + full Windows/PowerShell parallel for the entire email security audit + caveat that PS 5.1 `Resolve-DnsName -Type CAA` errors (use PS 7+ or `nslookup -type=CAA`). §16.22 expanded TXT verification token catalog with 17 new tokens (zscaler-verification, cloudflare-verify, autosect, cisco-site-verification, mscid, _amazonses, salesforce-domain-verification, workday/shopify/klaviyo/mailchimp/hubspot/zendesk/freshworks/intercom/loom/miro/gitlab) + new "Autodiscover-as-confirmation" pattern for M365 detection when MX is wrapped by Mimecast/Proofpoint/Barracuda. §22.1 added passive Autodiscover IP correlation pattern with Microsoft Exchange Online IP ranges. §22.8 added clarification: SharePoint HEAD HTTP 200 = tenant exists, NOT anonymous access granted (operators commonly misread). New §16.23 legacy-app pivot block (when Wayback `*.js` returns empty for brochure-ware sites, pivot to .asp/.php/.jsp/.cfm/.aspx/.json/.xml/.yml/.ini/.conf — with full broad-sweep one-liner). New §16.24 Common-Prefix Subdomain Sweep — formalized active prefix-probe technique with 100+ ordered prefix list, PowerShell + bash + puredns recipes, and real-engagement validation note (passive enum misses 20-40% of high-value subdomains; always pair with active prefix probe). §27.0.1 added crt.sh fallback chain (Censys, CertSpotter, Calidog, Subfinder, OTX, ThreatMiner, URLScan, Anubis-DB) with PowerShell wrapper that retries crt.sh 3× then falls back to Subfinder. §28.1 added Bulk IP→ASN recipes (Cymru bulk WHOIS, RIPEstat, bgp.tools, IPinfo Lite) + caveat that bgpview.io API has aggressive rate limits unsuitable for bulk. §40 severity matrix gained 8 rows: vendor procurement portal exposed + breach corpus hits (HIGH), PII-collection portal over plain HTTP (HIGH), decommissioned legacy mail + breach + cloud migration (CRITICAL), public-facing intranet without VPN (MEDIUM), staging/preprod publicly resolvable (MEDIUM), vpn. resolves but vendor unknown (INFO escalating to HIGH-CRITICAL on KEV match), DMARC RUA → third-party vendor (INFO). §49 self-test expanded from 30 → 40 prompts targeting all new content. +- **v2.1.1 (2026-04-27)** — battle-test gap fixes from real-engagement smoke run. Added: §15.0.1 HudsonRock Cavalier direct-API recipe (curl + PowerShell, full JSON shape, free-tier redaction caveats, rate-limit guidance). §15.2 expanded with legacy-mail-decommissioned escalation pattern (NXDOMAIN legacy mail + breach corpus + autodiscover-confirmed cloud migration → CRITICAL SSO_EXPOSURE). §16.14 expanded with DMARC reporting-vendor table (Kratikal kdmarc / dmarcian / Valimail / Agari / EasyDMARC / DMARC Analyzer / Postmark) + full Windows/PowerShell parallel for the entire email security audit + caveat that PS 5.1 `Resolve-DnsName -Type CAA` errors (use PS 7+ or `nslookup -type=CAA`). §16.22 expanded TXT verification token catalog with 17 new tokens (zscaler-verification, cloudflare-verify, autosect, cisco-site-verification, mscid, _amazonses, salesforce-domain-verification, workday/shopify/klaviyo/mailchimp/hubspot/zendesk/freshworks/intercom/loom/miro/gitlab) + new "Autodiscover-as-confirmation" pattern for M365 detection when MX is wrapped by Mimecast/Proofpoint/Barracuda. §22.1 added passive Autodiscover IP correlation pattern with Microsoft Exchange Online IP ranges. §22.8 added clarification: SharePoint HEAD HTTP 200 = tenant exists, NOT anonymous access granted (operators commonly misread). New §16.23 legacy-app pivot block (when Wayback `*.js` returns empty for brochure-ware sites, pivot to .asp/.php/.jsp/.cfm/.aspx/.json/.xml/.yml/.ini/.conf — with full broad-sweep one-liner). New §16.24 Common-Prefix Subdomain Sweep — formalized active prefix-probe technique with 100+ ordered prefix list, PowerShell + bash + puredns recipes, and real-engagement validation note (passive enum misses 20-40% of high-value subdomains; always pair with active prefix probe). §27.0.1 added crt.sh fallback chain (Censys, CertSpotter, Calidog, Subfinder, OTX, ThreatMiner, URLScan, Anubis-DB) with PowerShell wrapper that retries crt.sh 3× then falls back to Subfinder. §28.1 added Bulk IP→ASN recipes (Cymru bulk WHOIS, RIPEstat, bgp.tools, IPinfo Lite) + caveat that bgpview.io API has aggressive rate limits unsuitable for bulk. §40 severity matrix gained 8 rows: vendor procurement portal exposed + breach corpus hits (HIGH), PII-collection portal over plain HTTP (HIGH), decommissioned legacy mail + breach + cloud migration (CRITICAL), public-facing intranet without VPN (MEDIUM), staging/preprod publicly resolvable (MEDIUM), vpn. resolves but vendor unknown (INFO escalating to HIGH-CRITICAL on KEV match), DMARC RUA → third-party vendor (INFO). §49 self-test expanded from 30 → 40 prompts targeting all new content. - **v2.1 (2026-04-27)** — comprehensive expansion based on 32-test smoke-test gap analysis. Added: copy-paste curl probes for every check (§16.13), email security analysis with SPF/DMARC/DKIM/BIMI/MTA-STS/DNSSEC parsing + SaaS tenant inference (§16.14), origin discovery / CDN bypass via DNS history + cert SAN + favicon hash + JARM + Host-header probe (§16.15), vendor product fingerprints for Citrix/F5/Pulse/Fortinet/PaloAlto/Cisco/VMware/Exchange + KEV CVE associations (§16.16), cloud-native service URL fingerprints — Lambda Function URLs, Cloud Run, Cloud Functions, Azure Functions, Vercel, Netlify, Cloudflare Workers, etc. (§16.17), container & Kubernetes exposure (kubelet, etcd, K8s API, dashboard, Helm Tiller, container registries) (§16.18), CI/CD platform exposure (Jenkins deeper, GitLab, GitHub Actions, CircleCI, TeamCity, Argo CD, Spinnaker) (§16.19), documentation/wiki leak paths (Notion, Confluence, Trello, Miro, Lucidchart, Figma, ReadTheDocs, GitBook, Slab, Coda, etc.) (§16.20), WHOIS/RDAP/historical-WHOIS recipes + reverse-WHOIS pivots (§16.21), DNS record catalog with TXT verification token table → SaaS tenant inference (§16.22), Wayback CDX deep usage with all filter parameters (§16.23). Expanded: §17 secret catalog from 29 → 48 patterns adding modern AI API keys (Anthropic, OpenAI legacy + project, HuggingFace), infra (Cloudflare, DigitalOcean), package registries (npm, PyPI, Docker Hub), SaaS (Atlassian, Linear), observability (New Relic, DataDog, Sentry DSN), bot tokens (Discord, Telegram), and ngrok. Expanded §18 dork corpus from 50+ → 80+ with internal-tool exposure (Splunk/Grafana/Kibana/Argo CD/Sonarqube/Confluence/Jira/GitLab/Gitea), backup-file extensions, and sector-specific dorks (healthcare/finance/gov). Added §22.8 Microsoft 365 deep enumeration (Teams federation, SharePoint subdomain probe, OneDrive personal-site probe, OAuth client_id discovery, device-code phishing target check, Power Platform). Added §22.9 GraphQL field-suggestion enumeration recipe + alias batching, query-depth bypass, subscription enumeration, batched-query bypass. Added §23.5–23.9 read-only validators for Anthropic, OpenAI, npm, Atlassian, DataDog (5 new). Added §23.12 post-discovery enumeration workflows (AWS IAM enum, GitHub PAT scope/repo enum, Slack workspace enum, JWT full triage with algorithm-confusion + brute-force + none-bypass, Postman PMAK workspace enum, Anthropic + OpenAI usage enum, generic key provenance enum). Pinned §24 Postman search endpoint with verified shape + DevTools fallback recipe. Added §27.1 wordlist sources (Assetnote, SecLists, jhaddix, OneListForAll, raft-large-words, fuzzdb, etc.) + size guidance. Added §28.4 TLS deep audit (sslyze + testssl.sh + nmap + JA3/JA4 + cipher/protocol/cert checks). Added §28.5 reverse DNS sweep + IPv6 enumeration + BGP route observation. Added §29.2 vulnerability prioritization data sources (NVD/EPSS/CISA KEV/ExploitDB/Metasploit/InTheWild/OpenCVE/Trickest CVE+POC mapping/OSV.dev/VulnCheck KEV) + bulk prioritization workflow. Expanded §39 attack-path hints with 15 more templates (open kubelet/etcd, K8s API anonymous, Citrix/F5/vCenter/Cloud Function unauth, npm typosquat, DMARC missing, live AI keys, Slack invite, sourcemap with sourcesContent). Expanded §40 severity matrix with 30 more worked examples covering Kubernetes/container, vendor products with KEV CVEs, M365/cloud-native, CI/CD misconfig, documentation leaks, email-security gaps, AI/package-registry credentials, TLS issues. Added §41 LinkedIn employee enumeration tradecraft (search techniques + role inference + email-pattern derivation + sock-puppet considerations). Added §42 job posting tech-stack analysis (sources + extraction + tooling). Added §43 Slack/Discord/Telegram/Mattermost workspace discovery. Added §44 package registry leak hunting (npm/PyPI/RubyGems/Cargo/Packagist/NuGet/Maven Central + workflow + typosquat surveillance). Added §45 sat imagery for physical recon (sources + extraction + LinkedIn/Glassdoor/Instagram/conference intel + vehicle/fleet intel). Added §46 tooling quick-install (subdomain, HTTP probing, vuln scanning, content discovery, JS extraction, Wayback, cloud, identity, mobile, TLS, utilities, frameworks). Added §47 sector-specific recon notes (healthcare DICOM/HL7/FHIR/EHR + finance SWIFT/FIX/Bloomberg/banking middleware + ICS-SCADA Modbus/BACnet/S7/DNP3 + IoT MQTT/CoAP/UPnP + government FedRAMP/FISMA + maritime/aviation/auto). Renumbered Runnable Helper → §48, Self-Test → §49 (refreshed for v2.1), Changelog → §50. - **v2.0 (2026-04-27)** — major rewrite for external red-team posture. Added: pre-built wordlists (§16), 29-pattern secret catalog (§17), 50+ dork corpus (§18), GitHub code-search dorks (§19), endpoint interest score (§20), mobile ownership confidence (§21), identity-fabric concrete endpoints (§22), read-only secret validators (§23), Postman workspace search (§24), Stack Exchange sweep (§25), public SaaS dorks (§26), subdomain-source stack (§27), domain-level breach severity (§15.1), L2 explorer table (§30.2), USCC + ICP workflow (§14.2), cross-module sidecar coordination (§36), attack-path hint patterns (§39), severity decision matrix (§40), runnable secret-scan helper (§41). Strengthened: confidence levels (§2), output format (§3), do-not rules (§5). Original tool tables retained and lightly reorganized. - **v1.x** — original tool-reference cheat sheet. diff --git a/skills/offensive-osint/scripts/h1_reference.py b/skills/offensive-osint/scripts/h1_reference.py new file mode 100755 index 0000000..00ee6e9 --- /dev/null +++ b/skills/offensive-osint/scripts/h1_reference.py @@ -0,0 +1,378 @@ +#!/usr/bin/env python3 +""" +h1_reference.py — HackerOne Hacktivity Reference Agent + +Queries HackerOne's public GraphQL API for disclosed reports and surfaces +relevant findings during recon. No API key required. Max 50 results/page. + +Usage examples: + # Top voted reports (best validated techniques — great starting point) + python3 h1_reference.py --top-voted --limit 25 + + # Highest bounty reports (signal for business-impact framing) + python3 h1_reference.py --top-bounty --limit 10 + + # Keyword search in titles across multiple pages + python3 h1_reference.py --query "SSRF" --pages 10 + python3 h1_reference.py --query "OAuth bypass" --pages 5 + + # Filter by severity (client-side) + python3 h1_reference.py --top-voted --severity critical high --limit 20 + + # Filter by CWE (client-side, matches CWE label substring) + python3 h1_reference.py --top-voted --cwe "SSRF" "Request Forgery" + + # Program-specific disclosures + python3 h1_reference.py --program shopify --pages 3 + + # Lookup a program's numeric team ID + python3 h1_reference.py --lookup-program taxact + + # Full combo: top-bounty SSRF reports, critical/high only + python3 h1_reference.py --top-bounty --query "SSRF" --severity critical high --pages 10 + + # JSON output for piping + python3 h1_reference.py --top-voted --query "XSS" --pages 5 --json +""" + +import argparse +import base64 +import json +import sys +import re +import time +import urllib.request +import urllib.error +from typing import Optional + +GRAPHQL_URL = "https://hackerone.com/graphql" +HEADERS = { + "Content-Type": "application/json", + "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36", + "Origin": "https://hackerone.com", + "Referer": "https://hackerone.com/hacktivity", +} +PAGE_SIZE = 50 + +# HackerOne's GraphQL server crashes on named variables + substate filter + report fields. +# We build inline query strings to avoid this. Additional known crashes: +# - disclosed_at field with substate filter +# - sort + substate filter + report fields +REPORT_FIELDS = """... on HacktivityDocument { + id + severity_rating + total_awarded_amount + currency + cwe + cve_ids + votes + team { handle name } + reporter { username } + report { _id title url } +}""" + +TEAM_LOOKUP_QUERY = """ +query TeamLookup($handle: String!) { + team(handle: $handle) { + id + _id + handle + name + url + } +} +""" + + +def _escape(s: str) -> str: + return s.replace("\\", "\\\\").replace('"', '\\"') + + +def _gql_list(items: list) -> str: + return "[" + ", ".join(f'"{_escape(str(i))}"' for i in items) + "]" + + +def _offset_cursor(n: int) -> str: + """H1 uses base64(str(n)) as cursor offsets.""" + return base64.b64encode(str(n).encode()).decode() + + +def gql_raw(query: str) -> dict: + payload = json.dumps({"query": query}).encode() + req = urllib.request.Request(GRAPHQL_URL, data=payload, headers=HEADERS, method="POST") + try: + with urllib.request.urlopen(req, timeout=20) as resp: + return json.loads(resp.read()) + except urllib.error.HTTPError as e: + body = e.read().decode(errors="replace") + print(f"[!] HTTP {e.code}: {body[:300]}", file=sys.stderr) + sys.exit(1) + except Exception as e: + print(f"[!] Request failed: {e}", file=sys.stderr) + sys.exit(1) + + +def gql_vars(query: str, variables: dict) -> dict: + payload = json.dumps({"query": query, "variables": variables}).encode() + req = urllib.request.Request(GRAPHQL_URL, data=payload, headers=HEADERS, method="POST") + try: + with urllib.request.urlopen(req, timeout=20) as resp: + return json.loads(resp.read()) + except urllib.error.HTTPError as e: + body = e.read().decode(errors="replace") + print(f"[!] HTTP {e.code}: {body[:300]}", file=sys.stderr) + sys.exit(1) + except Exception as e: + print(f"[!] Request failed: {e}", file=sys.stderr) + sys.exit(1) + + +def lookup_program(handle: str) -> Optional[str]: + data = gql_vars(TEAM_LOOKUP_QUERY, {"handle": handle}) + team = data.get("data", {}).get("team") + if not team: + print(f"[!] Program '{handle}' not found or is private", file=sys.stderr) + return None + print(f"[+] {team['handle']} → id={team['_id']}, name={team['name']}") + return team["_id"] + + +def build_page_query(args, after: Optional[str] = None) -> str: + """ + Build an inline GraphQL query for one page of results. + + H1 crash rules (discovered empirically): + - substate filter + sort + report fields → CRASH + - disclosed_at field + substate filter → CRASH + - named variables + substate filter + report fields → CRASH + + Strategy: + - Pure sort (no --program): no substate filter, sort works fine + - Program filter: substate filter, no sort, client-side sort + """ + has_sort = args.top_voted or args.top_bounty + has_program = bool(args.program_id) + + after_str = f', after: "{_escape(after)}"' if after else "" + + if has_sort and not has_program: + # Sort-only mode: no substate filter, works without crashing + sort_field = "votes" if args.top_voted else "total_awarded_amount" + return ( + f'{{ search(index: CompleteHacktivityReportIndex, query: {{bool: {{}}}}, ' + f'first: {PAGE_SIZE}{after_str}, sort: {{field: "{sort_field}", direction: DESC}}) ' + f'{{ total_count pageInfo {{ endCursor }} nodes {{ {REPORT_FIELDS} }} }} }}' + ) + else: + # Filter mode: substate + optional team filter, no sort + filter_parts = ['terms: {substate: ["resolved"]}'] + if has_program: + filter_parts.append(f'terms: {{team_id: ["{_escape(str(args.program_id))}"]}}') + filter_str = ", ".join(f"{{{p}}}" for p in filter_parts) + return ( + f'{{ search(index: CompleteHacktivityReportIndex, ' + f'query: {{bool: {{filter: [{filter_str}]}}}}, ' + f'first: {PAGE_SIZE}{after_str}) ' + f'{{ total_count pageInfo {{ endCursor }} nodes {{ {REPORT_FIELDS} }} }} }}' + ) + + +def fetch_all_pages(args) -> list[dict]: + """Fetch up to args.pages pages from the H1 GraphQL API.""" + all_nodes: list[dict] = [] + cursor = None + + for page_num in range(1, args.pages + 1): + if page_num > 1: + time.sleep(0.3) # polite rate limiting + + query = build_page_query(args, after=cursor) + data = gql_raw(query) + + if "errors" in data or data.get("data") is None: + for err in (data.get("errors") or []): + print(f"[!] GraphQL error (page {page_num}): {err.get('message')}", file=sys.stderr) + break + + search = data["data"]["search"] + nodes = search.get("nodes", []) + all_nodes.extend(nodes) + cursor = search.get("pageInfo", {}).get("endCursor") + + if not nodes or not cursor: + break + + # Stop early if we already have enough matches (when keyword filtering) + if not args.query and not args.severity and not args.cwe: + matching = len([n for n in all_nodes if n.get("report")]) + if matching >= args.limit: + break + + return all_nodes + + +def apply_client_filters(nodes: list[dict], args) -> list[dict]: + keyword_pattern = re.compile(args.query, re.IGNORECASE) if args.query else None + severity_set = set(s.lower() for s in args.severity) if args.severity else None + cwe_patterns = [re.compile(c, re.IGNORECASE) for c in args.cwe] if args.cwe else [] + + results = [] + for node in nodes: + report = node.get("report") + if not report: + continue + + title = report.get("title", "") + + if keyword_pattern and not keyword_pattern.search(title): + continue + + if severity_set: + node_sev = (node.get("severity_rating") or "none").lower() + if node_sev not in severity_set: + continue + + if cwe_patterns: + node_cwe = node.get("cwe") or "" + if not any(p.search(node_cwe) for p in cwe_patterns): + continue + + results.append(node) + + return results + + +def client_sort(results: list[dict], args) -> list[dict]: + """Apply client-side sort when server-side sort was skipped (filter mode).""" + has_sort = args.top_voted or args.top_bounty + has_program = bool(args.program_id) + + if has_sort and has_program: + key = "votes" if args.top_voted else "total_awarded_amount" + results = sorted(results, key=lambda n: n.get(key) or 0, reverse=True) + + return results + + +def format_severity(s: Optional[str]) -> str: + if not s: + return "none" + colors = { + "critical": "\033[91m", + "high": "\033[33m", + "medium": "\033[93m", + "low": "\033[32m", + "none": "\033[37m", + } + reset = "\033[0m" + c = colors.get(s.lower(), "") + return f"{c}{s.upper()}{reset}" + + +def print_results(results: list[dict], total_fetched: int, args): + if not results: + print("[*] No matching results found.") + return + + print(f"\n{'='*72}") + label_parts = [] + if args.top_voted: + label_parts.append("top voted") + if args.top_bounty: + label_parts.append("top bounty") + if args.query: + label_parts.append(f'keyword="{args.query}"') + if args.severity: + label_parts.append(f"severity={','.join(args.severity)}") + if args.program: + label_parts.append(f"program={args.program}") + label = " | ".join(label_parts) if label_parts else "all disclosed" + print(f" HackerOne Reference — {label}") + print(f" {len(results)} matches from {total_fetched} fetched reports") + print(f"{'='*72}\n") + + for i, node in enumerate(results[: args.limit], 1): + report = node.get("report", {}) or {} + team = node.get("team", {}) or {} + reporter = node.get("reporter", {}) or {} + + title = report.get("title", "Unknown") + url = report.get("url", "") + severity = format_severity(node.get("severity_rating")) + cwe = node.get("cwe") or "" + cves = ", ".join(node.get("cve_ids") or []) + bounty = node.get("total_awarded_amount") + currency = node.get("currency") or "USD" + votes = node.get("votes") or 0 + program = team.get("handle", "?") + reporter_name = reporter.get("username", "?") + + bounty_str = f"${bounty:,} {currency}" if bounty else "no bounty" + + print(f"[{i:02d}] {title}") + print(f" Severity : {severity} | CWE: {cwe or 'n/a'}") + print(f" Program : {program} | Reporter: {reporter_name}") + if cves: + print(f" CVE : {cves}") + print(f" Bounty : {bounty_str} | Votes: {votes}") + print(f" URL : {url}") + print() + + +def main(): + parser = argparse.ArgumentParser( + description="HackerOne Hacktivity Reference Agent — surface relevant disclosures during recon", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=__doc__, + ) + parser.add_argument("--query", "-q", help="Keyword regex to match in report titles (client-side)") + parser.add_argument( + "--severity", "-s", + nargs="+", + choices=["none", "low", "medium", "high", "critical"], + metavar="LEVEL", + help="Client-side severity filter: none low medium high critical", + ) + parser.add_argument( + "--cwe", + nargs="+", + metavar="PATTERN", + help="Client-side CWE label filter (regex, e.g. 'SSRF' 'Traversal')", + ) + parser.add_argument("--program", "-p", metavar="HANDLE", help="Filter by program handle") + parser.add_argument("--lookup-program", metavar="HANDLE", help="Resolve a program handle to its numeric ID and exit") + parser.add_argument("--top-voted", action="store_true", help="Sort by community votes (validated techniques)") + parser.add_argument("--top-bounty", action="store_true", help="Sort by bounty amount (impact framing reference)") + parser.add_argument("--limit", "-n", type=int, default=20, help="Max results to display (default: 20)") + parser.add_argument( + "--pages", + type=int, + default=1, + help="Number of pages to fetch (50 results/page, default: 1). Use 5-20 for keyword searches.", + ) + parser.add_argument("--json", action="store_true", help="Output raw JSON instead of formatted text") + + args = parser.parse_args() + + if args.lookup_program: + lookup_program(args.lookup_program) + return + + args.program_id = None + if args.program: + args.program_id = lookup_program(args.program) + if not args.program_id: + sys.exit(1) + + nodes = fetch_all_pages(args) + results = apply_client_filters(nodes, args) + results = client_sort(results, args) + + if args.json: + print(json.dumps(results[: args.limit], indent=2)) + else: + print_results(results, len(nodes), args) + + +if __name__ == "__main__": + main() diff --git a/skills/osint-methodology/SKILL.md b/skills/osint-methodology/SKILL.md index 3187b53..8880249 100644 --- a/skills/osint-methodology/SKILL.md +++ b/skills/osint-methodology/SKILL.md @@ -1,7 +1,7 @@ --- name: osint-methodology -description: "Comprehensive OSINT methodology for external red-team operations and authorized attack-surface assessments. Covers the 5-stage recon pipeline (seed discovery, asset expansion, enrichment, exposure analysis, reporting), asset-graph discipline with 29 asset types, severity rubric (CRITICAL/HIGH/MEDIUM/LOW/INFO), confidence upgrade workflows, time budgeting, asset-level triage rules, scale-based tactics, identity-fabric mapping (Entra/Okta/ADFS/Google/SAML/M365 Teams+SharePoint+OAuth), API and auth-map methodology, JavaScript deep analysis, mobile attack surface, cloud attack surface, breach×identity correlation, detectability tagging, detection-aware probing (back-off, persona rotation), read-only validator discipline, WAF/CDN bypass + origin discovery, vulnerability prioritization (CVE/EPSS/KEV), phishing infrastructure planning + pretext development, bug bounty submission templates, client deliverable templates with risk translation, threat-actor investigation (incl. RU/CN pivots), cryptocurrency tracing, image/video forensics, chronolocation. Use when planning or executing reconnaissance against authorized targets, mapping an organization's external attack surface, investigating a person/entity, tracing crypto flows, geolocating media, or performing attribution work." -version: 2.1 +description: "Comprehensive OSINT methodology for external red-team operations and authorized attack-surface assessments. Covers the 5-stage recon pipeline, asset-graph discipline, severity rubric, confidence upgrade workflows, time budgeting, identity-fabric mapping, breach×identity correlation, detectability tagging, detection-aware probing, WAF/CDN bypass, vulnerability prioritization, phishing infrastructure planning, bug bounty submission, and client deliverable templates. Use when planning or executing reconnaissance against authorized targets, mapping an organization's external attack surface, investigating a person/entity, or producing client deliverables." +version: 2.2 triggers: - external recon - external red team @@ -26,7 +26,6 @@ triggers: - mobile recon - APK analysis - cloud bucket enumeration - - bucket enum - breach correlation - secret leak hunt - origin discovery @@ -49,14 +48,10 @@ triggers: - asset triage - detection-aware probing - back-off strategy - - persona rotation - OSINT methodology - open source intelligence - target profiling - - data correlation - OSINT workflow - - intelligence collection - - OSINT campaign - recon methodology - threat actor investigation - attribution @@ -64,129 +59,107 @@ triggers: # OSINT Methodology — External Red-Team Edition -## 0. When to use this skill / When NOT +## 0. When to Use / When NOT -**Use this skill when:** -- Planning or executing external reconnaissance against an authorized target (red team, bug bounty in-scope, ASM engagement). -- Mapping an organization's external attack surface end-to-end (subdomains → assets → exposure → attack paths). -- Investigating a person, entity, or threat actor where evidence discipline matters. -- Tracing cryptocurrency flows, geolocating media, performing image/video forensics, or chronolocating events. -- Building a structured OSINT campaign that needs reproducibility, severity grading, and clean handoffs. -- Producing client-facing deliverables (exec summaries, technical reports, reproduction packages) from offensive engagements. +**Use this skill when:** planning or executing authorized external recon (red team, bug bounty, ASM); mapping an org's attack surface; investigating a person/entity/threat-actor; producing client deliverables. -**Do NOT use this skill when:** -- The user is asking for active exploitation, post-exploitation, lateral movement, AD privilege escalation, malware development, or anything beyond reconnaissance — those are out of scope. -- The user is asking for blue-team / defensive content (SIEM rules, detection engineering) — different domain. -- The target's authorization is unclear and the user is asking you to act against a third-party asset they don't own — see §1 below; gently surface the scope question before proceeding. +**Do NOT use this skill when:** the user needs active exploitation, post-exploitation, or malware dev; blue-team/detection content; or the target's authorization is unclear — surface the scope question first. --- ## 1. Authorization & Legal Posture -This skill is intended for assets the operator owns or has written authorization to assess (red-team rules of engagement, bug-bounty in-scope assets, ASM contracts). +Intended for assets the operator owns or has **written authorization** to assess. -**Soft scope check:** when a user asks you to act against a target whose authorization isn't established earlier in the conversation, ask once before proceeding: +**Soft scope check** — when authorization isn't established, ask once: +> *"Quick scope check: is this a target you own or have written authorization to assess? I want to make sure we stay on the right side of the engagement boundary."* -> *"Quick scope check: is this a target you own or have written authorization to assess (e.g., a red-team engagement, in-scope bug-bounty asset, or your own infrastructure)? I want to make sure we stay on the right side of the engagement boundary."* +Once asserted, don't re-ask. If the engagement type is stated ("pentest of acme.com under contract"), proceed. -Once authorization is asserted, proceed without re-asking. If the user explicitly states the engagement type (e.g., "this is for our pentest of acme.com under contract"), you don't need to ask again. - -**Always-on guardrails (regardless of authorization):** -- Never weaken auth, rate limits, banners, or any safety control that enforces scope on the target side. -- Never run destructive probes (true SYN scans on production, masscan at line rate, fuzzing/brute-force) outside an explicit DEEP / `--aggressive` mode. -- Never paste real PII, valid credentials, session tokens, API keys, or other secrets into cloud-hosted LLMs or third-party services. -- Never take action against assets outside the documented scope, even if "obviously related" (subsidiaries, vendors, employees' personal accounts, etc.). +**Always-on guardrails:** +- Never weaken auth, rate limits, or safety controls on the target side. +- No destructive probes (SYN scans at line-rate, masscan, fuzzing) outside explicit `--aggressive` mode. +- Never paste real PII, credentials, session tokens, or API keys into cloud-hosted LLMs. +- Never act against assets outside documented scope, even "obviously related" ones. --- ## 2. Confidence Levels -Every assertion you make during an engagement should carry a confidence level. Three levels: +Every assertion carries a confidence level. -| Level | Meaning | Examples | -|---|---|---| -| **TENTATIVE** | Plausible based on indirect evidence; unverified. | Snippet-only Google dork match; email pattern inferred from name; subdomain returned by one passive source only; favicon-hash overlap (two hosts share a favicon — could be shared infra, could be a coincidence). | -| **FIRM** | Directly observed but uncorroborated. | Subdomain that resolves to an IP; HEAD-confirmed bucket exists (private); CT-log entry shows certificate; Shodan banner returned. | -| **CONFIRMED** | Multiple independent corroborations OR directly verified. | Live-validated PMAK token (read-only `/me` returned 200); breach corpus + crt.sh + DNS all agree; bucket listable AND files retrievable; user enumerated AND password reset flow returns valid hint. | +| Level | Meaning | +|---|---| +| **TENTATIVE** | Plausible from indirect evidence; unverified. Snippet-only dork match, email pattern inferred from name, single passive-source subdomain. | +| **FIRM** | Directly observed, uncorroborated. Subdomain resolves; Shodan banner returned; CT-log entry. | +| **CONFIRMED** | Multiple independent corroborations OR directly verified. Live-validated token; bucket listable; three-source subdomain convergence. | -**Rule of three for attribution:** require three independent weak signals, OR one strong + one weak, before asserting linkage. Don't single-source attribute. +**Rule of three for attribution:** 3 independent weak signals, OR 1 strong + 1 weak. Never single-source attribute. ### 2.1 Confidence Upgrade Workflows -Confidence isn't static — every TENTATIVE asset should have a documented path to FIRM and to CONFIRMED. Use these per-asset-type rules. - | Asset type | TENTATIVE → FIRM | FIRM → CONFIRMED | |---|---|---| -| **Subdomain** | Returned by ≥2 independent passive sources, OR DNS A/AAAA/CNAME resolves successfully. | Serves on a standard port (80/443/22/etc.) AND HTTP banner / TLS cert / SSH banner returned. | -| **IP** | Discovered via ≥2 sources (passive DNS, ASN lookup, Shodan). | Active probe responds (TCP SYN-ACK on at least one port, or ICMP echo reply). | -| **WebApp** | URL extracted from JS / API / archive but not yet hit. | HTTP request returns 2xx/3xx/4xx (any non-network-error response) AND content-length > 0. | -| **Email** | Generated from a name pattern OR returned by snippet-only dork. | Listed in Hunter.io / EmailRep / IntelX / breach corpus, OR `MAIL FROM`/`RCPT TO` SMTP probe returns 250 (without delivery — abort at DATA). | -| **Bucket (S3/GCS/Azure)** | Permutation candidate; no probe yet. | HEAD returns 200, 301, or 403 (existence confirmed). Then CONFIRMED when GET returns object listing or known object retrieval. | -| **Endpoint (API / wayback)** | Extracted from JS regex / Wayback / Postman. | HTTP request returns non-404 (route exists). Then CONFIRMED when the endpoint's behavior is fingerprinted (auth posture, response shape, rate limits). | -| **Credential / secret** | Matches catalog regex in captured text. | Read-only validator (`/me`, `auth.test`, `sts:GetCallerIdentity`, `/user`) returns success. Then CONFIRMED with documented scope + account ID. | -| **Person** | Name extracted from a single source (LinkedIn / breach / GitHub commit). | Confirmed by a second source (Hunter.io role + LinkedIn profile, or two breach sources with same email). | -| **Repo** | Name match on org keyword in GitHub search. | Repo metadata shows confirmed org/email/website match. Then CONFIRMED when commit-history shows employee involvement. | -| **Mobile app** | Name match in app store. | Ownership-confidence score ≥70 (see companion skill §21). Then CONFIRMED when binary metadata (signing cert, package name, dev account) ties back to target. | -| **Certificate** | Returned by crt.sh once. | CT-log entry confirmed in ≥2 logs. Then CONFIRMED when serving on a discovered host. | -| **SSO tenant** | Discovery-endpoint returns OIDC metadata. | Tenant GUID extracted AND domain resolves through the tenant's expected MX / autodiscover / SP record. | - -**Default reporting posture:** never claim CONFIRMED without explicit corroboration. When in doubt, downgrade. Operators trust under-claims more than over-claims. +| Subdomain | ≥2 passive sources OR DNS resolves | Serves on a standard port AND banner/cert returned | +| IP | ≥2 sources (passive DNS, ASN, Shodan) | TCP SYN-ACK or ICMP reply | +| WebApp | URL extracted but not yet hit | HTTP returns 2xx/3xx/4xx AND content-length > 0 | +| Email | Name-pattern inferred OR snippet-only | Listed in Hunter/IntelX/breach, OR SMTP 250 (abort at DATA) | +| Bucket | Permutation candidate + HEAD returns 200/301/403 (exists) | GET listing = CONFIRMED | +| Credential / secret | Regex match in captured text | Read-only validator returns success (scope + account-ID documented) | +| Person | Name from single source | Confirmed by second independent source | +| SSO tenant | OIDC discovery endpoint returns metadata | Tenant GUID extracted AND domain ties back via MX/autodiscover/SP record | + +Default reporting posture: never claim CONFIRMED without explicit corroboration. When in doubt, downgrade. --- -## 3. Output Format Conventions +## 3. Output Format -When you produce findings during an active session, structure each finding to match the schema below — it drops cleanly into asset-management tools. +Each finding uses this schema (drops cleanly into asset-management tools): ``` Finding: - id: - module: - asset_key: - category: - severity: - confidence: - title: - description: <2-5 sentences> + id: + module: + asset_key: + category: + severity: + confidence: + title: + description: <2-5 sentences> evidence: - url: - timestamp: - sha256: - raw: - references: - - - remediation: + url: + timestamp: + sha256: + raw: + references: [] + remediation: ``` -**Always use UTC timestamps**. Local time creates correlation bugs across notes/screenshots/logs. +Always use UTC timestamps. --- ## 4. Source Hygiene & Citations -For every artifact you capture, record: **URL + UTC timestamp + SHA-256 hash + tool version + run_id**. +For every artifact: **URL + UTC timestamp + SHA-256 + tool version + run_id**. -- Hash all downloaded files with SHA-256. -- Screenshot in PNG (lossless, smaller than full-page WARC for evidence packs). -- Capture raw HTTP requests/responses, capped at 2 KiB body to keep evidence packs small. -- Use JSONL (NDJSON) logs, one line per event, with a `run_id` so the entire engagement is replayable. +- Hash all downloads with SHA-256. Screenshot in PNG. +- Raw HTTP captures capped at 2 KiB body. JSONL logs, one line per event. - Separate evidence read-only from working copies; never edit captured artifacts. - -When citing a source in your output, prefer durable references (CVE, vendor advisory, ATT&CK technique ID, RFC) over ephemeral ones (a Twitter post, a forum thread). If the only source is ephemeral, archive it (archive.today, Wayback SavePageNow) before citing. +- Prefer durable references (CVE, ATT&CK technique ID, RFC). If ephemeral, archive first (archive.today, Wayback SavePageNow). --- -## 5. Do NOT (hard rules) +## 5. Do NOT -- DO NOT paste creds, session tokens, API keys, real PII, infostealer logs, or unique pivots into cloud LLMs (ChatGPT, Claude.ai, Gemini, Perplexity). Use local models (Ollama, LM Studio, GPT4All) for sensitive analysis. -- DO NOT assume vendor labels are ground truth. Cross-label sanity: TRM, Chainalysis, Arkham can disagree. Treat every label as a hypothesis. -- DO NOT assume 1:1 bridge flows. Bridges/mixers/wrappers introduce mint/burn semantics; validate with on-chain proofs. -- DO NOT assert ownership from a single signal. Favicon-hash overlap, shared CT issuer, shared NS — each is a hypothesis. Need rule-of-three. -- DO NOT run fuzzing, SYN scans, masscan, or `nuclei fuzzing/*` templates outside an explicit DEEP / `--aggressive` mode. -- DO NOT use a credential validator to do anything except read-only verification (no create/delete/send). -- DO NOT mirror-image (assume the target thinks like you do). Separate capability from intent and sponsorship. -- DO NOT confuse correlation with control. -- DO NOT escalate when you encounter active defenses; back off and document (see §6.4). +- Do NOT paste creds, session tokens, real PII, or unique pivots into cloud LLMs. Use local models for sensitive analysis. +- Do NOT assume vendor labels are ground truth (TRM, Chainalysis, Arkham can disagree). +- Do NOT assert ownership from a single signal (favicon hash, shared NS, shared CT issuer — each is a hypothesis). +- Do NOT run fuzzing, SYN scans, masscan, or `nuclei fuzzing/*` outside explicit `--aggressive` mode. +- Do NOT use a credential validator for anything except read-only verification. +- Do NOT mirror-image the threat actor. Separate capability from intent and sponsorship. +- Do NOT escalate when you hit active defenses — back off and document (§6.4). --- @@ -194,1500 +167,289 @@ When citing a source in your output, prefer durable references (CVE, vendor advi ### 6.1 Sock Puppets -A sock puppet is a fake account that cannot be linked to you. Build a posting history, age the account, use it from a separate browser profile. +Build posting history, age the account, use a separate browser profile. Persona generation: Fake Name Generator, This Person Does Not Exist. Browser isolation: Firefox Multi-Account Containers. Disposable numbers for SMS verification. Audit every extension before install. Maintain chain-of-custody: timestamp every action, hash every artifact. -Resources & techniques: -- Persona generation: [Fake Name Generator](https://www.fakenamegenerator.com/), [This Person Does Not Exist](https://thispersondoesnotexist.com/). -- Browser isolation: [Firefox Multi-Account Containers](https://addons.mozilla.org/firefox/addon/multi-account-containers/), or dedicated profiles per persona. -- Disposable phone numbers: Burner, Silent Link (some platforms reject VoIP — keep a backlog of numbers). -- Hardware passkeys for any high-value persona; store recovery codes offline. -- Audit every browser extension before installation. Supply-chain attacks on popular extensions have repeatedly targeted investigators — assume the popular ones are at higher risk, not lower. -- Maintain chain-of-custody: timestamp every action, hash every key artifact, record tool versions per case. -- Personas should look like real low-engagement accounts: profile photo (synthetic), bio, a few low-effort posts spread across weeks before the persona is "used." +### 6.2 Detectability Tagging -References: -- [Effective Sock Puppets](https://medium.com/@unseeable06/creating-an-effective-sock-puppet-for-your-osint-investigation-95fdbb8b075a) -- [Ultimate Guide to Sock Puppets](https://osintteam.blog/the-ultimate-guide-to-sockpuppets-in-osint-how-to-create-and-utilize-them-effectively-d088c2ed6e36) - -### 6.2 Detectability & OpSec Tagging - -Every probe leaves a footprint. Tag every operation in your notes with a detectability level so you can reason about the SIEM trail you're leaving on the target's side. +Tag every operation so you can reason about the trail you leave. | Tag | Examples | |---|---| -| **Low** | Passive Shodan InternetDB; CT-log queries (crt.sh); Wayback CDX; passive DNS (SecurityTrails); Hunter.io email enrichment; HTTP HEAD on public buckets; `getuserrealm.srf`; Microsoft OIDC metadata fetch. | -| **Medium** | Microsoft `GetCredentialType` user-enum; Okta `/api/v1/authn` user-enum; Postman API key validation; AWS `sts:GetCallerIdentity` (logs to CloudTrail); Slack `auth.test`; full-page screenshots; Swagger/GraphQL probes against a 28/13-path wordlist; targeted favicon-hash + JARM fingerprinting. | -| **High** | Active port scans (naabu / masscan / nmap); Nuclei full template runs against production; subdomain brute-force at scale; APK download from third-party mirrors; deep-mode user enumeration past N attempts per tenant; SMTP `RCPT TO` enumeration; web fuzzing (ffuf/gobuster). | - -When working with a client, document the operations actually run and their detectability tag in the engagement report — clients appreciate knowing what their detection stack should have caught. +| **Low** | Passive Shodan InternetDB; crt.sh; Wayback CDX; SecurityTrails PDNS; Hunter.io; HTTP HEAD on public buckets; `getuserrealm.srf`; OIDC metadata fetch. | +| **Medium** | `GetCredentialType` user-enum; Okta `/api/v1/authn` user-enum; credential validation; AWS `sts:GetCallerIdentity`; Swagger/GraphQL probes; targeted favicon-hash + JARM fingerprinting. | +| **High** | Active port scans (naabu/masscan/nmap); Nuclei full runs against production; subdomain brute-force at scale; SMTP `RCPT TO` enum; web fuzzing. | -**Defaults:** passive by default. Active probes only when (a) explicitly authorized, (b) within agreed maintenance windows, and (c) with the operator's awareness of the resulting log volume. +Defaults: passive by default. Active probes only when (a) explicitly authorized, (b) within agreed windows, (c) operator aware of log volume. ### 6.3 Validator Discipline -When you discover a credential in the wild (a leaked API key, a sourcemap-exposed token, a hard-coded PMAK in a public Postman workspace), you may want to confirm it's live. Do this with **read-only validators only**. - -Discipline: -- Read-only endpoint only (e.g., `/me`, `/whoami`, `auth.test`, `sts:GetCallerIdentity`). -- Never use the validated credential to create, modify, delete, or send anything. -- Tag the validation attempt with detectability — every validator generates an audit-log entry on the provider side. -- Record `checked_at` (UTC), the response (truncated), and the scope/account-ID returned. -- If the operator's rules of engagement forbid validation, mark the credential `validation_skipped_by_policy` and stop. - -Concrete validator endpoints (Postman, AWS, GitHub, Slack, Anthropic, OpenAI, npm, Atlassian, DataDog) live in the companion `offensive-osint` skill. +When you find a credential in the wild, confirm liveness with **read-only validators only** (`/me`, `auth.test`, `sts:GetCallerIdentity`). Never create, modify, delete, or send. Record `checked_at` UTC + truncated response + scope/account-ID. Concrete validator endpoints for 9 providers live in `offensive-osint` §23. -### 6.4 Detection-Aware Probing (signs of detection + back-off) +### 6.4 Detection-Aware Probing -Your probes will eventually hit detection. Recognize the signs and back off **before** you trip an active response. - -**Signs you've been detected (in roughly increasing severity):** - -1. **Rate-limit responses** — `429 Too Many Requests`, `Retry-After` header set, `X-RateLimit-Remaining: 0`. -2. **Captcha interstitials** — Cloudflare interstitial page, hCaptcha challenge, AWS WAF page. -3. **WAF page** — explicit "Access denied" with provider branding (Cloudflare, Akamai, Imperva, F5 ASM, AWS WAF, Sucuri). -4. **Status code drift** — endpoints that previously returned 200/401 now return 403 only from your IP. -5. **Banner change** — server header shape or response timing changes consistently. -6. **DNS poisoning back to NXDOMAIN** — target's authoritative servers stop resolving subdomains (probably their CDN took over). -7. **Honeypot bait** — endpoints that look too good (`/admin/db_dump.sql`, exposed `.env` with credentials that don't validate). Real exposures rarely look this clean. -8. **Direct contact** — your sock-puppet email gets a "we noticed unusual activity" message; or, in extreme cases, your IP gets a courtesy abuse-contact email. +**Signs you've been detected (escalating severity):** 429 / `Retry-After`; captcha interstitials; WAF block page; status-code drift (200→403 from your IP only); banner change; NXDOMAIN rollback; honeypot bait (credentials that don't validate); direct contact. **Back-off ladder:** - -1. **Slow down.** Halve your concurrency. Add 2–10s jitter between requests. -2. **Switch endpoints.** Stop hitting the path that triggered. Move to a different module of the recon pipeline. -3. **Switch persona.** New User-Agent (rotate among realistic browsers), new TLS fingerprint (different httpx/curl version). -4. **Switch IP.** Rotate to a new egress (residential proxy, Tor for sensitive lookups, a different cloud region). -5. **Pause.** Wait 1–24 hours. Many WAFs have rolling-window IP-based reputation; passive time often resets it. -6. **Document and consult.** If you've hit (3) WAF, (4) status drift, or (8) direct contact, **stop active probing and consult the engagement lead**. Continued probing past these signals risks scope violation. - -**Persona / IP rotation rules:** -- Never rotate persona to one that's been used in a prior engagement against the same target. -- Use residential proxies (Bright Data, Smartproxy, IPRoyal) for high-detectability work — but be aware they're sometimes IP-blocklisted by Cloudflare. -- Tor exit nodes are useful for **passive lookups** (CT logs, archive sites) but are blocked by most active-probe targets. -- Cloud egress IPs (AWS / GCP / Azure) are often blocklisted aggressively for recon. Use sparingly. -- Document every rotation with timestamp + reason; reviewers will ask. - -**Don't:** -- Don't try to "outsmart" a confirmed WAF block by sending more aggressive payloads. That's how clients get extra logs and how you get caught. -- Don't switch source IPs to evade an explicit block-list — that crosses into evasion territory and may breach the rules of engagement. -- Don't ignore signals because the dashboard says "still up." The probe is being silently logged; the response will come later. +1. Halve concurrency; add 2–10s jitter. +2. Stop hitting the triggering path; pivot to a different module. +3. New User-Agent / TLS fingerprint. +4. Rotate egress IP (residential proxy, different cloud region). +5. Pause 1–24 hours. +6. If WAF block / status drift / direct contact: **stop and consult the engagement lead.** --- ## 7. External Red-Team Recon Pipeline -A 5-stage pipeline for any authorized external assessment. Stages are sequential; modules within a stage can run concurrently. - -### Stage 1 — Seed Discovery -Establish the ground truth of who/what the target is. - -- WHOIS on the seed domain (registrant, dates, name servers). -- ASN enumeration: which AS does the org own/use? (Hurricane Electric BGP Toolkit, RIPEstat, BGPView.) -- DNS records (A/AAAA/MX/TXT/NS/SOA/CAA) — records-only, no walking yet. -- Certificate Transparency history for the root domain (crt.sh, Censys). - -### Stage 2 — Asset Expansion -Discover everything that might belong to the target. - -- Subdomain enumeration (passive sources first: crt.sh, VirusTotal, AlienVault OTX, Shodan, then permutations and bruteforce). -- Cloud bucket enumeration (S3/GCS/Azure permutations from company name + subdomain stems — see §15). -- Typosquat domain generation (dnstwist variants → resolve → WHOIS) — for both phishing risk and adjacent corp assets. -- Wayback CDX archive endpoints for forgotten paths. -- Mobile app discovery (Android via google-play-scraper, iOS via iTunes Search API — see §14). -- DNS deep walking (NSEC walk on misconfigured zones, AXFR opportunism). -- LinkedIn employee enumeration → email-pattern derivation. - -### Stage 3 — Enrichment -Add depth to the discovered assets. - -- Port + service detection (Shodan InternetDB free → naabu/masscan if authorized). -- Live TLS handshakes (cert chain, JARM, favicon mmh3 hash). -- Web tech detection (Wappalyzer-style ~600 signatures via httpx). -- WAF/CDN inference (header markers). -- Origin discovery if behind CDN (see §27). -- Security header audit. -- Bulk screenshots (triage 1000s of hosts visually). -- Email harvesting (6 parallel sources). -- Email security audit (SPF/DMARC/DKIM/BIMI/MTA-STS). -- GitHub code-search dorking (13 dork templates × 29+ secret regexes). -- JavaScript deep analysis (sourcemaps, secrets, endpoints, internal-host leakage). -- SSO/IdP tenant fingerprinting (Entra, Okta, ADFS, Google, SAML, M365 Teams/SharePoint/OAuth — see §11). -- API & auth-map discovery (Swagger/OpenAPI, GraphQL, Postman). -- Secrets-beyond-GitHub sweep (Postman public workspaces, Stack Exchange, Trello/Notion/Atlassian dorks). -- Vendor product fingerprinting (Citrix/F5/PaloAlto/Pulse/Fortinet/Cisco/VMware/Exchange). -- Container / CI-CD / cloud-native exposure check. -- Job posting harvest for tech-stack inference. - -### Stage 4 — Exposure Analysis -Convert assets into findings. - -- Nuclei (15 always-on built-in checks + optional binary). -- TLS deep audit (sslyze / testssl.sh). -- Breach × identity correlation (HudsonRock Cavalier, HIBP, DeHashed, IntelX, local corpus → SSO_EXPOSURE findings). -- Targeted misconfiguration probes (`.git/config`, `.env`, `phpinfo.php`, `/actuator/env`, `/actuator/heapdump`, `_cat/indices`, `/console`, `/manager/html`). -- Vulnerability prioritization (CVE × EPSS × CISA KEV × public-POC availability — see §28). - -### Stage 5 — Reporting -Make the work usable. - -- Risk scoring per finding (CVSS + program-specific weights). -- Asset graph export (D3-friendly nodes/links, GraphML, JSON). -- Client-facing report (executive summary + technical detail + remediation — see §31). -- Reproduction package (run_id, tool versions, raw evidence, JSONL log). -- Bug bounty submission (if applicable — see §30). - -### 7.5 Pipeline Priority Order (highest signal density first) - -When budget is constrained, work in this order: - -1. **Breaches** — infostealer logs (HudsonRock Cavalier free tier) + HIBP + DeHashed. Highest ROI for red teams; often gives valid plaintext creds for corp SSO. Requires emails as input. -2. **GitHub recon** — code-search dorks. Finds AWS keys, Slack tokens, JWT secrets, `.env` files. Fastest path to cloud pivot. +Five sequential stages; modules within a stage can run concurrently. + +| Stage | What you do | +|---|---| +| **1 — Seed Discovery** | WHOIS, ASN enum (HE BGP Toolkit, RIPEstat), DNS records (A/AAAA/MX/TXT/NS/SOA/CAA), CT history (crt.sh, Censys). | +| **2 — Asset Expansion** | Subdomain enum (passive first → permutations → brute); cloud bucket permutation; typosquat generation; Wayback CDX; mobile app discovery; DNS walking; LinkedIn employee enum. | +| **3 — Enrichment** | Port/service (Shodan InternetDB → naabu); TLS handshakes (cert chain, JARM, favicon mmh3); WAF/CDN inference; origin discovery; security headers; email harvest; email security audit; GitHub dorking; JS deep analysis; SSO/IdP fingerprinting; API discovery; secrets sweep (Postman, Stack Exchange); vendor product fingerprinting; container/CI-CD/cloud-native exposure; job posting harvest. | +| **4 — Exposure Analysis** | Nuclei always-on checks; TLS deep audit; breach × identity correlation → SSO_EXPOSURE findings; targeted misconfig probes (`.git/config`, `.env`, `/actuator/env`, `/_cat/indices`, `/console`); vulnerability prioritization (CVE × EPSS × KEV × POC). | +| **5 — Reporting** | Risk scoring per finding; asset graph export; client-facing report (exec summary + technical detail + remediation); reproduction package; bug bounty submission if applicable. | + +### 7.1 Pipeline Priority Order (highest signal density first) + +1. **Breaches** — HudsonRock Cavalier + HIBP + DeHashed. Highest ROI; often yields plaintext corp SSO creds. +2. **GitHub recon** — code-search dorks. Fastest path to AWS keys, Slack tokens, JWT secrets. 3. **Nuclei misconfig sweep** — exposed admin panels, CVEs with public POCs. -4. **Cloud buckets** — permutate company name + subdomain stems. Listable bucket = CRITICAL. -5. **Ports** — Shodan InternetDB first (free, keyless). VPN concentrators, RDP, Jenkins, GitLab-CE, Elasticsearch are the high-value pivot points. +4. **Cloud buckets** — listable = CRITICAL. +5. **Ports** — Shodan InternetDB first. VPN concentrators, RDP, Jenkins, Elasticsearch are high-value pivots. 6. **Email OSINT** — feeds breaches; feeds phishing list. -7. **Web tech / WAF / screenshots** — triage thousands of hosts; know the stack before probing. -8. **Wayback** — archived JS often has hard-coded keys; archived endpoints reveal removed admin/dev paths. -9. **DNS deep + email security** — SPF/DMARC gaps enable email spoofing; TXT verification tokens reveal SaaS tenancies. -10. **Certificates** — CT-log timeline catches forgotten subdomains; weak ciphers = cheap findings. +7. **Web tech / WAF / screenshots** — triage thousands of hosts. +8. **Wayback** — archived JS for hard-coded keys; removed admin/dev paths. +9. **DNS deep + email security** — SPF/DMARC gaps enable spoofing; TXT tokens reveal SaaS tenancies. +10. **Certificates → TLS** — CT timeline catches forgotten subdomains; weak ciphers = cheap findings. 11. **ASN + reverse DNS** — corporate IP space hosts unadvertised infra. -12. **WHOIS** — registrant PII reveals adjacent corp assets. -13. **Typosquat** — actively-registered squats are findings; unregistered ones go on the phishing-domain shortlist. -14. **Security headers** — low standalone value but required for client reports. - -### 7.6 Time Budgeting & Engagement Profiles +12. **Typosquats** — registered = finding; unregistered = phishing shortlist. -Stage and asset count drive how long a recon takes. Rough estimates (single operator on a typical SaaS-style target): +### 7.2 Time Budgeting & Engagement Profiles -| Stage | Small org (<100 employees) | Medium (100–1K) | Large (1K+) | +| Stage | Small org (<100) | Medium (100–1K) | Large (1K+) | |---|---|---|---| -| 1. Seed discovery | 30 min | 30 min | 30 min | +| 1. Seed | 30 min | 30 min | 30 min | | 2. Asset expansion | 1–2 h | 2–4 h | 4–8 h | | 3. Enrichment (per 100 alive webapps) | ~1 h | ~1 h | ~1 h | | 4. Exposure analysis | 1–3 h | 3–6 h | 6–12 h | | 5. Reporting | 2–4 h | 4–8 h | 1–2 days | -**Engagement profiles:** - -- **1-hour rapid recon ("how exposed is X?")** — Stage 1 (15 min) → passive subdomain (crt.sh + Subfinder, 10 min) → Shodan InternetDB on resolved IPs (5 min) → email harvest via Hunter+IntelX (10 min) → breach lookup on emails (10 min) → executive-summary-only output (10 min). -- **4-hour focused recon ("phish-readiness check")** — adds: full email harvest, LinkedIn employee enum, SPF/DMARC analysis, typosquat candidate generation, SSO/IdP fingerprinting. Output: phishing-feasibility report + target email list. -- **1-day standard recon** — full Stages 1–4 with the priority order above. Output: per-asset finding list + asset graph + exec summary. -- **1-week deep recon** — all of standard, plus: deep-mode user enumeration, JS deep analysis at full budget, mobile attack surface, cloud-native fingerprinting, vendor product fingerprinting, package registry leak hunting, vulnerability prioritization. Output: full client deliverable package + reproduction bundle. -- **Ongoing monitoring (weekly diff)** — re-run Stages 1–3 weekly; diff against baseline; alert on new asset / new finding / asset disappeared. +**Profiles:** 1-hour rapid (Stages 1–2 passive + breach + exec summary) · 4-hour focused (adds email harvest, SSO fingerprinting, typosquats) · 1-day standard (full Stages 1–4 in priority order) · 1-week deep (all of standard + JS deep, mobile, cloud-native, vendor product, package registry) · ongoing weekly diff (re-run Stages 1–3, diff against baseline). -**When to abort early:** -- After Stage 1 if scope is wrong (target turns out to be subsidiary of unrelated corp; rules of engagement need clarification). -- After Stage 2 if attack surface is below threshold (no public webapps + no exposed services + no leaked emails → little to find externally). -- During any stage if you hit the WAF / detection signs in §6.4. +**Abort conditions:** scope mismatch after Stage 1; near-zero attack surface after Stage 2; WAF/detection signs hit during any stage (§6.4). --- ## 8. Asset Graph Discipline -Treat every discovery as a typed asset in a graph, not a free-floating string. +Every discovery is a **typed asset** in a graph, not a free-floating string. -### 8.1 Asset Taxonomy (29 types) +### 8.1 Asset Taxonomy -| Category | Asset Types | +| Category | Types | |---|---| -| **DNS / Network** | `domain`, `subdomain`, `ip`, `netblock`, `asn` | -| **Service** | `port`, `service`, `certificate` | -| **Identity** | `email`, `person`, `credential` | -| **Code / Config** | `repo`, `secret` | -| **Cloud / Storage** | `bucket`, `firebase_project` | -| **Web** | `webapp`, `wayback_endpoint`, `api_endpoint`, `api_spec`, `graphql_schema` | -| **Mobile** | `mobile_app`, `deep_link`, `exported_component` | -| **Phishing / Adversarial** | `typosquat_domain` | -| **Collaboration / SaaS** | `postman_collection`, `postman_workspace`, `postman_api_key`, `stack_post`, `saas_public_surface` | - -### 8.2 Asset Schema - -Every asset carries: -- `type` — one of the 29 above. -- `key` — unique dedup id (typed prefix, e.g. `sub:api.example.com`, `email:alice@example.com`). -- `value` — the actual string/object. -- `sources[]` — every source that confirmed this asset (deduplicated). -- `confidence` — TENTATIVE / FIRM / CONFIRMED. -- `first_seen`, `last_seen` — UTC timestamps. -- `attrs{}` — type-specific metadata (e.g., for a `webapp`: status_code, title, tech-stack list, JARM, favicon mmh3, screenshot path). +| DNS / Network | `domain`, `subdomain`, `ip`, `netblock`, `asn` | +| Service | `port`, `service`, `certificate` | +| Identity | `email`, `person`, `credential` | +| Code / Config | `repo`, `secret` | +| Cloud / Storage | `bucket`, `firebase_project` | +| Web | `webapp`, `wayback_endpoint`, `api_endpoint`, `api_spec`, `graphql_schema` | +| Mobile | `mobile_app`, `deep_link`, `exported_component` | +| Phishing | `typosquat_domain` | +| SaaS | `postman_collection`, `postman_workspace`, `postman_api_key`, `stack_post`, `saas_public_surface` | -### 8.3 Edge Taxonomy +Every asset carries: `type`, `key` (typed dedup id), `value`, `sources[]`, `confidence`, `first_seen`, `last_seen`, `attrs{}`. -Relationships are typed edges, not text: -`RESOLVES_TO`, `HOSTED_ON`, `IN_NETBLOCK`, `BELONGS_TO_ASN`, `LISTED_IN_CERT`, `OWNED_BY`, `ALIAS_OF`, `BREACHED_FROM`, `EMPLOYED_BY`, `HOSTS_REPO`, `TYPOSQUAT_OF`, `EXPOSES`, `DOCUMENTED_BY`, `BELONGS_TO_HOST`, `REQUIRES_AUTH`, `LEAKS_SCHEMA`, `SHIPPED_BY_ORG`, `CONTAINS_SECRET`, `TALKS_TO_HOST`, `EXPOSES_DEEPLINK`, `HAS_EXPORTED_COMPONENT`, `USES_FIREBASE_PROJECT`, `LACKS_PINNING_FOR`. +**Discipline:** create the asset first, then attach the finding. Dedup by key. `sources[]` must list every source. Confidence is per-source, then aggregated. -### 8.4 Discipline rules +### 8.2 Asset-Level Triage Rules -- **Every discovery is an asset.** Don't write findings against free-floating strings; create the asset first, then attach the finding. -- **Dedup by key, not by value.** Same value, different type ≠ same asset (`sub:api.example.com` and `webapp:https://api.example.com/` are different assets with a `BELONGS_TO_HOST` edge). -- **Provenance is non-negotiable.** `sources[]` must list every source. If two sources confirmed it, both go in. -- **Confidence is per-source, then aggregated.** A subdomain returned by 3 passive sources is FIRM; one returned by snippet-only Bing is TENTATIVE. -- **Late binding via sidecars.** When module A produces output that module B needs, write a JSON sidecar (`mobile_endpoints.json`, `secrets_sidecar.json`) — don't block module B on module A. See §24. +**WebApp priority (highest first):** auth (`auth.`, `login.`, `sso.`) → admin paths → dev/staging hosts → API (`api.`, `gateway.`) → customer-facing (`portal.`, `app.`) → marketing. -### 8.5 Asset-Level Triage Rules +**Email priority:** exec (CEO/CFO/CISO) → IT/helpdesk/security → dev/engineer/DBA → sales/HR/finance → generic role accounts. -When you have a mixed bag of assets and limited probe budget, prioritize by what each asset *enables*: - -**WebApp priority by hostname signal (highest first):** - -1. Auth-related hostnames (`auth.`, `login.`, `sso.`, `idp.`, `accounts.`, `oauth.`). -2. Admin paths (`/admin`, `/dashboard`, `/console`, `/manager`, `/wp-admin`, `/phpmyadmin`). -3. Dev/staging hosts (`dev.`, `staging.`, `stg.`, `qa.`, `uat.`, `test.`, `sandbox.`, `preprod.`, `preview.`) — lower defenses, often dump prod data. -4. API hostnames (`api.`, `services.`, `gateway.`, `graph.`). -5. Customer-facing hostnames (`portal.`, `app.`, `my.`, `account.`). -6. Marketing / content (`www.`, `blog.`, `news.`, `careers.`, `support.`). - -**Subdomain priority by inferred function:** - -- API > Admin > Dev > Auth > Prod-app > Marketing. - -**IP priority by netblock:** - -- Corporate ASN-owned (most likely to host unadvertised internal infra). -- Cloud netblocks (AWS / GCP / Azure / DO / OVH) — high turnover but interesting for cloud-native services. -- CDN ranges (Cloudflare / Akamai / Fastly) — usually edge, not origin; defer unless doing origin discovery. - -**Email priority by role hint:** - -| Role indicator | Priority | Why | -|---|---|---| -| `ceo@`, `cfo@`, `cto@`, `ciso@` | HIGHEST | Exec accounts have highest breach value (BEC, finance authority, board access). | -| `it@`, `helpdesk@`, `support@`, `security@` | HIGH | IT/security accounts have privileged tool access; helpdesk accounts handle reset workflows. | -| `dev`, `engineer`, `architect`, `dba` | MEDIUM | Developer accounts often have GitHub / cloud / CI access. | -| `sales`, `marketing`, `hr`, `finance` | MEDIUM | SaaS access (Salesforce, HubSpot, Workday); finance enables BEC. | -| Generic role accounts (`info@`, `noreply@`, `contact@`) | LOW | Often unmonitored or alias forwarded; less personal context. | - -**Repo priority by recency + naming:** - -- Recently-pushed (last 30 days) > stale. -- Public repo with target name in description > target name only in code. -- Forked from internal-looking parent > standalone. -- Mentions `prod`, `internal`, `private`, `secret` in name → priority HIGH despite being public (may be misnamed or accidentally exposed). - -**Application order:** when you have N assets and budget for M probes (M < N), apply asset-type priority first, then within-type priority. E.g.: 50 subdomains → probe API + admin + dev first (~15), then auth + prod-app (~20), defer marketing/content to a later pass. +**Repo priority:** recently pushed (last 30 days) > stale; public with target name in description > code-only; mentions `prod`/`internal`/`secret` in name → HIGH priority despite being public. --- ## 9. Findings Rubric & Severity Mapping -Severity is operational, not subjective. Use these anchors: - -### 9.1 CRITICAL - -Pre-auth code execution, confirmed valid credentials, listable production data, fundamental trust violations. - -Examples: -- `.git/config` exposed on production webapp (full source-code disclosure). -- `/.env` exposed (credentials in plaintext, often DB / cloud / API). -- Spring Boot `/actuator/env` or `/actuator/heapdump` reachable unauthenticated. -- Listable S3 / GCS / Azure bucket containing user data. -- Unauthenticated POST/PUT/DELETE to a write endpoint that mutates state. -- Open Firebase Realtime Database (`https://{project}.firebaseio.com/.json` returns data). -- `android:debuggable=true` in a production Android app. -- Live-validated credential (PMAK, AWS key, Anthropic/OpenAI key) with broad scope. -- ≥10 employees compromised in a breach corpus + their tenant identified (SSO_EXPOSURE). -- Open Elasticsearch cluster (`/_cat/indices` returns data). -- Open Docker API (`/v1.40/containers/json` returns containers). -- Open Redis (no AUTH; can write `authorized_keys`). -- Open Kubernetes API server with anonymous-auth enabled. -- Open kubelet on 10250 (pod exec without auth). -- Open etcd on 2379 (cluster state and secrets). -- BlueKeep-vulnerable RDP, EternalBlue-vulnerable SMB. -- Citrix Netscaler / F5 BIG-IP with version-specific RCE CVE. - -### 9.2 HIGH - -Significant exposure but not yet RCE; clear path to escalation; high-value information disclosure. - -Examples: -- Public secret in a GitHub repo (PAT, AWS key, Slack token, etc.). -- Sourcemap (`.js.map`) accessible — full original-source disclosure of frontend. -- Open GraphQL introspection on production (full schema leaked → mutations to enum). -- Subdomain takeover possible (CNAME points to unclaimed Heroku/Shopify/etc.). -- Reflected CORS with credentials (`Access-Control-Allow-Origin: ` + `Access-Control-Allow-Credentials: true`). -- Verb tampering: hidden DELETE/PATCH on an endpoint that publicly only allows GET. -- Missing HSTS on a sensitive path (`/login`, `/sso`, `/admin`, `/auth`) — escalated from MED. -- Exposed Jenkins/Tomcat-Manager/phpMyAdmin admin UI (no auth or default creds). -- Telnet (port 23) reachable. -- WebView with JS bridge in a mobile app (XSS → RCE potential). -- Sensitive deep-link handler in a mobile app. -- DMARC policy `p=none` on production sending domain (spoof-feasible). -- Vendor product banner with known unpatched CVE (KEV-listed). - -### 9.3 MEDIUM - -Information disclosure, hardening gaps, brute-force exposure. - -Examples: -- Missing security headers on standard pages: HSTS, CSP. -- Apache `/server-status` or `/server-info` reachable. -- `phpinfo()` or `/info.php` reachable on dev/staging only. -- Internal IP / hostname / K8s service DNS leaked in JS. -- Schema leakage in error pages (stack traces, ORM signatures). -- `android:allowBackup=true` in Android app. -- `android:usesCleartextTraffic=true` in Android app. -- Exported activity/service without `android:permission` protection. -- Missing rate-limit on an API endpoint. -- Wildcard CORS (`Access-Control-Allow-Origin: *`) on an API that returns user-tied data (no creds). -- Slack webhook URL leaked. -- Twilio Account SID leaked (without auth token). -- SPF record permissive (`+all` or many includes). - -### 9.4 LOW - -Cosmetic or marginal hardening gaps. - -Examples: -- Missing `X-Frame-Options`. -- Missing `X-Content-Type-Options`. -- `.DS_Store` exposed. -- Stripe **test** key leaked. -- Firebase URL exposed (URL only, no open RTDB). -- Certificate pinning missing in mobile app. -- Outdated WordPress install detected (no known exploit yet). -- BIMI not configured (brand impersonation risk only). - -### 9.5 INFO - -Worth recording, no action required immediately. - -Examples: -- Missing `Referrer-Policy` / `Permissions-Policy`. -- Discovered `/.well-known/security.txt`. -- `robots.txt` reveals interesting paths. -- Private bucket exists but is locked down. -- Domain detected in a breach corpus with 0 employee accounts. -- DNSSEC not enabled. - -### 9.6 Severity escalation rules - -- HSTS missing on auth/login/SSO/admin path → **MED → HIGH**. -- Wildcard CORS + credentials → **MED → HIGH**. -- Wildcard CORS + sensitive endpoint → **LOW → MED**. -- API endpoint with score ≥70 on the interest rubric (companion skill §20) → at least **HIGH**. -- Domain breach severity ≥10 employees → **CRITICAL** regardless of stale-data caveats. -- Vendor product version matches CISA KEV entry → **CRITICAL**. -- DMARC `p=reject` + SPF strict + DKIM rotated → no escalation; well-postured. - ---- - -## 10. Bug-Bounty / Red-Team Pivot Modes - -Existing investigative work (threat-actor research, doxxing investigations, attribution) operates under different posture than offensive recon. Switch posture explicitly. - -| Aspect | Investigative Mode | Offensive Recon Mode | -|---|---|---| -| **Probing rate** | Slow, single-threaded, blend with normal traffic. | Bursts, parallel, but rate-limited per provider. | -| **OpSec posture** | Sock-puppet only, never reveal investigator. | Persona may be the engagement persona; team may notify SOC. | -| **Evidence handling** | Court-grade chain of custody; hashes, timestamps, screenshots. | Engagement-grade; same hashing/timestamp discipline but evidence is for the client report. | -| **Severity in scope** | All severity levels relevant for context. | CRIT/HIGH/MED matter; LOW/INFO often dropped from exec summary. | -| **Authorization posture** | Public-record / OSINT-only; no probing private resources without authorization. | Written rules of engagement; explicit scope; explicit out-of-scope list. | -| **Reporting format** | Narrative + sourced timeline. | Per-asset findings + remediation + reproduction steps. | -| **Stop conditions** | When the question is answered. | When the engagement window closes OR when the report is delivered. | - -When you're working with the user, ask which mode they're in if it's unclear from context. - -### 10.1 Scale-Based Tactics - -Org size shapes which techniques pay off. - -**Small org (< 100 employees):** -- Executive accounts disproportionately matter; one CEO/CFO compromise often hands you the keys. -- Email harvest is small enough to enumerate exhaustively (10–50 emails total). -- Likely Microsoft 365 or Google Workspace; identity fabric is one tenant. -- Code repos often public on GitHub under personal accounts (founders moved from solo dev). -- Cloud presence often single-account AWS or GCP project. -- Tactics: deep on every email + every identity-fabric finding; full LinkedIn enum; check founders' personal GitHub orgs. - -**Medium org (100–1K):** -- Balanced enumeration. Email list is enumerable but not exhaustive. -- Identity fabric likely one IdP but with multiple SaaS tenants (Slack workspace, Notion org, GitHub org). -- Mobile apps possible; check both stores. -- Cloud presence multi-account or multi-region. -- Tactics: full pipeline at standard depth; sample-and-deepen on each asset class; LinkedIn priority by role. - -**Large org (1K–10K):** -- Email enum becomes lossy (sample top roles); breach hits scale up. -- Multi-tenant identity fabric (often Entra + Okta + multiple Auth0 customers). -- Mobile apps, multiple Android packages from different teams. -- Cloud presence sprawling; subsidiaries / acquisitions complicate scope. -- Tactics: breadth-first; rely on automation for asset discovery; manual triage on findings. - -**Very large org (10K+) or conglomerate:** -- Brand-pivot maps before anything else: enumerate every brand domain, every subsidiary. -- Breach corpus dominates: 10K+ employees mean significant past-breach exposure. -- Identity fabric may differ per business unit (legal entity boundaries). -- Tactics: scope pruning is the most important step; sampling + automation throughout; deep dive only on high-priority findings. - -**Cross-scale principle:** the smaller the org, the more individual-account focus pays off. The larger the org, the more systemic posture findings (DMARC gaps, SSO_EXPOSURE breadth, vendor-product version sweeps) pay off. - ---- - -## 11. Identity Fabric Mapping - -An organization's IdP/SSO posture is a high-value target: compromise the identity fabric and you don't need to break into individual apps. Map it methodically. - -### 11.1 Subdomain prefix enumeration - -Probe these prefixes against the target's root domain (and any sibling brand domains discovered): - -``` -auth.{domain} -login.{domain} -sso.{domain} -idp.{domain} -iam.{domain} -identity.{domain} -accounts.{domain} -oauth.{domain} -``` - -Plus generic OIDC discovery on every alive subdomain: -``` -{any-host}/.well-known/openid-configuration -``` - -### 11.2 Microsoft Entra (Azure AD) - -- **OIDC metadata + tenant GUID extraction** — fetch `https://login.microsoftonline.com/{tenant-or-domain}/.well-known/openid-configuration`. The `issuer` field returns a URL containing the tenant GUID (8-4-4-4-12 hex format). Tenant GUID + domain = stable tenant fingerprint. -- **getuserrealm.srf** — `https://login.microsoftonline.com/getuserrealm.srf?login=@` returns NameSpaceType: `Managed` (cloud-native), `Federated` (on-prem ADFS / external IdP), or `Unknown`. Detectability: low. -- **Autodiscover v2** — `https://autodiscover-s.outlook.com/autodiscover/metadata/json/1` POST with email; detects tenant membership. -- **GetCredentialType** (deep-mode user-enum) — `https://login.microsoftonline.com/common/GetCredentialType` POST `{"username": ""}`. Response indicates whether email exists in tenant. Detectability: medium. Cap attempts at 20 per tenant. - -### 11.3 Okta - -- **Org slug derivation** — derive candidate slugs from subdomains + root domain stem; Okta tenants live at `.okta.com` (or `.oktapreview.com`). -- **OIDC fingerprint** — `https://.okta.com/.well-known/openid-configuration`. -- **/api/v1/authn user-enum** (deep-mode) — POST `{"username": "", "password": "invalid"}`. 400 vs 401 response code indicates user existence. Detectability: medium. Cap at 20 per tenant. - -### 11.4 ADFS - -- **Passive fingerprint** — GET `https://{domain}/adfs/idpinitiatedsignon.aspx` → 200 indicates ADFS present. -- **Active mex endpoint** (deep-mode) — `https://{domain}/adfs/Services/Trust/mex` returns SOAP metadata. - -### 11.5 Google Workspace - -- `https://{domain}/.well-known/openid-configuration` — Google-hosted-domain customers expose discovery endpoints with characteristic issuer/JWKS URIs. -- MX records pointing to `*.googlemail.com` / `aspmx.l.google.com` is a strong Google Workspace signal. - -### 11.6 Generic OIDC (Keycloak / Auth0 / Ping / OneLogin / Duo) - -- Probe every alive subdomain for `/.well-known/openid-configuration`. -- The `issuer` and `authorization_endpoint` fields fingerprint the IdP product. -- `*.auth0.com`, `*.onelogin.com`, `*.pingone.com`, `*.duosecurity.com` patterns are characteristic. - -### 11.7 SAML metadata - -Probe these paths on every alive webapp: - -``` -/saml/metadata -/FederationMetadata/2007-06/FederationMetadata.xml -/federationmetadata/2007-06/federationmetadata.xml -/simplesaml/saml2/idp/metadata.php -/auth/saml2/metadata -``` - -SAML metadata XML contains: `EntityID`, signing certs, `SingleSignOnService` URL, `NameIDFormat`. - -### 11.8 AWS account-ID extraction - -- **S3 bucket region header** — HEAD on a known target bucket returns `x-amz-bucket-region`; correlate with bucket-name entropy to infer account. -- **ARN regex in JSON / HTML responses** — search for `arn:aws:[a-z0-9-]+:[a-z0-9-]*:([0-9]{12}):` (the 12-digit AWS account ID is the capture group). -- **`AccountId` property in JS / API responses** — common in IAM-related error messages and CloudFormation outputs. -- **OAuth client_id leaks** — Google OAuth: `-.apps.googleusercontent.com`; MSAL: GUID in `clientId` property. - -### 11.9 Output - -Each discovered IdP becomes a `Service` asset with `attrs.product`, `attrs.tenant_id`, `attrs.discovery_endpoint`. Then in Stage 4, correlate with breach data: every compromised user under a discovered tenant becomes an SSO_EXPOSURE finding (CRITICAL — see §22.3). - -### 11.10 Microsoft 365 Deep Surface - -Beyond plain Entra fingerprinting, M365 exposes a wider attack surface that's worth enumerating in depth. - -**Teams Federation:** - -- `https://login.microsoftonline.com//.well-known/openid-configuration` confirms tenant. -- Teams federation status: `https://teams.microsoft.com/api/mt//beta/users//externalsearchv3` (requires authenticated request from a federated tenant; useful for confirming whether external Teams chat is allowed). -- **External chat enabled** = soft-attack surface (vishing, smishing, "from-IT" pretexts via Teams chat). -- **Open Federation** (any tenant can chat) is the default; check whether the target restricted it. - -**SharePoint subdomains:** - -- `.sharepoint.com` — main tenant SharePoint. -- `-my.sharepoint.com` — OneDrive-for-Business URLs (per-user personal sites). -- `-admin.sharepoint.com` — SharePoint admin center (auth-required, but presence confirms tenancy). -- Where `` is derived from the company name (often the part before `.com`). - -**OneDrive personal site enumeration:** - -- Per-user OneDrive URL: `https://-my.sharepoint.com/personal//Documents/`. -- Replace `@` with `_` and `.` with `_` in the email (e.g., `alice@acme.com` → `alice_acme_com`). -- Authenticated probe; useful for confirming whether the OneDrive personal site has been provisioned (which itself is a presence indicator). - -**M365 OAuth client_id discovery:** - -- Many internal apps register OAuth client_ids in Entra. Search JS bundles, mobile-app strings, and API responses for `client_id=` patterns. -- Microsoft's well-known first-party client_ids (for Office, Graph, etc.) are documented; finding non-Microsoft GUIDs reveals custom internal apps. -- The endpoint `https://login.microsoftonline.com//v2.0/.well-known/openid-configuration` lists supported endpoints; some tenants leave `device_authorization_endpoint` enabled (device-code phishing target). - -**Power Platform / Power Apps:** - -- `https://make.powerapps.com/environments` (auth-required); environment IDs sometimes leak in URLs. -- `*.crm.dynamics.com` (Dynamics 365 / Power Apps default URLs). -- `*.azurewebsites.net` for App Service deployments. - -**M365 OAuth misconfig findings to look for:** +### Severity Anchors -- `device_authorization_endpoint` enabled on `common` tenant (device-code phishing target) → **MEDIUM** (operational risk; not directly exploitable but enables attack). -- Custom OAuth app with `Public client` flow enabled and broad scopes (offline_access, Mail.Read, Files.Read.All) → **HIGH** if app is approved for the tenant. -- Multi-tenant OAuth app published by the target (others can consent) → check whether scopes include sensitive Graph permissions. - -**Detectability:** all M365 endpoint probes log to Entra sign-in logs / audit logs (medium-low for fetch-only; medium for any auth attempt). - ---- - -## 12. API & Auth-Map Methodology - -Modern targets expose REST, GraphQL, and undocumented internal APIs. The OSINT goal is to enumerate them, classify them, and rank by attack interest. - -### 12.1 Discovery paths - -- **Swagger / OpenAPI** — probe a 28-path wordlist (companion skill §16.1) on every alive webapp. Parse YAML/JSON; extract every endpoint (method + path). -- **GraphQL** — probe a 13-path wordlist (companion skill §16.2). POST a standard introspection query. If schema returns, you have full type/query/mutation/subscription enumeration. -- **GraphQL when introspection is disabled** — fall back to field-suggestion enumeration (companion skill §22.9). -- **Postman** — query Postman's public universal-search endpoint with the target name; walk each matching workspace; extract requests, headers, pre-request scripts, test scripts, env vars. -- **JS-extracted endpoints** — every endpoint extracted from JavaScript bundles feeds into the same classifier. -- **Mobile-extracted endpoints** — every endpoint from APK static analysis feeds in via sidecar (`mobile_endpoints.json`). - -### 12.2 Classification - -For each endpoint, capture: - -``` -url, method, source[], auth_required, auth_type, auth_location, -rate_limited, cors_policy, sensitive_path_keywords[], schema_leaks, -verb_tampering_possible, interest_score (0..100), interest_reasons[] -``` - -How to determine each field: -- Send `OPTIONS` → `Allow` header reveals supported methods (verb tampering check). -- Send `GET` without auth → 200 = `auth_required=false`; 401/403 = `auth_required=true`. -- Capture response headers for `WWW-Authenticate` (auth_type), `RateLimit-*` / `X-RateLimit-*`. -- Send a request with `Origin: https://attacker.example` → response `Access-Control-Allow-Origin` reflected = `cors_policy=reflected`. -- Trigger an error → check response for stack traces, ORM hints. - -### 12.3 Interest score (0–100) - -See companion skill §20 for the full rubric. **Score ≥ 70 → HIGH/CRITICAL finding** with `attack_path_hint` in evidence. - -### 12.4 Attack-path hints - -When emitting a HIGH/CRITICAL finding, include a one-sentence attack-path hint in the evidence so the operator knows where to start exploiting. Templates in companion skill §39. - ---- - -## 13. JavaScript Deep Analysis - -For every alive webapp, scrape its JS — it's where modern frontends leak. - -### 13.1 Script discovery - -- Parse HTML for `