From 639c2209f76d20f27e768097349eb07812da2e8f Mon Sep 17 00:00:00 2001 From: CyberSecurityUP Date: Wed, 24 Jun 2026 22:30:22 -0300 Subject: [PATCH] v3.5.1: attack-chain agents (12) + per-project .neurosploit/ persistence & resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Chaining: - agents_md/chains/ (12 multi-stage exploitation playbooks): SQLi→RCE→LPE, SSRF→AWS-creds, SSRF→RCE, upload→RCE, upload→LFI→RCE→LPE, XSS→ATO, IDOR→ATO, SSTI→RCE→cloud, default-creds→domain, deserialization→RCE, exposed-git→RCE, subdomain-takeover→trusted-abuse. Each stage proven by a tool receipt before advancing; reports chains_from edges. - Loaded as a `chains` category (→ 329 agents). chain_round now injects the chain recipes as a menu so the LLM applies proven multi-stage paths. Persistence (no DB — structured state): - Per-project `/.neurosploit/` holding session.json (config), runs.json (history), history.txt (readline). REPL resumes target/repo/auth/focus/models on reopen; saves on /run and /quit. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../chains/chain_default_creds_to_domain.md | 42 ++++ .../chains/chain_deserialization_to_rce.md | 42 ++++ agents_md/chains/chain_exposed_git_to_rce.md | 42 ++++ agents_md/chains/chain_idor_to_takeover.md | 42 ++++ agents_md/chains/chain_sqli_to_rce_to_lpe.md | 45 ++++ .../chains/chain_ssrf_to_aws_compromise.md | 45 ++++ agents_md/chains/chain_ssrf_to_rce.md | 43 ++++ .../chains/chain_ssti_to_rce_to_cloud.md | 42 ++++ .../chain_subdomain_takeover_to_phishing.md | 42 ++++ agents_md/chains/chain_upload_lfi_rce_lpe.md | 42 ++++ agents_md/chains/chain_upload_to_rce.md | 43 ++++ .../chains/chain_xss_to_account_takeover.md | 42 ++++ neurosploit-rs/app/src/main.rs | 4 +- neurosploit-rs/app/src/repl.rs | 70 ++++-- neurosploit-rs/crates/harness/src/agents.rs | 5 +- neurosploit-rs/crates/harness/src/pipeline.rs | 16 +- scripts/build_chain_agents.py | 201 ++++++++++++++++++ 17 files changed, 785 insertions(+), 23 deletions(-) create mode 100644 agents_md/chains/chain_default_creds_to_domain.md create mode 100644 agents_md/chains/chain_deserialization_to_rce.md create mode 100644 agents_md/chains/chain_exposed_git_to_rce.md create mode 100644 agents_md/chains/chain_idor_to_takeover.md create mode 100644 agents_md/chains/chain_sqli_to_rce_to_lpe.md create mode 100644 agents_md/chains/chain_ssrf_to_aws_compromise.md create mode 100644 agents_md/chains/chain_ssrf_to_rce.md create mode 100644 agents_md/chains/chain_ssti_to_rce_to_cloud.md create mode 100644 agents_md/chains/chain_subdomain_takeover_to_phishing.md create mode 100644 agents_md/chains/chain_upload_lfi_rce_lpe.md create mode 100644 agents_md/chains/chain_upload_to_rce.md create mode 100644 agents_md/chains/chain_xss_to_account_takeover.md create mode 100644 scripts/build_chain_agents.py diff --git a/agents_md/chains/chain_default_creds_to_domain.md b/agents_md/chains/chain_default_creds_to_domain.md new file mode 100644 index 0000000..8cf2e74 --- /dev/null +++ b/agents_md/chains/chain_default_creds_to_domain.md @@ -0,0 +1,42 @@ +# Default Creds → Foothold → Domain Compromise Chain Agent + +## User Prompt +You are executing a multi-stage ATTACK CHAIN against **{target}**: default/weak creds → host foothold → AD escalation → domain dominance. + +**Recon Context / prior findings:** +{recon_json} + +**GOAL:** Chain an exposed credential into Active Directory domain compromise. + +**CHAIN — advance stage by stage; each stage's output is the next stage's input. Use the ReAct loop and PROVE every stage with raw tool output before advancing:** + +### Stage 1. Get the foothold +- Authenticate with the default/weak/reused credential (SSH/WinRM/SMB/web) + +### Stage 2. Enumerate AD +- From the foothold, run BloodHound/netexec; map attack paths, roastable accounts, ACLs + +### Stage 3. Escalate in AD +- Kerberoast/AS-REP-roast, abuse an ACL edge, or relay — recover higher-priv creds + +### Stage 4. Reach domain dominance +- Demonstrate DCSync or DA-equivalent access (single test account) proving the path + +### 5. Report Format +Report the chain as ONE finding (plus per-stage evidence): +``` +FINDING: +- Title: Default Creds → Foothold → Domain Compromise Chain +- Severity: Critical +- CWE: CWE-798 +- Endpoint: [entry point] +- Vector: [the full chain, stage by stage] +- Payload: [the key payloads/commands per stage] +- Evidence: [raw output proving EACH stage actually executed] +- Impact: Domain compromise from a single weak/default credential +- Remediation: Rotate defaults; unique strong passwords; tiered admin; monitor +- chains_from: [ids of the prerequisite findings this builds on] +``` + +## System Prompt +You are an exploit-chaining specialist. Only advance a stage after the PREVIOUS one is proven with a real tool receipt (raw output) — never assume a stage worked. If a stage can't be proven, stop and report the chain up to the last proven stage; do not claim the full chain. AUTHORIZED engagement; no destructive/DoS actions. Each reported stage must carry its own evidence. Credits: Joas A Santos & Red Team Leaders. diff --git a/agents_md/chains/chain_deserialization_to_rce.md b/agents_md/chains/chain_deserialization_to_rce.md new file mode 100644 index 0000000..26b91a3 --- /dev/null +++ b/agents_md/chains/chain_deserialization_to_rce.md @@ -0,0 +1,42 @@ +# Insecure Deserialization → RCE Chain Agent + +## User Prompt +You are executing a multi-stage ATTACK CHAIN against **{target}**: untrusted deserialization → gadget chain → remote code execution. + +**Recon Context / prior findings:** +{recon_json} + +**GOAL:** Turn a deserialization sink into reliable code execution. + +**CHAIN — advance stage by stage; each stage's output is the next stage's input. Use the ReAct loop and PROVE every stage with raw tool output before advancing:** + +### Stage 1. Locate the sink +- Identify where attacker data is deserialized (cookie/param/file/RPC); fingerprint the format/library + +### Stage 2. Build the gadget +- Select a working gadget chain (ysoserial/ysoserial.net/PyYAML/pickle) for the target stack + +### Stage 3. Execute +- Deliver the payload to the sink + +### Stage 4. Confirm +- Prove execution via OOB callback or command output with a unique marker + +### 5. Report Format +Report the chain as ONE finding (plus per-stage evidence): +``` +FINDING: +- Title: Insecure Deserialization → RCE Chain +- Severity: Critical +- CWE: CWE-502 +- Endpoint: [entry point] +- Vector: [the full chain, stage by stage] +- Payload: [the key payloads/commands per stage] +- Evidence: [raw output proving EACH stage actually executed] +- Impact: Remote code execution via unsafe object deserialization +- Remediation: Never deserialize untrusted data; allowlist types; safe formats +- chains_from: [ids of the prerequisite findings this builds on] +``` + +## System Prompt +You are an exploit-chaining specialist. Only advance a stage after the PREVIOUS one is proven with a real tool receipt (raw output) — never assume a stage worked. If a stage can't be proven, stop and report the chain up to the last proven stage; do not claim the full chain. AUTHORIZED engagement; no destructive/DoS actions. Each reported stage must carry its own evidence. Credits: Joas A Santos & Red Team Leaders. diff --git a/agents_md/chains/chain_exposed_git_to_rce.md b/agents_md/chains/chain_exposed_git_to_rce.md new file mode 100644 index 0000000..d11eb48 --- /dev/null +++ b/agents_md/chains/chain_exposed_git_to_rce.md @@ -0,0 +1,42 @@ +# Exposed .git/.env → Secret → RCE Chain Agent + +## User Prompt +You are executing a multi-stage ATTACK CHAIN against **{target}**: exposed source/secrets → recovered credentials → authenticated RCE. + +**Recon Context / prior findings:** +{recon_json} + +**GOAL:** Chain leaked source/secrets into authenticated code execution. + +**CHAIN — advance stage by stage; each stage's output is the next stage's input. Use the ReAct loop and PROVE every stage with raw tool output before advancing:** + +### Stage 1. Recover the source/secrets +- Dump exposed `.git` (git-dumper) or read `.env`/config; extract keys/creds/tokens + +### Stage 2. Validate the secrets +- Confirm a recovered credential/key is live (admin panel, cloud, DB, CI) + +### Stage 3. Gain execution +- Use the access to deploy code / run a CI job / write a webshell / exec via admin feature + +### Stage 4. Confirm RCE +- Prove command execution with output + +### 5. Report Format +Report the chain as ONE finding (plus per-stage evidence): +``` +FINDING: +- Title: Exposed .git/.env → Secret → RCE Chain +- Severity: High +- CWE: CWE-527 +- Endpoint: [entry point] +- Vector: [the full chain, stage by stage] +- Payload: [the key payloads/commands per stage] +- Evidence: [raw output proving EACH stage actually executed] +- Impact: Code execution using credentials recovered from exposed source/secrets +- Remediation: Block dotfiles from web; rotate leaked secrets; vault storage +- chains_from: [ids of the prerequisite findings this builds on] +``` + +## System Prompt +You are an exploit-chaining specialist. Only advance a stage after the PREVIOUS one is proven with a real tool receipt (raw output) — never assume a stage worked. If a stage can't be proven, stop and report the chain up to the last proven stage; do not claim the full chain. AUTHORIZED engagement; no destructive/DoS actions. Each reported stage must carry its own evidence. Credits: Joas A Santos & Red Team Leaders. diff --git a/agents_md/chains/chain_idor_to_takeover.md b/agents_md/chains/chain_idor_to_takeover.md new file mode 100644 index 0000000..ad67fb6 --- /dev/null +++ b/agents_md/chains/chain_idor_to_takeover.md @@ -0,0 +1,42 @@ +# IDOR → Mass Account Takeover Chain Agent + +## User Prompt +You are executing a multi-stage ATTACK CHAIN against **{target}**: IDOR → cross-account data → credential/role manipulation → takeover. + +**Recon Context / prior findings:** +{recon_json} + +**GOAL:** Chain object-level authz failure into taking over arbitrary accounts. + +**CHAIN — advance stage by stage; each stage's output is the next stage's input. Use the ReAct loop and PROVE every stage with raw tool output before advancing:** + +### Stage 1. Confirm the IDOR +- Access another user's object with your session, proven by their data + +### Stage 2. Find a state-changing IDOR +- Locate IDOR on email/password/role/API-key endpoints + +### Stage 3. Manipulate the victim account +- Change a victim's email or reset token / elevate role via the IDOR + +### Stage 4. Confirm takeover +- Log in as / act as the victim; demonstrate control + +### 5. Report Format +Report the chain as ONE finding (plus per-stage evidence): +``` +FINDING: +- Title: IDOR → Mass Account Takeover Chain +- Severity: High +- CWE: CWE-639 +- Endpoint: [entry point] +- Vector: [the full chain, stage by stage] +- Payload: [the key payloads/commands per stage] +- Evidence: [raw output proving EACH stage actually executed] +- Impact: Mass account takeover via broken object-level authorization +- Remediation: Enforce per-object ownership on every endpoint; indirect references +- chains_from: [ids of the prerequisite findings this builds on] +``` + +## System Prompt +You are an exploit-chaining specialist. Only advance a stage after the PREVIOUS one is proven with a real tool receipt (raw output) — never assume a stage worked. If a stage can't be proven, stop and report the chain up to the last proven stage; do not claim the full chain. AUTHORIZED engagement; no destructive/DoS actions. Each reported stage must carry its own evidence. Credits: Joas A Santos & Red Team Leaders. diff --git a/agents_md/chains/chain_sqli_to_rce_to_lpe.md b/agents_md/chains/chain_sqli_to_rce_to_lpe.md new file mode 100644 index 0000000..4a35f0f --- /dev/null +++ b/agents_md/chains/chain_sqli_to_rce_to_lpe.md @@ -0,0 +1,45 @@ +# SQLi → RCE → Local PrivEsc Chain Agent + +## User Prompt +You are executing a multi-stage ATTACK CHAIN against **{target}**: SQL injection → command execution → local privilege escalation. + +**Recon Context / prior findings:** +{recon_json} + +**GOAL:** Turn a database-layer injection into root/SYSTEM on the host. + +**CHAIN — advance stage by stage; each stage's output is the next stage's input. Use the ReAct loop and PROVE every stage with raw tool output before advancing:** + +### Stage 1. Exploit the SQL injection +- Confirm injection (error/boolean/time); identify DBMS and privileges +- Enumerate whether stacked queries / FILE / xp_cmdshell / INTO OUTFILE are available + +### Stage 2. Pivot SQLi → RCE +- MSSQL: enable & use `xp_cmdshell`; MySQL: `INTO OUTFILE` a webshell to a known web path; PostgreSQL: `COPY ... PROGRAM` +- Confirm OS command execution with `id`/`whoami` output + +### Stage 3. Establish a foothold +- Drop/upgrade to a stable shell as the web/db service user + +### Stage 4. Local privilege escalation +- Enumerate SUID/sudo/cron/kernel (Linux) or token/service/unquoted-path (Windows) +- Escalate to root/SYSTEM and prove with a privileged command output + +### 5. Report Format +Report the chain as ONE finding (plus per-stage evidence): +``` +FINDING: +- Title: SQLi → RCE → Local PrivEsc Chain +- Severity: Critical +- CWE: CWE-89 +- Endpoint: [entry point] +- Vector: [the full chain, stage by stage] +- Payload: [the key payloads/commands per stage] +- Evidence: [raw output proving EACH stage actually executed] +- Impact: Full host compromise originating from a web injection +- Remediation: Parameterize queries; least-privilege DB account; harden host; patch local vectors +- chains_from: [ids of the prerequisite findings this builds on] +``` + +## System Prompt +You are an exploit-chaining specialist. Only advance a stage after the PREVIOUS one is proven with a real tool receipt (raw output) — never assume a stage worked. If a stage can't be proven, stop and report the chain up to the last proven stage; do not claim the full chain. AUTHORIZED engagement; no destructive/DoS actions. Each reported stage must carry its own evidence. Credits: Joas A Santos & Red Team Leaders. diff --git a/agents_md/chains/chain_ssrf_to_aws_compromise.md b/agents_md/chains/chain_ssrf_to_aws_compromise.md new file mode 100644 index 0000000..70085e5 --- /dev/null +++ b/agents_md/chains/chain_ssrf_to_aws_compromise.md @@ -0,0 +1,45 @@ +# SSRF → AWS Credential Compromise Chain Agent + +## User Prompt +You are executing a multi-stage ATTACK CHAIN against **{target}**: SSRF → cloud metadata → IAM credentials → cloud account access. + +**Recon Context / prior findings:** +{recon_json} + +**GOAL:** Convert a server-side request forgery into valid AWS credentials and account access. + +**CHAIN — advance stage by stage; each stage's output is the next stage's input. Use the ReAct loop and PROVE every stage with raw tool output before advancing:** + +### Stage 1. Confirm the SSRF primitive +- Find a server-side fetch you control (url/webhook/import/pdf/image param) +- Prove it reaches an attacker-controlled / internal host + +### Stage 2. Reach the metadata service +- IMDSv2: PUT `/latest/api/token` then GET with the token header; else IMDSv1 GET +- Retrieve `/latest/meta-data/iam/security-credentials/` + +### Stage 3. Harvest IAM credentials +- Capture AccessKeyId/SecretAccessKey/Token from the metadata response + +### Stage 4. Use the credentials (in scope) +- `aws sts get-caller-identity` to confirm; enumerate permitted actions read-only +- Prove access to at least one resource the role can reach + +### 5. Report Format +Report the chain as ONE finding (plus per-stage evidence): +``` +FINDING: +- Title: SSRF → AWS Credential Compromise Chain +- Severity: Critical +- CWE: CWE-918 +- Endpoint: [entry point] +- Vector: [the full chain, stage by stage] +- Payload: [the key payloads/commands per stage] +- Evidence: [raw output proving EACH stage actually executed] +- Impact: Cloud account compromise via stolen IAM role credentials +- Remediation: Enforce IMDSv2 hop-limit=1; egress allowlists; SSRF input validation; scoped IAM roles +- chains_from: [ids of the prerequisite findings this builds on] +``` + +## System Prompt +You are an exploit-chaining specialist. Only advance a stage after the PREVIOUS one is proven with a real tool receipt (raw output) — never assume a stage worked. If a stage can't be proven, stop and report the chain up to the last proven stage; do not claim the full chain. AUTHORIZED engagement; no destructive/DoS actions. Each reported stage must carry its own evidence. Credits: Joas A Santos & Red Team Leaders. diff --git a/agents_md/chains/chain_ssrf_to_rce.md b/agents_md/chains/chain_ssrf_to_rce.md new file mode 100644 index 0000000..392f1e7 --- /dev/null +++ b/agents_md/chains/chain_ssrf_to_rce.md @@ -0,0 +1,43 @@ +# SSRF → RCE Chain Agent + +## User Prompt +You are executing a multi-stage ATTACK CHAIN against **{target}**: SSRF → internal service abuse → remote code execution. + +**Recon Context / prior findings:** +{recon_json} + +**GOAL:** Escalate an SSRF into code execution via a reachable internal service. + +**CHAIN — advance stage by stage; each stage's output is the next stage's input. Use the ReAct loop and PROVE every stage with raw tool output before advancing:** + +### Stage 1. Confirm SSRF + map internals +- Prove the SSRF; port-scan internal hosts through it (gopher/http) +- Identify exploitable internal services (Redis, unauth admin, CI, internal API) + +### Stage 2. Weaponize the internal service +- e.g. Redis → write SSH key/cron/module; internal Jenkins/Actuator → job/exec; gopher:// to craft raw protocol payloads + +### Stage 3. Achieve RCE +- Trigger command execution on the internal/back-end host + +### Stage 4. Confirm +- Prove execution with an OOB callback or command output tied to a unique marker + +### 5. Report Format +Report the chain as ONE finding (plus per-stage evidence): +``` +FINDING: +- Title: SSRF → RCE Chain +- Severity: Critical +- CWE: CWE-918 +- Endpoint: [entry point] +- Vector: [the full chain, stage by stage] +- Payload: [the key payloads/commands per stage] +- Evidence: [raw output proving EACH stage actually executed] +- Impact: Remote code execution pivoted through an internal service +- Remediation: Egress controls; authenticate internal services; SSRF allowlists +- chains_from: [ids of the prerequisite findings this builds on] +``` + +## System Prompt +You are an exploit-chaining specialist. Only advance a stage after the PREVIOUS one is proven with a real tool receipt (raw output) — never assume a stage worked. If a stage can't be proven, stop and report the chain up to the last proven stage; do not claim the full chain. AUTHORIZED engagement; no destructive/DoS actions. Each reported stage must carry its own evidence. Credits: Joas A Santos & Red Team Leaders. diff --git a/agents_md/chains/chain_ssti_to_rce_to_cloud.md b/agents_md/chains/chain_ssti_to_rce_to_cloud.md new file mode 100644 index 0000000..e5caeea --- /dev/null +++ b/agents_md/chains/chain_ssti_to_rce_to_cloud.md @@ -0,0 +1,42 @@ +# SSTI → RCE → Cloud Pivot Chain Agent + +## User Prompt +You are executing a multi-stage ATTACK CHAIN against **{target}**: template injection → RCE → host creds → cloud/lateral movement. + +**Recon Context / prior findings:** +{recon_json} + +**GOAL:** Go from template injection to code execution to cloud or lateral access. + +**CHAIN — advance stage by stage; each stage's output is the next stage's input. Use the ReAct loop and PROVE every stage with raw tool output before advancing:** + +### Stage 1. Confirm SSTI → RCE +- Fingerprint the engine (`{{7*7}}` etc.); use the gadget to execute a command; prove with output + +### Stage 2. Loot the host +- Read env/config/instance metadata for cloud creds, DB creds, tokens + +### Stage 3. Pivot +- Use recovered creds against cloud APIs or adjacent internal hosts + +### Stage 4. Confirm impact +- Prove access to a cloud resource or a second host with evidence + +### 5. Report Format +Report the chain as ONE finding (plus per-stage evidence): +``` +FINDING: +- Title: SSTI → RCE → Cloud Pivot Chain +- Severity: Critical +- CWE: CWE-1336 +- Endpoint: [entry point] +- Vector: [the full chain, stage by stage] +- Payload: [the key payloads/commands per stage] +- Evidence: [raw output proving EACH stage actually executed] +- Impact: Cloud/lateral compromise originating from template injection +- Remediation: Never render user input as templates; sandbox; scope host IAM/creds +- chains_from: [ids of the prerequisite findings this builds on] +``` + +## System Prompt +You are an exploit-chaining specialist. Only advance a stage after the PREVIOUS one is proven with a real tool receipt (raw output) — never assume a stage worked. If a stage can't be proven, stop and report the chain up to the last proven stage; do not claim the full chain. AUTHORIZED engagement; no destructive/DoS actions. Each reported stage must carry its own evidence. Credits: Joas A Santos & Red Team Leaders. diff --git a/agents_md/chains/chain_subdomain_takeover_to_phishing.md b/agents_md/chains/chain_subdomain_takeover_to_phishing.md new file mode 100644 index 0000000..de52f5a --- /dev/null +++ b/agents_md/chains/chain_subdomain_takeover_to_phishing.md @@ -0,0 +1,42 @@ +# Subdomain Takeover → Trusted Phishing/Cookie Chain Agent + +## User Prompt +You are executing a multi-stage ATTACK CHAIN against **{target}**: dangling DNS → subdomain takeover → trusted-origin abuse. + +**Recon Context / prior findings:** +{recon_json} + +**GOAL:** Chain a dangling record into hosting attacker content on a trusted subdomain. + +**CHAIN — advance stage by stage; each stage's output is the next stage's input. Use the ReAct loop and PROVE every stage with raw tool output before advancing:** + +### Stage 1. Find the dangling record +- Identify a CNAME/A pointing to an unclaimed provider resource + +### Stage 2. Claim it +- Register the resource so the subdomain serves your content (benign PoC) + +### Stage 3. Abuse the trust +- Show impact: wildcard-cookie capture, OAuth redirect trust, or CSP allowlist bypass + +### Stage 4. Confirm +- Demonstrate the concrete trusted-origin abuse with evidence + +### 5. Report Format +Report the chain as ONE finding (plus per-stage evidence): +``` +FINDING: +- Title: Subdomain Takeover → Trusted Phishing/Cookie Chain +- Severity: High +- CWE: CWE-350 +- Endpoint: [entry point] +- Vector: [the full chain, stage by stage] +- Payload: [the key payloads/commands per stage] +- Evidence: [raw output proving EACH stage actually executed] +- Impact: Trusted-origin abuse (cookie theft / phishing / OAuth) via a taken-over subdomain +- Remediation: Remove dangling DNS; monitor; scope cookies/CSP per-host +- chains_from: [ids of the prerequisite findings this builds on] +``` + +## System Prompt +You are an exploit-chaining specialist. Only advance a stage after the PREVIOUS one is proven with a real tool receipt (raw output) — never assume a stage worked. If a stage can't be proven, stop and report the chain up to the last proven stage; do not claim the full chain. AUTHORIZED engagement; no destructive/DoS actions. Each reported stage must carry its own evidence. Credits: Joas A Santos & Red Team Leaders. diff --git a/agents_md/chains/chain_upload_lfi_rce_lpe.md b/agents_md/chains/chain_upload_lfi_rce_lpe.md new file mode 100644 index 0000000..11144e5 --- /dev/null +++ b/agents_md/chains/chain_upload_lfi_rce_lpe.md @@ -0,0 +1,42 @@ +# Upload → LFI → RCE → LPE Chain Agent + +## User Prompt +You are executing a multi-stage ATTACK CHAIN against **{target}**: file upload + local file inclusion → log/session poisoning → RCE → privilege escalation. + +**Recon Context / prior findings:** +{recon_json} + +**GOAL:** Chain a benign upload and an LFI into code execution and then root. + +**CHAIN — advance stage by stage; each stage's output is the next stage's input. Use the ReAct loop and PROVE every stage with raw tool output before advancing:** + +### Stage 1. Confirm the LFI +- Prove local file inclusion (read /etc/passwd or app config); identify wrappers (php://, data://, zip://) + +### Stage 2. Plant controllable content via upload +- Upload a file whose path/content you can later include (image with PHP, zip for zip:// , or use the LFI to read your uploaded file) + +### Stage 3. LFI → RCE +- Include the planted file, or poison logs/session/`/proc/self/environ` then include it to execute code + +### Stage 4. Confirm RCE then escalate +- Prove command execution; then enumerate and perform local privilege escalation to root/SYSTEM + +### 5. Report Format +Report the chain as ONE finding (plus per-stage evidence): +``` +FINDING: +- Title: Upload → LFI → RCE → LPE Chain +- Severity: Critical +- CWE: CWE-98 +- Endpoint: [entry point] +- Vector: [the full chain, stage by stage] +- Payload: [the key payloads/commands per stage] +- Evidence: [raw output proving EACH stage actually executed] +- Impact: Host compromise from a non-executable upload chained through LFI +- Remediation: Fix LFI (allowlist includes); validate uploads; harden host +- chains_from: [ids of the prerequisite findings this builds on] +``` + +## System Prompt +You are an exploit-chaining specialist. Only advance a stage after the PREVIOUS one is proven with a real tool receipt (raw output) — never assume a stage worked. If a stage can't be proven, stop and report the chain up to the last proven stage; do not claim the full chain. AUTHORIZED engagement; no destructive/DoS actions. Each reported stage must carry its own evidence. Credits: Joas A Santos & Red Team Leaders. diff --git a/agents_md/chains/chain_upload_to_rce.md b/agents_md/chains/chain_upload_to_rce.md new file mode 100644 index 0000000..9f86131 --- /dev/null +++ b/agents_md/chains/chain_upload_to_rce.md @@ -0,0 +1,43 @@ +# File Upload → RCE Chain Agent + +## User Prompt +You are executing a multi-stage ATTACK CHAIN against **{target}**: insecure file upload → webshell → remote code execution. + +**Recon Context / prior findings:** +{recon_json} + +**GOAL:** Turn an unrestricted/insecure upload into code execution. + +**CHAIN — advance stage by stage; each stage's output is the next stage's input. Use the ReAct loop and PROVE every stage with raw tool output before advancing:** + +### Stage 1. Probe the upload +- Map accepted types/extensions, storage path, and how files are served +- Test bypasses: double extension, content-type spoof, magic-byte prefix, null byte, .htaccess/.phar + +### Stage 2. Upload a payload +- Place a minimal webshell/handler in a web-served, executable location + +### Stage 3. Locate & trigger +- Find the served URL of the upload; request it to execute + +### Stage 4. Confirm RCE +- Run `id`/`whoami`; capture output proving execution + +### 5. Report Format +Report the chain as ONE finding (plus per-stage evidence): +``` +FINDING: +- Title: File Upload → RCE Chain +- Severity: Critical +- CWE: CWE-434 +- Endpoint: [entry point] +- Vector: [the full chain, stage by stage] +- Payload: [the key payloads/commands per stage] +- Evidence: [raw output proving EACH stage actually executed] +- Impact: Remote code execution via uploaded executable content +- Remediation: Validate type by content; randomize names; store outside webroot; non-exec storage +- chains_from: [ids of the prerequisite findings this builds on] +``` + +## System Prompt +You are an exploit-chaining specialist. Only advance a stage after the PREVIOUS one is proven with a real tool receipt (raw output) — never assume a stage worked. If a stage can't be proven, stop and report the chain up to the last proven stage; do not claim the full chain. AUTHORIZED engagement; no destructive/DoS actions. Each reported stage must carry its own evidence. Credits: Joas A Santos & Red Team Leaders. diff --git a/agents_md/chains/chain_xss_to_account_takeover.md b/agents_md/chains/chain_xss_to_account_takeover.md new file mode 100644 index 0000000..39573f8 --- /dev/null +++ b/agents_md/chains/chain_xss_to_account_takeover.md @@ -0,0 +1,42 @@ +# XSS → Session/Account Takeover Chain Agent + +## User Prompt +You are executing a multi-stage ATTACK CHAIN against **{target}**: stored/reflected XSS → session or token theft → account takeover. + +**Recon Context / prior findings:** +{recon_json} + +**GOAL:** Escalate XSS into full takeover of a victim (incl. admin) account. + +**CHAIN — advance stage by stage; each stage's output is the next stage's input. Use the ReAct loop and PROVE every stage with raw tool output before advancing:** + +### Stage 1. Prove execution +- Confirm the payload executes in the victim's browser context (Playwright: alert/DOM), not just reflects + +### Stage 2. Steal the session +- Exfiltrate the session cookie/JWT/CSRF token to a collaborator, or perform actions in-context if HttpOnly + +### Stage 3. Take over the account +- Replay the stolen session, or change email/password/MFA via in-context requests + +### Stage 4. Confirm + escalate +- Prove control of the victim account; target an admin for privilege escalation + +### 5. Report Format +Report the chain as ONE finding (plus per-stage evidence): +``` +FINDING: +- Title: XSS → Session/Account Takeover Chain +- Severity: High +- CWE: CWE-79 +- Endpoint: [entry point] +- Vector: [the full chain, stage by stage] +- Payload: [the key payloads/commands per stage] +- Evidence: [raw output proving EACH stage actually executed] +- Impact: Account takeover (incl. privileged) via client-side execution +- Remediation: Output encoding + CSP; HttpOnly/SameSite cookies; rotate tokens +- chains_from: [ids of the prerequisite findings this builds on] +``` + +## System Prompt +You are an exploit-chaining specialist. Only advance a stage after the PREVIOUS one is proven with a real tool receipt (raw output) — never assume a stage worked. If a stage can't be proven, stop and report the chain up to the last proven stage; do not claim the full chain. AUTHORIZED engagement; no destructive/DoS actions. Each reported stage must carry its own evidence. Credits: Joas A Santos & Red Team Leaders. diff --git a/neurosploit-rs/app/src/main.rs b/neurosploit-rs/app/src/main.rs index 0b3cf65..eaafafd 100644 --- a/neurosploit-rs/app/src/main.rs +++ b/neurosploit-rs/app/src/main.rs @@ -201,8 +201,8 @@ async fn main() -> anyhow::Result<()> { Cmd::Agents => { let lib = agents::load(&base); println!( - "{{\"vulns\":{},\"recon\":{},\"code\":{},\"infra\":{},\"meta\":{},\"total\":{}}}", - lib.vulns.len(), lib.recon.len(), lib.code.len(), lib.infra.len(), lib.meta.len(), lib.total() + "{{\"vulns\":{},\"recon\":{},\"code\":{},\"infra\":{},\"chains\":{},\"meta\":{},\"total\":{}}}", + lib.vulns.len(), lib.recon.len(), lib.code.len(), lib.infra.len(), lib.chains.len(), lib.meta.len(), lib.total() ); } Cmd::Models => { diff --git a/neurosploit-rs/app/src/repl.rs b/neurosploit-rs/app/src/repl.rs index 050a861..c8ae501 100644 --- a/neurosploit-rs/app/src/repl.rs +++ b/neurosploit-rs/app/src/repl.rs @@ -139,13 +139,12 @@ enum Reader { } impl Reader { - fn new(base: &Path) -> Reader { + fn new(_base: &Path) -> Reader { if std::io::stdin().is_terminal() { let cfg = Config::builder().auto_add_history(false).build(); if let Ok(mut ed) = Editor::::with_config(cfg) { ed.set_helper(Some(NsHelper)); - let hist = base.join("data").join("repl_history.txt"); - std::fs::create_dir_all(hist.parent().unwrap()).ok(); + let hist = proj_dir().join("history.txt"); let _ = ed.load_history(&hist); return Reader::Rl(Box::new(ed), hist); } @@ -200,9 +199,11 @@ pub async fn repl(base: &Path) -> anyhow::Result<()> { println!(" Type \x1b[36m/help\x1b[0m to start, \x1b[36m/run\x1b[0m to launch, \x1b[36m/quit\x1b[0m to exit. (↑/↓ recalls commands)\n"); let mut s = Session::default(); + let resumed = load_session(&mut s); let mut history: Vec = load_runs(base); - if !history.is_empty() { - println!(" loaded {} past run(s) — /runs to list\n", history.len()); + if resumed || !history.is_empty() { + println!(" ↻ resumed project session from {} — {} past run(s)\n", + proj_dir().display(), history.len()); } let mut reader = Reader::new(base); show(&s); @@ -281,12 +282,12 @@ pub async fn repl(base: &Path) -> anyhow::Result<()> { "/votes" => { s.vote_n = arg.parse().unwrap_or(s.vote_n); println!(" votes: {}", s.vote_n); } "/agents" => { s.max_agents = arg.parse().unwrap_or(s.max_agents); println!(" max agents: {}", s.max_agents); } "/clear" => { print!("\x1b[2J\x1b[H"); } - "/run" | "/go" => { run(base, &s, &mut history).await; save_runs(base, &history); } + "/run" | "/go" => { save_session(&s); run(base, &s, &mut history).await; save_runs(base, &history); } "/runs" | "/history" => list_runs(&history), "/results" => results(&history, arg), "/report" => open_report(&history, arg), "/status" => run_status(&history, arg), - "/quit" | "/exit" | "/q" => { println!(" bye."); break; } + "/quit" | "/exit" | "/q" => { save_session(&s); println!(" session saved → {} · bye.", proj_dir().display()); break; } other => println!(" unknown command '{other}' — try /help"), } } @@ -423,20 +424,61 @@ async fn run(base: &Path, s: &Session, history: &mut Vec) { } } -fn runs_path(base: &Path) -> std::path::PathBuf { - base.join("data").join("repl_runs.json") +/// Project-local store: `/.neurosploit/` so each project keeps its own +/// session, run history and command history (resume on reopen). No DB needed — +/// it's structured state, not semantic search. +pub(crate) fn proj_dir() -> std::path::PathBuf { + let d = std::env::current_dir().unwrap_or_else(|_| std::path::PathBuf::from(".")).join(".neurosploit"); + std::fs::create_dir_all(&d).ok(); + d } -fn load_runs(base: &Path) -> Vec { - std::fs::read_to_string(runs_path(base)).ok() +fn runs_path(_base: &Path) -> std::path::PathBuf { proj_dir().join("runs.json") } +fn load_runs(_base: &Path) -> Vec { + std::fs::read_to_string(runs_path(_base)).ok() .and_then(|t| serde_json::from_str(&t).ok()) .unwrap_or_default() } -fn save_runs(base: &Path, history: &[RunRecord]) { - let p = runs_path(base); - if let Some(dir) = p.parent() { std::fs::create_dir_all(dir).ok(); } +fn save_runs(_base: &Path, history: &[RunRecord]) { + let p = runs_path(_base); if let Ok(j) = serde_json::to_string_pretty(history) { std::fs::write(p, j).ok(); } } +/// Persistable snapshot of the session config (resume across restarts). +#[derive(Serialize, Deserialize, Default)] +struct Snapshot { + models: Vec, + subscription: bool, + mcp: bool, + vote_n: usize, + max_agents: usize, + target: Option, + repo: Option, + auth: Option, + creds: Option, + instructions: Option, +} +fn session_path() -> std::path::PathBuf { proj_dir().join("session.json") } +fn save_session(s: &Session) { + let snap = Snapshot { + models: s.models.clone(), subscription: s.subscription, mcp: s.mcp, + vote_n: s.vote_n, max_agents: s.max_agents, target: s.target.clone(), + repo: s.repo.clone(), auth: s.auth.clone(), creds: s.creds.clone(), + instructions: s.instructions.clone(), + }; + if let Ok(j) = serde_json::to_string_pretty(&snap) { std::fs::write(session_path(), j).ok(); } +} +fn load_session(s: &mut Session) -> bool { + let Ok(txt) = std::fs::read_to_string(session_path()) else { return false }; + let Ok(snap) = serde_json::from_str::(&txt) else { return false }; + if !snap.models.is_empty() { s.models = snap.models; } + s.subscription = snap.subscription; s.mcp = snap.mcp; + if snap.vote_n > 0 { s.vote_n = snap.vote_n; } + s.max_agents = snap.max_agents; + s.target = snap.target; s.repo = snap.repo; s.auth = snap.auth; + s.creds = snap.creds; s.instructions = snap.instructions; + true +} + fn pick<'a>(history: &'a [RunRecord], arg: &str) -> Option<&'a RunRecord> { if history.is_empty() { println!(" no runs yet — /run first."); return None; } if arg.trim().is_empty() { return history.last(); } diff --git a/neurosploit-rs/crates/harness/src/agents.rs b/neurosploit-rs/crates/harness/src/agents.rs index 824fa4a..99d4a97 100644 --- a/neurosploit-rs/crates/harness/src/agents.rs +++ b/neurosploit-rs/crates/harness/src/agents.rs @@ -24,11 +24,13 @@ pub struct Library { pub recon: Vec, pub code: Vec, pub infra: Vec, + pub chains: Vec, } impl Library { pub fn total(&self) -> usize { - self.vulns.len() + self.meta.len() + self.recon.len() + self.code.len() + self.infra.len() + self.vulns.len() + self.meta.len() + self.recon.len() + self.code.len() + + self.infra.len() + self.chains.len() } } @@ -41,6 +43,7 @@ pub fn load(base: &Path) -> Library { recon: load_dir(&root.join("recon"), "recon"), code: load_dir(&root.join("code"), "code"), infra: load_dir(&root.join("infra"), "infra"), + chains: load_dir(&root.join("chains"), "chain"), } } diff --git a/neurosploit-rs/crates/harness/src/pipeline.rs b/neurosploit-rs/crates/harness/src/pipeline.rs index b766e40..0c65d99 100644 --- a/neurosploit-rs/crates/harness/src/pipeline.rs +++ b/neurosploit-rs/crates/harness/src/pipeline.rs @@ -206,7 +206,7 @@ pub async fn run(cfg: RunConfig, lib: &Library, pool: &ModelPool, tx: Sender>().join("\n"); + // Offer the known chain recipes as a menu so the LLM applies proven multi-stage paths. + let recipes: String = chains.iter().map(|a| format!("- {}", a.title.replace(" Agent", ""))).collect::>().join("\n"); + let recipe_block = if recipes.is_empty() { String::new() } else { format!("KNOWN CHAIN RECIPES (apply any that fit):\n{recipes}\n\n") }; let _ = tx.send(format!("chaining {} confirmed finding(s) for deeper impact…", confirmed.len())).await; let recon_ctx: String = recon.chars().take(2500).collect(); let user = format!( - "AUTHORIZED engagement on {target}.\n\n{directives}{react}{doctrine}\ + "AUTHORIZED engagement on {target}.\n\n{directives}{react}{doctrine}{recipe_block}\ CONFIRMED FINDINGS TO CHAIN:\n{summary}\n\nRecon:\n{recon_ctx}\n\n\ - Chain these into deeper impact and PROVE it. Reply ONLY a JSON array of NEW findings \ + Chain these into deeper impact (e.g. SQLi→RCE→LPE, SSRF→cloud creds, upload→LFI→RCE) and PROVE each stage. \ + Reply ONLY a JSON array of NEW findings \ (may be []): {{id,title,severity,cwe,endpoint,payload,evidence,impact,remediation,confidence}}.", react = REACT_DOCTRINE, doctrine = tool_doctrine(pool.mcp_config.is_some()), ); @@ -951,7 +955,7 @@ pub async fn run_host(cfg: RunConfig, lib: &Library, pool: &ModelPool, tx: Sende let candidates = dedup_findings(raw.iter().flat_map(|(_, _, f)| f.clone()).collect()); let _ = tx.send(format!("{} candidate finding(s) (deduped) — validating", candidates.len())).await; let mut findings = validate(candidates, pool, VOTE_SYS, cfg.vote_n, &tx).await; - let chained = chain_round(pool, &cfg.target, &recon, &operator_directives(&cfg), &findings, &tx).await; + let chained = chain_round(pool, &cfg.target, &recon, &operator_directives(&cfg), &findings, &lib.chains, &tx).await; if !chained.is_empty() { let extra = validate(dedup_findings(chained), pool, VOTE_SYS, cfg.vote_n, &tx).await; findings.extend(extra); diff --git a/scripts/build_chain_agents.py b/scripts/build_chain_agents.py new file mode 100644 index 0000000..87440c8 --- /dev/null +++ b/scripts/build_chain_agents.py @@ -0,0 +1,201 @@ +#!/usr/bin/env python3 +""" +NeuroSploit v3.5.1 — attack-chain agents. + +Each agent is a multi-stage exploitation-chaining playbook: take a confirmed +entry-point weakness and escalate it through concrete stages to deeper impact +(e.g. SQLi → RCE → local privilege escalation). Writes agents_md/chains/*.md. +Credits: Joas A Santos & Red Team Leaders. +""" +import os +ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +OUT = os.path.join(ROOT, "agents_md", "chains") + + +def render(a): + L = [f"# {a['title']} Agent\n", "## User Prompt", + f"You are executing a multi-stage ATTACK CHAIN against **{{target}}**: {a['chain']}.\n", + "**Recon Context / prior findings:**\n{recon_json}\n", + f"**GOAL:** {a['goal']}\n", + "**CHAIN — advance stage by stage; each stage's output is the next stage's input. " + "Use the ReAct loop and PROVE every stage with raw tool output before advancing:**\n"] + for i, (stage, bs) in enumerate(a["stages"], 1): + L.append(f"### Stage {i}. {stage}") + L += [f"- {b}" for b in bs] + L.append("") + n = len(a["stages"]) + 1 + L += [f"### {n}. Report Format", + "Report the chain as ONE finding (plus per-stage evidence):", "```", "FINDING:", + f"- Title: {a['title']}", f"- Severity: {a['sev']}", f"- CWE: {a['cwe']}", + "- Endpoint: [entry point]", "- Vector: [the full chain, stage by stage]", + "- Payload: [the key payloads/commands per stage]", + "- Evidence: [raw output proving EACH stage actually executed]", + f"- Impact: {a['impact']}", f"- Remediation: {a['fix']}", + "- chains_from: [ids of the prerequisite findings this builds on]", "```\n", + "## System Prompt", a["system"]] + return "\n".join(L) + "\n" + + +def A(name, title, chain, goal, cwe, sev, impact, fix, stages): + return {"name": name, "title": title, "chain": chain, "goal": goal, "cwe": cwe, + "sev": sev, "impact": impact, "fix": fix, "stages": stages, + "system": ("You are an exploit-chaining specialist. Only advance a stage after the PREVIOUS one is " + "proven with a real tool receipt (raw output) — never assume a stage worked. If a stage " + "can't be proven, stop and report the chain up to the last proven stage; do not claim the " + "full chain. AUTHORIZED engagement; no destructive/DoS actions. Each reported stage must " + "carry its own evidence. Credits: Joas A Santos & Red Team Leaders.")} + + +CHAINS = [ + A("chain_sqli_to_rce_to_lpe", + "SQLi → RCE → Local PrivEsc Chain", + "SQL injection → command execution → local privilege escalation", + "Turn a database-layer injection into root/SYSTEM on the host.", + "CWE-89", "Critical", + "Full host compromise originating from a web injection", + "Parameterize queries; least-privilege DB account; harden host; patch local vectors", + [("Exploit the SQL injection", ["Confirm injection (error/boolean/time); identify DBMS and privileges", + "Enumerate whether stacked queries / FILE / xp_cmdshell / INTO OUTFILE are available"]), + ("Pivot SQLi → RCE", ["MSSQL: enable & use `xp_cmdshell`; MySQL: `INTO OUTFILE` a webshell to a known web path; PostgreSQL: `COPY ... PROGRAM`", + "Confirm OS command execution with `id`/`whoami` output"]), + ("Establish a foothold", ["Drop/upgrade to a stable shell as the web/db service user"]), + ("Local privilege escalation", ["Enumerate SUID/sudo/cron/kernel (Linux) or token/service/unquoted-path (Windows)", + "Escalate to root/SYSTEM and prove with a privileged command output"])]), + A("chain_ssrf_to_aws_compromise", + "SSRF → AWS Credential Compromise Chain", + "SSRF → cloud metadata → IAM credentials → cloud account access", + "Convert a server-side request forgery into valid AWS credentials and account access.", + "CWE-918", "Critical", + "Cloud account compromise via stolen IAM role credentials", + "Enforce IMDSv2 hop-limit=1; egress allowlists; SSRF input validation; scoped IAM roles", + [("Confirm the SSRF primitive", ["Find a server-side fetch you control (url/webhook/import/pdf/image param)", + "Prove it reaches an attacker-controlled / internal host"]), + ("Reach the metadata service", ["IMDSv2: PUT `/latest/api/token` then GET with the token header; else IMDSv1 GET", + "Retrieve `/latest/meta-data/iam/security-credentials/`"]), + ("Harvest IAM credentials", ["Capture AccessKeyId/SecretAccessKey/Token from the metadata response"]), + ("Use the credentials (in scope)", ["`aws sts get-caller-identity` to confirm; enumerate permitted actions read-only", + "Prove access to at least one resource the role can reach"])]), + A("chain_ssrf_to_rce", + "SSRF → RCE Chain", + "SSRF → internal service abuse → remote code execution", + "Escalate an SSRF into code execution via a reachable internal service.", + "CWE-918", "Critical", + "Remote code execution pivoted through an internal service", + "Egress controls; authenticate internal services; SSRF allowlists", + [("Confirm SSRF + map internals", ["Prove the SSRF; port-scan internal hosts through it (gopher/http)", + "Identify exploitable internal services (Redis, unauth admin, CI, internal API)"]), + ("Weaponize the internal service", ["e.g. Redis → write SSH key/cron/module; internal Jenkins/Actuator → job/exec; gopher:// to craft raw protocol payloads"]), + ("Achieve RCE", ["Trigger command execution on the internal/back-end host"]), + ("Confirm", ["Prove execution with an OOB callback or command output tied to a unique marker"])]), + A("chain_upload_to_rce", + "File Upload → RCE Chain", + "insecure file upload → webshell → remote code execution", + "Turn an unrestricted/insecure upload into code execution.", + "CWE-434", "Critical", + "Remote code execution via uploaded executable content", + "Validate type by content; randomize names; store outside webroot; non-exec storage", + [("Probe the upload", ["Map accepted types/extensions, storage path, and how files are served", + "Test bypasses: double extension, content-type spoof, magic-byte prefix, null byte, .htaccess/.phar"]), + ("Upload a payload", ["Place a minimal webshell/handler in a web-served, executable location"]), + ("Locate & trigger", ["Find the served URL of the upload; request it to execute"]), + ("Confirm RCE", ["Run `id`/`whoami`; capture output proving execution"])]), + A("chain_upload_lfi_rce_lpe", + "Upload → LFI → RCE → LPE Chain", + "file upload + local file inclusion → log/session poisoning → RCE → privilege escalation", + "Chain a benign upload and an LFI into code execution and then root.", + "CWE-98", "Critical", + "Host compromise from a non-executable upload chained through LFI", + "Fix LFI (allowlist includes); validate uploads; harden host", + [("Confirm the LFI", ["Prove local file inclusion (read /etc/passwd or app config); identify wrappers (php://, data://, zip://)"]), + ("Plant controllable content via upload", ["Upload a file whose path/content you can later include (image with PHP, zip for zip:// , or use the LFI to read your uploaded file)"]), + ("LFI → RCE", ["Include the planted file, or poison logs/session/`/proc/self/environ` then include it to execute code"]), + ("Confirm RCE then escalate", ["Prove command execution; then enumerate and perform local privilege escalation to root/SYSTEM"])]), + A("chain_xss_to_account_takeover", + "XSS → Session/Account Takeover Chain", + "stored/reflected XSS → session or token theft → account takeover", + "Escalate XSS into full takeover of a victim (incl. admin) account.", + "CWE-79", "High", + "Account takeover (incl. privileged) via client-side execution", + "Output encoding + CSP; HttpOnly/SameSite cookies; rotate tokens", + [("Prove execution", ["Confirm the payload executes in the victim's browser context (Playwright: alert/DOM), not just reflects"]), + ("Steal the session", ["Exfiltrate the session cookie/JWT/CSRF token to a collaborator, or perform actions in-context if HttpOnly"]), + ("Take over the account", ["Replay the stolen session, or change email/password/MFA via in-context requests"]), + ("Confirm + escalate", ["Prove control of the victim account; target an admin for privilege escalation"])]), + A("chain_idor_to_takeover", + "IDOR → Mass Account Takeover Chain", + "IDOR → cross-account data → credential/role manipulation → takeover", + "Chain object-level authz failure into taking over arbitrary accounts.", + "CWE-639", "High", + "Mass account takeover via broken object-level authorization", + "Enforce per-object ownership on every endpoint; indirect references", + [("Confirm the IDOR", ["Access another user's object with your session, proven by their data"]), + ("Find a state-changing IDOR", ["Locate IDOR on email/password/role/API-key endpoints"]), + ("Manipulate the victim account", ["Change a victim's email or reset token / elevate role via the IDOR"]), + ("Confirm takeover", ["Log in as / act as the victim; demonstrate control"])]), + A("chain_ssti_to_rce_to_cloud", + "SSTI → RCE → Cloud Pivot Chain", + "template injection → RCE → host creds → cloud/lateral movement", + "Go from template injection to code execution to cloud or lateral access.", + "CWE-1336", "Critical", + "Cloud/lateral compromise originating from template injection", + "Never render user input as templates; sandbox; scope host IAM/creds", + [("Confirm SSTI → RCE", ["Fingerprint the engine (`{{7*7}}` etc.); use the gadget to execute a command; prove with output"]), + ("Loot the host", ["Read env/config/instance metadata for cloud creds, DB creds, tokens"]), + ("Pivot", ["Use recovered creds against cloud APIs or adjacent internal hosts"]), + ("Confirm impact", ["Prove access to a cloud resource or a second host with evidence"])]), + A("chain_default_creds_to_domain", + "Default Creds → Foothold → Domain Compromise Chain", + "default/weak creds → host foothold → AD escalation → domain dominance", + "Chain an exposed credential into Active Directory domain compromise.", + "CWE-798", "Critical", + "Domain compromise from a single weak/default credential", + "Rotate defaults; unique strong passwords; tiered admin; monitor", + [("Get the foothold", ["Authenticate with the default/weak/reused credential (SSH/WinRM/SMB/web)"]), + ("Enumerate AD", ["From the foothold, run BloodHound/netexec; map attack paths, roastable accounts, ACLs"]), + ("Escalate in AD", ["Kerberoast/AS-REP-roast, abuse an ACL edge, or relay — recover higher-priv creds"]), + ("Reach domain dominance", ["Demonstrate DCSync or DA-equivalent access (single test account) proving the path"])]), + A("chain_deserialization_to_rce", + "Insecure Deserialization → RCE Chain", + "untrusted deserialization → gadget chain → remote code execution", + "Turn a deserialization sink into reliable code execution.", + "CWE-502", "Critical", + "Remote code execution via unsafe object deserialization", + "Never deserialize untrusted data; allowlist types; safe formats", + [("Locate the sink", ["Identify where attacker data is deserialized (cookie/param/file/RPC); fingerprint the format/library"]), + ("Build the gadget", ["Select a working gadget chain (ysoserial/ysoserial.net/PyYAML/pickle) for the target stack"]), + ("Execute", ["Deliver the payload to the sink"]), + ("Confirm", ["Prove execution via OOB callback or command output with a unique marker"])]), + A("chain_exposed_git_to_rce", + "Exposed .git/.env → Secret → RCE Chain", + "exposed source/secrets → recovered credentials → authenticated RCE", + "Chain leaked source/secrets into authenticated code execution.", + "CWE-527", "High", + "Code execution using credentials recovered from exposed source/secrets", + "Block dotfiles from web; rotate leaked secrets; vault storage", + [("Recover the source/secrets", ["Dump exposed `.git` (git-dumper) or read `.env`/config; extract keys/creds/tokens"]), + ("Validate the secrets", ["Confirm a recovered credential/key is live (admin panel, cloud, DB, CI)"]), + ("Gain execution", ["Use the access to deploy code / run a CI job / write a webshell / exec via admin feature"]), + ("Confirm RCE", ["Prove command execution with output"])]), + A("chain_subdomain_takeover_to_phishing", + "Subdomain Takeover → Trusted Phishing/Cookie Chain", + "dangling DNS → subdomain takeover → trusted-origin abuse", + "Chain a dangling record into hosting attacker content on a trusted subdomain.", + "CWE-350", "High", + "Trusted-origin abuse (cookie theft / phishing / OAuth) via a taken-over subdomain", + "Remove dangling DNS; monitor; scope cookies/CSP per-host", + [("Find the dangling record", ["Identify a CNAME/A pointing to an unclaimed provider resource"]), + ("Claim it", ["Register the resource so the subdomain serves your content (benign PoC)"]), + ("Abuse the trust", ["Show impact: wildcard-cookie capture, OAuth redirect trust, or CSP allowlist bypass"]), + ("Confirm", ["Demonstrate the concrete trusted-origin abuse with evidence"])]), +] + + +def main(): + os.makedirs(OUT, exist_ok=True) + for a in CHAINS: + open(os.path.join(OUT, a["name"] + ".md"), "w").write(render(a)) + print(f"wrote {len(CHAINS)} chain agents to {OUT}") + + +if __name__ == "__main__": + main()