exploitgraph 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. core/__init__.py +0 -0
  2. core/attack_graph.py +83 -0
  3. core/aws_client.py +284 -0
  4. core/config.py +83 -0
  5. core/console.py +469 -0
  6. core/context_engine.py +172 -0
  7. core/correlator.py +476 -0
  8. core/http_client.py +243 -0
  9. core/logger.py +97 -0
  10. core/module_loader.py +69 -0
  11. core/risk_engine.py +47 -0
  12. core/session_manager.py +254 -0
  13. exploitgraph-1.0.0.dist-info/METADATA +429 -0
  14. exploitgraph-1.0.0.dist-info/RECORD +42 -0
  15. exploitgraph-1.0.0.dist-info/WHEEL +5 -0
  16. exploitgraph-1.0.0.dist-info/entry_points.txt +2 -0
  17. exploitgraph-1.0.0.dist-info/licenses/LICENSE +21 -0
  18. exploitgraph-1.0.0.dist-info/top_level.txt +2 -0
  19. modules/__init__.py +0 -0
  20. modules/base.py +82 -0
  21. modules/cloud/__init__.py +0 -0
  22. modules/cloud/aws_credential_validator.py +340 -0
  23. modules/cloud/azure_enum.py +289 -0
  24. modules/cloud/cloudtrail_analyzer.py +494 -0
  25. modules/cloud/gcp_enum.py +272 -0
  26. modules/cloud/iam_enum.py +321 -0
  27. modules/cloud/iam_privilege_escalation.py +515 -0
  28. modules/cloud/metadata_check.py +315 -0
  29. modules/cloud/s3_enum.py +469 -0
  30. modules/discovery/__init__.py +0 -0
  31. modules/discovery/http_enum.py +235 -0
  32. modules/discovery/subdomain_enum.py +260 -0
  33. modules/exploitation/__init__.py +0 -0
  34. modules/exploitation/api_exploit.py +403 -0
  35. modules/exploitation/jwt_attack.py +346 -0
  36. modules/exploitation/ssrf_scanner.py +258 -0
  37. modules/reporting/__init__.py +0 -0
  38. modules/reporting/html_report.py +446 -0
  39. modules/reporting/json_export.py +107 -0
  40. modules/secrets/__init__.py +0 -0
  41. modules/secrets/file_secrets.py +358 -0
  42. modules/secrets/git_secrets.py +267 -0
@@ -0,0 +1,254 @@
1
+ """ExploitGraph - SQLite-backed multi-session manager."""
2
+ from __future__ import annotations
3
+ import json, sqlite3, hashlib
4
+ from datetime import datetime, timezone
5
+ from pathlib import Path
6
+ from typing import Any, Optional
7
+
8
+
9
+ def _now() -> str:
10
+ """Current UTC time as ISO string — Python 3.9+ compatible."""
11
+ return datetime.now(timezone.utc).isoformat()
12
+
13
+
14
+ SESSION_DIR = Path(__file__).parent.parent / "sessions"
15
+ SESSION_DIR.mkdir(exist_ok=True)
16
+ DB_PATH = SESSION_DIR / "exploitgraph.db"
17
+
18
+
19
+ def _conn() -> sqlite3.Connection:
20
+ c = sqlite3.connect(DB_PATH)
21
+ c.row_factory = sqlite3.Row
22
+ c.execute("PRAGMA journal_mode=WAL")
23
+ return c
24
+
25
+
26
+ def _init():
27
+ c = _conn()
28
+ c.executescript("""
29
+ CREATE TABLE IF NOT EXISTS sessions (
30
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
31
+ session_id TEXT UNIQUE NOT NULL, name TEXT, target TEXT NOT NULL,
32
+ mode TEXT DEFAULT 'offensive', status TEXT DEFAULT 'active',
33
+ risk_score REAL DEFAULT 0.0, created_at TEXT NOT NULL, updated_at TEXT NOT NULL
34
+ );
35
+ CREATE TABLE IF NOT EXISTS findings (
36
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
37
+ session_id TEXT NOT NULL, module TEXT NOT NULL, title TEXT NOT NULL,
38
+ severity TEXT NOT NULL, cvss_score REAL DEFAULT 0.0,
39
+ description TEXT, evidence TEXT, recommendation TEXT,
40
+ aws_parallel TEXT, mitre_technique TEXT, created_at TEXT NOT NULL,
41
+ FOREIGN KEY (session_id) REFERENCES sessions(session_id)
42
+ );
43
+ CREATE TABLE IF NOT EXISTS secrets (
44
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
45
+ session_id TEXT NOT NULL, secret_type TEXT NOT NULL, value TEXT NOT NULL,
46
+ source TEXT, severity TEXT DEFAULT 'HIGH', description TEXT,
47
+ aws_parallel TEXT, created_at TEXT NOT NULL,
48
+ FOREIGN KEY (session_id) REFERENCES sessions(session_id)
49
+ );
50
+ CREATE TABLE IF NOT EXISTS graph_nodes (
51
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
52
+ session_id TEXT NOT NULL, node_id TEXT NOT NULL, label TEXT,
53
+ node_type TEXT, severity TEXT DEFAULT 'INFO', details TEXT,
54
+ UNIQUE(session_id, node_id),
55
+ FOREIGN KEY (session_id) REFERENCES sessions(session_id)
56
+ );
57
+ CREATE TABLE IF NOT EXISTS graph_edges (
58
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
59
+ session_id TEXT NOT NULL, source TEXT NOT NULL, target TEXT NOT NULL,
60
+ label TEXT, technique TEXT,
61
+ FOREIGN KEY (session_id) REFERENCES sessions(session_id)
62
+ );
63
+ """)
64
+ c.commit(); c.close()
65
+
66
+ _init()
67
+
68
+
69
+ class Session:
70
+ def __init__(self, target: str, name: str = "", mode: str = "offensive"):
71
+ self.target = target.rstrip("/")
72
+ self.name = name or f"session_{datetime.now(timezone.utc).strftime('%H%M%S')}"
73
+ self.mode = mode
74
+ self.session_id = "EG-" + hashlib.md5(
75
+ f"{target}{_now()}".encode()
76
+ ).hexdigest()[:8].upper()
77
+ self.created_at = _now()
78
+ self.risk_score = 0.0
79
+
80
+ self.endpoints: list[dict] = []
81
+ self.exposed_files: list[dict] = []
82
+ self.secrets: list[dict] = []
83
+ self.findings: list[dict] = []
84
+ self.valid_creds: list[dict] = []
85
+ self.graph_nodes: list[dict] = []
86
+ self.graph_edges: list[dict] = []
87
+ self.exploit_results: list[dict] = []
88
+ self.notes: list[str] = []
89
+ self._scratch: dict = {}
90
+
91
+ self._save()
92
+
93
+ def _save(self):
94
+ c = _conn()
95
+ c.execute(
96
+ "INSERT OR REPLACE INTO sessions "
97
+ "(session_id,name,target,mode,status,risk_score,created_at,updated_at) "
98
+ "VALUES (?,?,?,?,?,?,?,?)",
99
+ (self.session_id, self.name, self.target, self.mode,
100
+ "active", self.risk_score, self.created_at, _now())
101
+ )
102
+ c.commit(); c.close()
103
+
104
+ def add_finding(self, *, title, severity, description, evidence, recommendation,
105
+ module="unknown", cvss_score=0.0, aws_parallel="", mitre_technique=""):
106
+ row = dict(session_id=self.session_id, module=module, title=title,
107
+ severity=severity, cvss_score=cvss_score, description=description,
108
+ evidence=evidence, recommendation=recommendation,
109
+ aws_parallel=aws_parallel, mitre_technique=mitre_technique,
110
+ created_at=_now())
111
+ self.findings.append(row)
112
+ c = _conn()
113
+ c.execute(
114
+ "INSERT INTO findings "
115
+ "(session_id,module,title,severity,cvss_score,description,evidence,"
116
+ "recommendation,aws_parallel,mitre_technique,created_at) "
117
+ "VALUES (:session_id,:module,:title,:severity,:cvss_score,:description,"
118
+ ":evidence,:recommendation,:aws_parallel,:mitre_technique,:created_at)", row)
119
+ c.commit(); c.close()
120
+
121
+ def add_secret(self, *, secret_type, value, source, severity="HIGH",
122
+ description="", aws_parallel=""):
123
+ if any(s["value"] == value for s in self.secrets):
124
+ return
125
+ row = dict(session_id=self.session_id, secret_type=secret_type, value=value,
126
+ source=source, severity=severity, description=description,
127
+ aws_parallel=aws_parallel, created_at=_now())
128
+ self.secrets.append(row)
129
+ c = _conn()
130
+ c.execute(
131
+ "INSERT INTO secrets "
132
+ "(session_id,secret_type,value,source,severity,description,aws_parallel,created_at) "
133
+ "VALUES (:session_id,:secret_type,:value,:source,:severity,"
134
+ ":description,:aws_parallel,:created_at)", row)
135
+ c.commit(); c.close()
136
+
137
+ def add_graph_node(self, node_id, label, node_type, severity="INFO", details=""):
138
+ if any(n["node_id"] == node_id for n in self.graph_nodes):
139
+ return
140
+ row = dict(session_id=self.session_id, node_id=node_id, label=label,
141
+ node_type=node_type, severity=severity, details=details)
142
+ self.graph_nodes.append(row)
143
+ c = _conn()
144
+ c.execute(
145
+ "INSERT OR IGNORE INTO graph_nodes "
146
+ "(session_id,node_id,label,node_type,severity,details) "
147
+ "VALUES (:session_id,:node_id,:label,:node_type,:severity,:details)", row)
148
+ c.commit(); c.close()
149
+
150
+ def add_graph_edge(self, source, target, label="", technique=""):
151
+ row = dict(session_id=self.session_id, source=source, target=target,
152
+ label=label, technique=technique)
153
+ self.graph_edges.append(row)
154
+ c = _conn()
155
+ c.execute(
156
+ "INSERT INTO graph_edges (session_id,source,target,label,technique) "
157
+ "VALUES (:session_id,:source,:target,:label,:technique)", row)
158
+ c.commit(); c.close()
159
+
160
+ def add_exploit_result(self, module, action, success, detail, data=None):
161
+ self.exploit_results.append(dict(
162
+ module=module, action=action, success=success,
163
+ detail=detail, data=data, timestamp=_now()))
164
+
165
+ def set_scratch(self, key: str, value: Any): self._scratch[key] = value
166
+ def get_scratch(self, key: str, default=None): return self._scratch.get(key, default)
167
+
168
+ def update_risk(self, score: float):
169
+ self.risk_score = score
170
+ c = _conn()
171
+ c.execute("UPDATE sessions SET risk_score=?,updated_at=? WHERE session_id=?",
172
+ (score, _now(), self.session_id))
173
+ c.commit(); c.close()
174
+
175
+ def close(self):
176
+ c = _conn()
177
+ c.execute("UPDATE sessions SET status='closed',updated_at=? WHERE session_id=?",
178
+ (_now(), self.session_id))
179
+ c.commit(); c.close()
180
+
181
+ def summary(self) -> dict:
182
+ sev = {k: 0 for k in ("CRITICAL","HIGH","MEDIUM","LOW","INFO")}
183
+ for f in self.findings:
184
+ key = f.get("severity","INFO")
185
+ sev[key] = sev.get(key, 0) + 1
186
+ return dict(session_id=self.session_id, name=self.name, target=self.target,
187
+ mode=self.mode, risk_score=self.risk_score,
188
+ endpoints=len(self.endpoints), exposed_files=len(self.exposed_files),
189
+ secrets=len(self.secrets), findings=len(self.findings),
190
+ valid_creds=len(self.valid_creds), severity=sev)
191
+
192
+
193
+ class SessionManager:
194
+ def __init__(self):
195
+ self._active: Optional[Session] = None
196
+
197
+ @property
198
+ def active(self) -> Optional[Session]: return self._active
199
+
200
+ def new(self, target: str, name: str = "", mode: str = "offensive") -> Session:
201
+ self._active = Session(target, name, mode)
202
+ return self._active
203
+
204
+ def switch(self, sid: str) -> Optional[Session]:
205
+ c = _conn()
206
+ row = c.execute("SELECT * FROM sessions WHERE session_id=?", (sid,)).fetchone()
207
+ c.close()
208
+ if not row: return None
209
+ s = Session.__new__(Session)
210
+ for k in ("session_id","name","target","mode","risk_score","created_at"):
211
+ setattr(s, k, row[k])
212
+ s._scratch = {}
213
+ c = _conn()
214
+ s.findings = [dict(r) for r in c.execute("SELECT * FROM findings WHERE session_id=?", (sid,)).fetchall()]
215
+ s.secrets = [dict(r) for r in c.execute("SELECT * FROM secrets WHERE session_id=?", (sid,)).fetchall()]
216
+ s.graph_nodes = [dict(r) for r in c.execute("SELECT * FROM graph_nodes WHERE session_id=?", (sid,)).fetchall()]
217
+ s.graph_edges = [dict(r) for r in c.execute("SELECT * FROM graph_edges WHERE session_id=?", (sid,)).fetchall()]
218
+ s.endpoints = []; s.exposed_files = []; s.valid_creds = []
219
+ s.exploit_results = []; s.notes = []
220
+ c.close()
221
+ self._active = s
222
+ return s
223
+
224
+ def list_all(self) -> list[dict]:
225
+ c = _conn()
226
+ rows = c.execute(
227
+ "SELECT session_id,name,target,mode,status,risk_score,created_at "
228
+ "FROM sessions ORDER BY created_at DESC").fetchall()
229
+ c.close()
230
+ return [dict(r) for r in rows]
231
+
232
+ def kill(self, sid: str) -> bool:
233
+ c = _conn()
234
+ n = c.execute("UPDATE sessions SET status='killed' WHERE session_id=?", (sid,)).rowcount
235
+ c.commit(); c.close()
236
+ if self._active and self._active.session_id == sid:
237
+ self._active = None
238
+ return n > 0
239
+
240
+ def get_findings(self, sid: str) -> list[dict]:
241
+ c = _conn()
242
+ rows = c.execute(
243
+ "SELECT * FROM findings WHERE session_id=? ORDER BY cvss_score DESC", (sid,)).fetchall()
244
+ c.close()
245
+ return [dict(r) for r in rows]
246
+
247
+ def get_secrets(self, sid: str) -> list[dict]:
248
+ c = _conn()
249
+ rows = c.execute("SELECT * FROM secrets WHERE session_id=?", (sid,)).fetchall()
250
+ c.close()
251
+ return [dict(r) for r in rows]
252
+
253
+
254
+ session_manager = SessionManager()
@@ -0,0 +1,429 @@
1
+ Metadata-Version: 2.4
2
+ Name: exploitgraph
3
+ Version: 1.0.0
4
+ Summary: Automated attack path discovery and exploitation framework for cloud-native applications
5
+ Author-email: Prajwal Pawar <prajwal@exploitgraph.io>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/prajwalpawar/ExploitGraph
8
+ Project-URL: Repository, https://github.com/prajwalpawar/ExploitGraph
9
+ Project-URL: Bug Tracker, https://github.com/prajwalpawar/ExploitGraph/issues
10
+ Project-URL: Documentation, https://github.com/prajwalpawar/ExploitGraph/wiki
11
+ Keywords: security,pentesting,cloud,aws,attack-path,exploitation
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Information Technology
14
+ Classifier: Topic :: Security
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Environment :: Console
22
+ Classifier: Operating System :: POSIX :: Linux
23
+ Classifier: Operating System :: MacOS
24
+ Requires-Python: >=3.9
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: requests>=2.31.0
28
+ Requires-Dist: colorama>=0.4.6
29
+ Requires-Dist: networkx>=3.2.0
30
+ Requires-Dist: jinja2>=3.1.2
31
+ Requires-Dist: PyJWT>=2.8.0
32
+ Requires-Dist: python-dotenv>=1.0.0
33
+ Requires-Dist: tabulate>=0.9.0
34
+ Requires-Dist: pyyaml>=6.0
35
+ Provides-Extra: aws
36
+ Requires-Dist: boto3>=1.34.0; extra == "aws"
37
+ Requires-Dist: botocore>=1.34.0; extra == "aws"
38
+ Provides-Extra: dev
39
+ Requires-Dist: pytest>=7.0; extra == "dev"
40
+ Requires-Dist: black>=23.0; extra == "dev"
41
+ Requires-Dist: flake8>=6.0; extra == "dev"
42
+ Requires-Dist: mypy>=1.0; extra == "dev"
43
+ Provides-Extra: all
44
+ Requires-Dist: exploitgraph[aws,dev]; extra == "all"
45
+ Dynamic: license-file
46
+
47
+ # ExploitGraph
48
+
49
+ <div align="center">
50
+
51
+ ```
52
+ ███████╗██╗ ██╗██████╗ ██╗ ██████╗ ██╗████████╗ ██████╗ ██████╗ █████╗ ██████╗ ██╗ ██╗
53
+ ██╔════╝╚██╗██╔╝██╔══██╗██║ ██╔═══██╗██║╚══██╔══╝██╔════╝ ██╔══██╗██╔══██╗██╔══██╗██║ ██║
54
+ █████╗ ╚███╔╝ ██████╔╝██║ ██║ ██║██║ ██║ ██║ ███╗██████╔╝███████║██████╔╝███████║
55
+ ██╔══╝ ██╔██╗ ██╔═══╝ ██║ ██║ ██║██║ ██║ ██║ ██║██╔══██╗██╔══██║██╔═══╝ ██╔══██║
56
+ ███████╗██╔╝ ██╗██║ ███████╗╚██████╔╝██║ ██║ ╚██████╔╝██║ ██║██║ ██║██║ ██║ ██║
57
+ ╚══════╝╚═╝ ╚═╝╚═╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝
58
+ ```
59
+
60
+ **Automated Attack Path Discovery & Exploitation Framework**
61
+
62
+ [![Python](https://img.shields.io/badge/Python-3.9%2B-blue?logo=python)](https://python.org)
63
+ [![License](https://img.shields.io/badge/License-MIT-green)](LICENSE)
64
+ [![Platform](https://img.shields.io/badge/Platform-Linux%20%7C%20macOS-lightgrey)](https://github.com/prajwalpawar/ExploitGraph)
65
+ [![Modules](https://img.shields.io/badge/Modules-8%2B-red)](modules/)
66
+ [![AWS](https://img.shields.io/badge/AWS-Cloud%20Security-orange?logo=amazon-aws)](modules/cloud/)
67
+
68
+ </div>
69
+
70
+ ---
71
+
72
+ ## What is ExploitGraph?
73
+
74
+ ExploitGraph is a **modular, open-source attack path discovery framework** that automatically chains cloud misconfigurations, exposed secrets, and application vulnerabilities into a complete kill chain — starting from **zero prior knowledge**.
75
+
76
+ Unlike tools that require credentials first (Pacu) or only audit configurations (Prowler/ScoutSuite), ExploitGraph **starts from nothing** and discovers everything it needs:
77
+
78
+ ```
79
+ Cloud Misconfiguration → Data Exposure → Secret Leakage → API Abuse → Full Compromise
80
+ ```
81
+
82
+ Every step is visualized as an interactive attack graph with MITRE ATT&CK mappings and AWS remediation commands.
83
+
84
+ ### How it differs from existing tools
85
+
86
+ | Tool | Starting Point | Output | Attack Chain |
87
+ |------|---------------|--------|--------------|
88
+ | **Pacu** | Needs IAM credentials | Module results | No chaining |
89
+ | **Prowler** | Needs AWS credentials | Audit findings | No chaining |
90
+ | **ScoutSuite** | Needs AWS credentials | Config report | No chaining |
91
+ | **TruffleHog** | Git repo / S3 bucket | Secret list | No chaining |
92
+ | **ExploitGraph** | **Just a URL** | **Full kill chain + visual graph** | **Automated** |
93
+
94
+ ---
95
+
96
+ ## Features
97
+
98
+ - **msfconsole-style interactive shell** with tab completion
99
+ - **8+ modular attack modules** across discovery, cloud, secrets, exploitation, reporting
100
+ - **Generic — works against any target** (not limited to fintech or specific apps)
101
+ - **Wordlist-driven discovery** — no hardcoded paths
102
+ - **20+ secret patterns** including AWS keys, JWT secrets, Stripe keys, GitHub tokens
103
+ - **Optional boto3 AWS integration** — real S3 ACL checks, IAM enumeration, MFA detection
104
+ - **JWT attack engine** — none-algorithm bypass, weak secret bruteforce
105
+ - **Interactive D3.js attack graph** in HTML report
106
+ - **CVSS scoring** per finding + session risk score (0-10)
107
+ - **MITRE ATT&CK for Cloud** mapping
108
+ - **Multi-session SQLite persistence** — resume scans across sessions
109
+ - **Offensive and defensive modes**
110
+ - **pip-installable** Python package
111
+
112
+ ---
113
+
114
+ ## Installation
115
+
116
+ ### Quick Start
117
+ ```bash
118
+ git clone https://github.com/prajwalpawar/ExploitGraph.git
119
+ cd ExploitGraph
120
+ pip install -r requirements.txt
121
+ python3 exploitgraph.py
122
+ ```
123
+
124
+ ### With AWS Support
125
+ ```bash
126
+ pip install -r requirements.txt
127
+ pip install boto3 botocore
128
+ ```
129
+
130
+ ### Requirements
131
+ - Python 3.9+
132
+ - Linux / macOS (Kali Linux recommended)
133
+ - No AWS credentials required for HTTP-mode scanning
134
+
135
+ ---
136
+
137
+ ## Usage
138
+
139
+ ### Interactive Console
140
+ ```bash
141
+ python3 exploitgraph.py
142
+ ```
143
+
144
+ ```
145
+ exploitgraph> workspace new pentest http://target.com
146
+ exploitgraph> run auto
147
+ ```
148
+
149
+ ### CLI Mode
150
+ ```bash
151
+ # Full automated attack chain
152
+ python3 exploitgraph.py -t http://target.com --auto
153
+
154
+ # Single module
155
+ python3 exploitgraph.py -t http://target.com -m cloud/s3_enum
156
+
157
+ # Defensive audit mode (no exploitation)
158
+ python3 exploitgraph.py -t http://target.com --mode defensive --auto
159
+
160
+ # List all modules
161
+ python3 exploitgraph.py --list-modules
162
+ ```
163
+
164
+ ### Console Commands
165
+ ```
166
+ SESSION
167
+ workspace new <name> <url> Create workspace
168
+ set TARGET http://target.com Set target
169
+ set MODE offensive|defensive Set mode
170
+
171
+ MODULES
172
+ show modules List all modules by category
173
+ use discovery/http_enum Select a module
174
+ options Show module options
175
+ set OPTION value Configure option
176
+ run Execute module
177
+ run auto Full attack chain
178
+ back Deselect module
179
+
180
+ INFORMATION
181
+ show findings Security findings
182
+ show secrets Extracted credentials
183
+ show attack-path ASCII kill chain
184
+ show summary Risk score + stats
185
+ info <module> Module details
186
+ search <keyword> Search modules
187
+
188
+ OUTPUT
189
+ export html HTML report with D3.js graph
190
+ export json JSON for SIEM integration
191
+ export all All formats
192
+
193
+ SESSION MANAGEMENT
194
+ sessions List sessions
195
+ sessions -i <id> Switch session
196
+ sessions -k <id> Kill session
197
+ ```
198
+
199
+ ---
200
+
201
+ ## Modules
202
+
203
+ ### Discovery
204
+ | Module | Description | MITRE |
205
+ |--------|-------------|-------|
206
+ | `discovery/http_enum` | Wordlist-driven endpoint enumeration + tech fingerprinting | T1595.003 |
207
+
208
+ ### Cloud
209
+ | Module | Description | MITRE |
210
+ |--------|-------------|-------|
211
+ | `cloud/s3_enum` | S3 bucket discovery, public ACL detection, file download + boto3 audit | T1530 |
212
+ | `cloud/iam_enum` | IAM user/role enumeration, MFA checks, policy analysis (requires boto3) | T1580, T1078.004 |
213
+
214
+ ### Secrets
215
+ | Module | Description | MITRE |
216
+ |--------|-------------|-------|
217
+ | `secrets/file_secrets` | 20+ pattern regex scanner + Shannon entropy detection | T1552.001 |
218
+
219
+ ### Exploitation
220
+ | Module | Description | MITRE |
221
+ |--------|-------------|-------|
222
+ | `exploitation/api_exploit` | Generic credential testing, admin access, privilege escalation | T1078.004 |
223
+ | `exploitation/jwt_attack` | None-algorithm bypass, weak secret bruteforce, algorithm confusion | T1078, T1550.001 |
224
+
225
+ ### Reporting
226
+ | Module | Description |
227
+ |--------|-------------|
228
+ | `reporting/html_report` | Interactive HTML report with D3.js attack graph, CVSS scores, MITRE mapping |
229
+ | `reporting/json_export` | Structured JSON for SIEM/ticketing integration |
230
+
231
+ ---
232
+
233
+ ## Secret Patterns (20+)
234
+
235
+ ExploitGraph detects the following credential types:
236
+
237
+ ```
238
+ AWS Access Key ID AKIA[0-9A-Z]{16}
239
+ AWS Secret Access Key aws_secret_access_key = ...
240
+ JWT Secret jwt_secret_key = ...
241
+ Generic API Key api_key = ...
242
+ Stripe Live Key sk_live_...
243
+ GitHub Token ghp_...
244
+ Google API Key AIza...
245
+ SendGrid API Key SG....
246
+ Slack Token xox[baprs]-...
247
+ Database Password db_password = ...
248
+ Database URL postgresql://user:pass@host
249
+ Private Key -----BEGIN RSA PRIVATE KEY-----
250
+ Bearer Token Authorization: Bearer ...
251
+ Encryption Key aes_key = [hex]
252
+ Admin Credentials admin password = ...
253
+ Twilio SID AC[a-z0-9]{32}
254
+ Webhook Secret webhook_secret = ...
255
+ High-Entropy Strings Shannon entropy > 4.5
256
+ ```
257
+
258
+ ---
259
+
260
+ ## MITRE ATT&CK for Cloud Coverage
261
+
262
+ | Technique | Name | Module |
263
+ |-----------|------|--------|
264
+ | T1595.003 | Wordlist Scanning | http_enum |
265
+ | T1580 | Cloud Infrastructure Discovery | s3_enum, iam_enum |
266
+ | T1530 | Data from Cloud Storage Object | s3_enum |
267
+ | T1552.001 | Credentials in Files | file_secrets |
268
+ | T1552.005 | Cloud Instance Metadata API | file_secrets |
269
+ | T1078.004 | Valid Accounts: Cloud Accounts | api_exploit, iam_enum |
270
+ | T1548 | Abuse Elevation Control Mechanism | api_exploit |
271
+ | T1550.001 | Application Access Token | jwt_attack |
272
+
273
+ ---
274
+
275
+ ## Demo: Vulnerable Target (Viva/Lab Use)
276
+
277
+ A deliberately vulnerable Flask fintech application is included for demonstration:
278
+
279
+ ```bash
280
+ # Terminal 1 — Start target
281
+ cd target && python3 app.py
282
+ # Running at http://127.0.0.1:5000
283
+
284
+ # Terminal 2 — Attack it
285
+ python3 exploitgraph.py -t http://127.0.0.1:5000 --auto
286
+ ```
287
+
288
+ The target simulates:
289
+ - Public S3 bucket with backup archive
290
+ - `.env` file with exposed AWS keys, API keys, JWT secrets
291
+ - Weak admin credentials in deployment notes
292
+ - Unauthenticated admin API endpoints
293
+ - Debug endpoint leaking configuration
294
+
295
+ > **The target app is for controlled lab environments only.**
296
+
297
+ ---
298
+
299
+ ## Writing Custom Modules
300
+
301
+ Create a file in `modules/custom/my_module.py`:
302
+
303
+ ```python
304
+ from modules.base import BaseModule, ModuleResult
305
+
306
+ class MyModule(BaseModule):
307
+ NAME = "my_module"
308
+ DESCRIPTION = "My custom scanner"
309
+ CATEGORY = "discovery"
310
+ SEVERITY = "HIGH"
311
+ MITRE = ["T1595"]
312
+
313
+ OPTIONS = {
314
+ "TARGET": {"default": "", "required": True, "description": "Target URL"},
315
+ }
316
+
317
+ def run(self, session):
318
+ target = self.get_option("TARGET")
319
+ # ... your logic ...
320
+ session.add_finding(
321
+ module="my_module",
322
+ title="Finding Title",
323
+ severity="HIGH",
324
+ description="What was found",
325
+ evidence="Proof",
326
+ recommendation="How to fix",
327
+ cvss_score=7.5,
328
+ )
329
+ return ModuleResult(True, {"found": True})
330
+ ```
331
+
332
+ ExploitGraph automatically discovers and loads it. No configuration needed.
333
+
334
+ ---
335
+
336
+ ## Report Output
337
+
338
+ The HTML report includes:
339
+ - Executive summary with severity breakdown
340
+ - Interactive D3.js attack graph (drag, zoom, hover for details)
341
+ - Expandable findings with CVSS scores
342
+ - Evidence + proof-of-concept per finding
343
+ - AWS CLI remediation commands
344
+ - MITRE ATT&CK technique mapping
345
+ - Full secrets table
346
+ - Exploitation evidence log
347
+ - Session risk score (0-10)
348
+
349
+ ---
350
+
351
+ ## AWS Integration
352
+
353
+ With boto3 installed and credentials configured:
354
+
355
+ ```bash
356
+ # Using AWS CLI profile
357
+ exploitgraph> use cloud/s3_enum
358
+ exploitgraph> set AWS_PROFILE my-profile
359
+ exploitgraph> run
360
+
361
+ # Using discovered credentials (auto-populated from file_secrets)
362
+ exploitgraph> use cloud/iam_enum
363
+ exploitgraph> run # Picks up AWS keys found by file_secrets automatically
364
+ ```
365
+
366
+ **All AWS operations are READ-ONLY** — no modifications to your AWS environment.
367
+
368
+ ---
369
+
370
+ ## Architecture
371
+
372
+ ```
373
+ ExploitGraph/
374
+ ├── exploitgraph.py Entry point (CLI + console launcher)
375
+ ├── core/
376
+ │ ├── console.py msfconsole-style interactive shell
377
+ │ ├── module_loader.py Dynamic plugin discovery & loading
378
+ │ ├── session_manager.py SQLite-backed multi-session tracking
379
+ │ ├── attack_graph.py networkx attack graph engine
380
+ │ ├── risk_engine.py CVSS-style risk scoring
381
+ │ ├── logger.py Structured colored logger
382
+ │ └── config.py YAML configuration loader
383
+ ├── modules/
384
+ │ ├── base.py BaseModule abstract class
385
+ │ ├── discovery/ HTTP enumeration modules
386
+ │ ├── cloud/ AWS/cloud security modules
387
+ │ ├── secrets/ Credential extraction modules
388
+ │ ├── exploitation/ Attack execution modules
389
+ │ ├── reporting/ Report generation modules
390
+ │ └── custom/ Drop your own modules here
391
+ ├── data/wordlists/ Attack wordlists
392
+ ├── sessions/ SQLite session database
393
+ ├── reports/ Generated reports
394
+ └── target/ Demo vulnerable application
395
+ ```
396
+
397
+ ---
398
+
399
+ ## Legal Disclaimer
400
+
401
+ ExploitGraph is developed for **authorized security testing and educational purposes only**.
402
+
403
+ - Only use against systems you own or have explicit written permission to test
404
+ - The demo target application is for isolated lab environments only
405
+ - Unauthorized use against third-party systems is illegal
406
+
407
+ The author assumes no liability for misuse of this tool.
408
+
409
+ ---
410
+
411
+ ## License
412
+
413
+ MIT License — see [LICENSE](LICENSE)
414
+
415
+ ---
416
+
417
+ ## Author
418
+
419
+ **Prajwal Pawar**
420
+ B.Sc. Cyber Security — Final Year Project
421
+ School of Computer Application
422
+
423
+ ---
424
+
425
+ ## Contributing
426
+
427
+ Contributions welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
428
+
429
+ The easiest contribution: write a new module in `modules/custom/` following the `BaseModule` pattern and submit a PR.