phantomprobe 0.9.0__tar.gz
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.
- phantomprobe-0.9.0/.gitignore +62 -0
- phantomprobe-0.9.0/CHANGELOG.md +75 -0
- phantomprobe-0.9.0/CONTRIBUTING.md +90 -0
- phantomprobe-0.9.0/LICENSE +21 -0
- phantomprobe-0.9.0/PKG-INFO +369 -0
- phantomprobe-0.9.0/README.md +320 -0
- phantomprobe-0.9.0/pyproject.toml +95 -0
- phantomprobe-0.9.0/scripts/audit_cpe_mapping.py +196 -0
- phantomprobe-0.9.0/src/phantomprobe/__init__.py +68 -0
- phantomprobe-0.9.0/src/phantomprobe/__main__.py +10 -0
- phantomprobe-0.9.0/src/phantomprobe/active.py +339 -0
- phantomprobe-0.9.0/src/phantomprobe/aggressive.py +294 -0
- phantomprobe-0.9.0/src/phantomprobe/asgi.py +19 -0
- phantomprobe-0.9.0/src/phantomprobe/burp.py +358 -0
- phantomprobe-0.9.0/src/phantomprobe/cli.py +372 -0
- phantomprobe-0.9.0/src/phantomprobe/constants.py +18 -0
- phantomprobe-0.9.0/src/phantomprobe/cookies.py +168 -0
- phantomprobe-0.9.0/src/phantomprobe/cve.py +622 -0
- phantomprobe-0.9.0/src/phantomprobe/dashboard.py +858 -0
- phantomprobe-0.9.0/src/phantomprobe/dns_security.py +312 -0
- phantomprobe-0.9.0/src/phantomprobe/doh.py +124 -0
- phantomprobe-0.9.0/src/phantomprobe/http_checks.py +305 -0
- phantomprobe-0.9.0/src/phantomprobe/http_client.py +60 -0
- phantomprobe-0.9.0/src/phantomprobe/js.py +263 -0
- phantomprobe-0.9.0/src/phantomprobe/models.py +33 -0
- phantomprobe-0.9.0/src/phantomprobe/passive.py +512 -0
- phantomprobe-0.9.0/src/phantomprobe/report.py +94 -0
- phantomprobe-0.9.0/src/phantomprobe/screenshot.py +127 -0
- phantomprobe-0.9.0/src/phantomprobe/takeover.py +203 -0
- phantomprobe-0.9.0/src/phantomprobe/waf.py +152 -0
- phantomprobe-0.9.0/tests/__init__.py +1 -0
- phantomprobe-0.9.0/tests/conftest.py +59 -0
- phantomprobe-0.9.0/tests/test_active.py +107 -0
- phantomprobe-0.9.0/tests/test_aggressive.py +157 -0
- phantomprobe-0.9.0/tests/test_audit_script.py +124 -0
- phantomprobe-0.9.0/tests/test_burp.py +249 -0
- phantomprobe-0.9.0/tests/test_cli.py +152 -0
- phantomprobe-0.9.0/tests/test_cookies.py +122 -0
- phantomprobe-0.9.0/tests/test_cve.py +496 -0
- phantomprobe-0.9.0/tests/test_dashboard.py +219 -0
- phantomprobe-0.9.0/tests/test_dns_security.py +188 -0
- phantomprobe-0.9.0/tests/test_http_checks.py +179 -0
- phantomprobe-0.9.0/tests/test_http_client.py +91 -0
- phantomprobe-0.9.0/tests/test_takeover.py +161 -0
- phantomprobe-0.9.0/tests/test_waf.py +98 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# PhantomProbe Git Ignore
|
|
2
|
+
|
|
3
|
+
# Python
|
|
4
|
+
__pycache__/
|
|
5
|
+
*.py[cod]
|
|
6
|
+
*$py.class
|
|
7
|
+
*.so
|
|
8
|
+
.Python
|
|
9
|
+
build/
|
|
10
|
+
develop-eggs/
|
|
11
|
+
dist/
|
|
12
|
+
downloads/
|
|
13
|
+
eggs/
|
|
14
|
+
.eggs/
|
|
15
|
+
lib/
|
|
16
|
+
lib64/
|
|
17
|
+
parts/
|
|
18
|
+
sdist/
|
|
19
|
+
var/
|
|
20
|
+
wheels/
|
|
21
|
+
*.egg-info/
|
|
22
|
+
.installed.cfg
|
|
23
|
+
*.egg
|
|
24
|
+
|
|
25
|
+
# Virtual environments
|
|
26
|
+
venv/
|
|
27
|
+
ENV/
|
|
28
|
+
env/
|
|
29
|
+
.venv
|
|
30
|
+
|
|
31
|
+
# IDE
|
|
32
|
+
.vscode/
|
|
33
|
+
.idea/
|
|
34
|
+
*.swp
|
|
35
|
+
*.swo
|
|
36
|
+
*~
|
|
37
|
+
|
|
38
|
+
# Reports (generated)
|
|
39
|
+
report-*.md
|
|
40
|
+
report-*.json
|
|
41
|
+
screenshot-*.png
|
|
42
|
+
*.html
|
|
43
|
+
|
|
44
|
+
# OS
|
|
45
|
+
.DS_Store
|
|
46
|
+
Thumbs.db
|
|
47
|
+
|
|
48
|
+
# Ruflo/Claude Flow (local development)
|
|
49
|
+
.claude-flow/
|
|
50
|
+
.claude/
|
|
51
|
+
.swarm/
|
|
52
|
+
|
|
53
|
+
# Test artifacts
|
|
54
|
+
.pytest_cache/
|
|
55
|
+
.coverage
|
|
56
|
+
htmlcov/
|
|
57
|
+
.tox/
|
|
58
|
+
|
|
59
|
+
# Local config
|
|
60
|
+
.env
|
|
61
|
+
config.local.json
|
|
62
|
+
*.local.toml
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to PhantomProbe are recorded here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project
|
|
5
|
+
follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [0.9.0] - 2026-09-03
|
|
8
|
+
|
|
9
|
+
The first packaged release. It consolidates the earlier single-file prototypes
|
|
10
|
+
into a modular, passive-first scanner, so several entries below read as fixes
|
|
11
|
+
against that prototype. Every data table and severity calibration was checked
|
|
12
|
+
against its live source before shipping.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- **Subdomain takeover detection** (`--phase2`). A two-signal check: the CNAME
|
|
17
|
+
must point at a known service *and* the service must report the resource
|
|
18
|
+
unclaimed, using the can-i-take-over-xyz fingerprints. Resolves CNAMEs over
|
|
19
|
+
DNS-over-HTTPS so the core stays dependency-free.
|
|
20
|
+
- **Email security** over DoH: SPF, DMARC and DKIM, with `+all` treated as
|
|
21
|
+
worse than a missing record, and DKIM reporting only the selectors it finds.
|
|
22
|
+
- **CAA and DNSSEC** checks, reported as hardening.
|
|
23
|
+
- **Cookie security** analysis (`Secure`, `HttpOnly`, `SameSite`), weighted by
|
|
24
|
+
whether a cookie looks like a session or a tracker.
|
|
25
|
+
- **WAF / CDN fingerprinting** of 35 WAFs from the wafw00f signature set.
|
|
26
|
+
- **HSTS preload eligibility**, judged against hstspreload.org's current
|
|
27
|
+
one-year `max-age` floor; **redirect-chain** analysis; and **security.txt**
|
|
28
|
+
discovery.
|
|
29
|
+
- **CVE exploitation intelligence**: every match is enriched with CISA KEV
|
|
30
|
+
(exploited in the wild, with a ransomware marker) and EPSS (probability of
|
|
31
|
+
exploitation), and an exploited CVE ranks above a higher-scored dormant one.
|
|
32
|
+
- **Phase 3 active vulnerability probing** (`--aggressive`, opt-in): CORS, open
|
|
33
|
+
redirect, HTTP parameter pollution and S3 bucket exposure. Non-destructive;
|
|
34
|
+
request smuggling deliberately excluded.
|
|
35
|
+
- **CPE audit script** (`scripts/audit_cpe_mapping.py`) to re-check the CVE
|
|
36
|
+
table against live NVD, and a **CI job** that builds and exercises every
|
|
37
|
+
Docker stage.
|
|
38
|
+
- **`requirements-dev.txt`** and a `--no-takeover` flag.
|
|
39
|
+
|
|
40
|
+
### Changed
|
|
41
|
+
|
|
42
|
+
- **Restructured** the 2270-line single scanner file into a proper
|
|
43
|
+
`src/phantomprobe/` package of focused modules, each under 500 lines.
|
|
44
|
+
- **Redesigned the dashboard**: a dense, calibrated dark theme that scores zero
|
|
45
|
+
on the impeccable design detector, down from 41 anti-patterns.
|
|
46
|
+
- **Expanded the CVE CPE table** from 21 to 74 products, each vendor/product
|
|
47
|
+
pair verified against NVD before being added (nginx corrected to `f5`, express
|
|
48
|
+
to `openjsf`).
|
|
49
|
+
- **Version is single-sourced** from `constants.py` via hatchling, so
|
|
50
|
+
distribution metadata cannot drift from the running code.
|
|
51
|
+
- Trimmed the `burp` extra to `requests` alone, and rewrote the README.
|
|
52
|
+
|
|
53
|
+
### Fixed
|
|
54
|
+
|
|
55
|
+
- **Packaging and tests were broken**: the wheel shipped only a shim reaching
|
|
56
|
+
the real code through a `sys.path` hack, and all five tests failed on imports.
|
|
57
|
+
- **Docker**: the dashboard bound to loopback inside the container (unreachable
|
|
58
|
+
via the published port), the `full` image could not take a screenshot
|
|
59
|
+
(browsers installed as root), and several compose profiles were misconfigured.
|
|
60
|
+
- **Console encoding** could abort a whole scan: an unencodable byte in output
|
|
61
|
+
raised on a legacy code page, discarding every finding.
|
|
62
|
+
- **Burp integration** was rewritten against the API Burp actually exposes; the
|
|
63
|
+
old code sent the key as a header instead of a path prefix and read fields
|
|
64
|
+
that do not exist.
|
|
65
|
+
- **CVE correlation returned nothing**: a padded CPE matched zero results in
|
|
66
|
+
NVD, two vendor mappings were wrong, and CVSS v4.0 scores were unread.
|
|
67
|
+
|
|
68
|
+
### Security
|
|
69
|
+
|
|
70
|
+
- Fixed **stored XSS** in the dashboard: target- and finding-derived fields are
|
|
71
|
+
now HTML-escaped before rendering.
|
|
72
|
+
- All outbound fetches go through a helper enforcing an **http/https scheme
|
|
73
|
+
allowlist**, so a hostile page cannot point the scanner at `file://`.
|
|
74
|
+
|
|
75
|
+
[0.9.0]: https://github.com/Ravel226/PhantomProbe/releases/tag/v0.9.0
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Contributing to PhantomProbe
|
|
2
|
+
|
|
3
|
+
Thanks for your interest. This document covers the setup and the conventions
|
|
4
|
+
that keep the scanner trustworthy.
|
|
5
|
+
|
|
6
|
+
## Development setup
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
git clone https://github.com/Ravel226/PhantomProbe.git
|
|
10
|
+
cd PhantomProbe
|
|
11
|
+
|
|
12
|
+
python3 -m venv venv
|
|
13
|
+
source venv/bin/activate # Windows: venv\Scripts\activate
|
|
14
|
+
|
|
15
|
+
pip install -r requirements-dev.txt # editable install + all extras + tooling
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Running the checks
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pytest # the suite runs offline; no target is needed
|
|
22
|
+
pytest --cov=phantomprobe # with coverage
|
|
23
|
+
black src tests # format
|
|
24
|
+
flake8 src tests # lint
|
|
25
|
+
bandit -r src -ll # security scan (CI fails on medium+ findings)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Project conventions
|
|
29
|
+
|
|
30
|
+
These are the habits that make the difference between a scanner people trust and
|
|
31
|
+
one they learn to ignore.
|
|
32
|
+
|
|
33
|
+
### Verify data against its source, don't transcribe it
|
|
34
|
+
|
|
35
|
+
Every lookup table here (the CVE CPE map, the takeover fingerprints, the WAF
|
|
36
|
+
signatures) was checked against the authority before landing, and the
|
|
37
|
+
verification is repeatable. A wrong CPE vendor, for instance, returns a clean
|
|
38
|
+
empty result from NVD, so a broken mapping looks exactly like a clean target.
|
|
39
|
+
|
|
40
|
+
- CVE mappings: `python scripts/audit_cpe_mapping.py --check vendor:product`
|
|
41
|
+
before adding one, and re-run the whole script periodically as vendors change
|
|
42
|
+
hands.
|
|
43
|
+
- Fingerprint tables: generate them from the upstream source rather than typing
|
|
44
|
+
them out, and add a test that guards their shape.
|
|
45
|
+
|
|
46
|
+
### Calibrate severity to real impact
|
|
47
|
+
|
|
48
|
+
Severity is what a finding buys an attacker today, not what a checklist said
|
|
49
|
+
years ago. A missing `SameSite` is hardening (browsers already default to Lax);
|
|
50
|
+
a session cookie readable by script is a genuine risk. When you are unsure, look
|
|
51
|
+
up the current behavior at the source (MDN, the relevant RFC, the vendor) and
|
|
52
|
+
put the reasoning in a comment.
|
|
53
|
+
|
|
54
|
+
A scanner that cries wolf gets muted. On a well-configured target, a check
|
|
55
|
+
should produce nothing.
|
|
56
|
+
|
|
57
|
+
### Tests touch no network
|
|
58
|
+
|
|
59
|
+
Every test stubs its I/O. Reach for a real host only to develop against, never
|
|
60
|
+
in the committed suite: it must pass offline and deterministically. Cover the
|
|
61
|
+
paths a healthy target never takes (a missing SPF, a public bucket), since those
|
|
62
|
+
are the ones a live run cannot show you.
|
|
63
|
+
|
|
64
|
+
### Keep the core dependency-free
|
|
65
|
+
|
|
66
|
+
The default install has no runtime dependencies. Anything a feature needs goes
|
|
67
|
+
in an optional extra in `pyproject.toml` and is imported lazily inside the
|
|
68
|
+
module that uses it, so importing the package never fails for a missing extra.
|
|
69
|
+
|
|
70
|
+
### Active behavior is opt-in
|
|
71
|
+
|
|
72
|
+
Passive checks read what the target exposes. Anything that sends crafted
|
|
73
|
+
requests belongs behind `--aggressive` and must be non-destructive: no request
|
|
74
|
+
rewriting, no writes, nothing that can disrupt other users of a shared host.
|
|
75
|
+
|
|
76
|
+
## Pull requests
|
|
77
|
+
|
|
78
|
+
1. Fork and branch (`git checkout -b feature/thing`)
|
|
79
|
+
2. Add tests for the new behavior, including the negative cases
|
|
80
|
+
3. Run the full check list above; it must be green
|
|
81
|
+
4. Update the README if you added a check or a flag
|
|
82
|
+
5. Open a PR with a description of what changed and why
|
|
83
|
+
|
|
84
|
+
Commit messages: present tense, imperative mood, first line under 72 characters,
|
|
85
|
+
with the reasoning in the body.
|
|
86
|
+
|
|
87
|
+
## Security
|
|
88
|
+
|
|
89
|
+
- Never commit secrets, credentials, or `.env` files
|
|
90
|
+
- Report vulnerabilities in PhantomProbe itself privately, not in a public issue
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ravel226
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: phantomprobe
|
|
3
|
+
Version: 0.9.0
|
|
4
|
+
Summary: Passive-first reconnaissance scanner for penetration testers and bug bounty hunters
|
|
5
|
+
Project-URL: Homepage, https://github.com/Ravel226/PhantomProbe
|
|
6
|
+
Project-URL: Repository, https://github.com/Ravel226/PhantomProbe
|
|
7
|
+
Project-URL: Issues, https://github.com/Ravel226/PhantomProbe/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/Ravel226/PhantomProbe/blob/main/CHANGELOG.md
|
|
9
|
+
Author-email: Ravel226 <86806675+Ravel226@users.noreply.github.com>
|
|
10
|
+
License: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: bug-bounty,cve,dns,osint,penetration-testing,reconnaissance,scanner,security,subdomain-takeover
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Information Technology
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Indexing/Search
|
|
25
|
+
Classifier: Topic :: Security
|
|
26
|
+
Requires-Python: >=3.8
|
|
27
|
+
Provides-Extra: all
|
|
28
|
+
Requires-Dist: fastapi>=0.100.0; extra == 'all'
|
|
29
|
+
Requires-Dist: playwright>=1.40.0; extra == 'all'
|
|
30
|
+
Requires-Dist: requests>=2.25.0; extra == 'all'
|
|
31
|
+
Requires-Dist: uvicorn>=0.23.0; extra == 'all'
|
|
32
|
+
Requires-Dist: websockets>=11.0; extra == 'all'
|
|
33
|
+
Provides-Extra: burp
|
|
34
|
+
Requires-Dist: requests>=2.25.0; extra == 'burp'
|
|
35
|
+
Provides-Extra: dashboard
|
|
36
|
+
Requires-Dist: fastapi>=0.100.0; extra == 'dashboard'
|
|
37
|
+
Requires-Dist: uvicorn>=0.23.0; extra == 'dashboard'
|
|
38
|
+
Requires-Dist: websockets>=11.0; extra == 'dashboard'
|
|
39
|
+
Provides-Extra: dev
|
|
40
|
+
Requires-Dist: bandit>=1.7; extra == 'dev'
|
|
41
|
+
Requires-Dist: black>=23.0; extra == 'dev'
|
|
42
|
+
Requires-Dist: flake8>=6.0; extra == 'dev'
|
|
43
|
+
Requires-Dist: isort>=5.12; extra == 'dev'
|
|
44
|
+
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
|
|
45
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
46
|
+
Provides-Extra: screenshot
|
|
47
|
+
Requires-Dist: playwright>=1.40.0; extra == 'screenshot'
|
|
48
|
+
Description-Content-Type: text/markdown
|
|
49
|
+
|
|
50
|
+
# PhantomProbe
|
|
51
|
+
|
|
52
|
+
**Passive-first reconnaissance scanner for penetration testers and bug bounty hunters.**
|
|
53
|
+
|
|
54
|
+
[](https://www.python.org/downloads/)
|
|
55
|
+
[](https://opensource.org/licenses/MIT)
|
|
56
|
+
[](tests/)
|
|
57
|
+
|
|
58
|
+
PhantomProbe maps a target's attack surface and reports what is actually wrong
|
|
59
|
+
with it. The core runs on the Python standard library alone, so a default
|
|
60
|
+
install has no dependencies and starts in one command. Optional features (a web
|
|
61
|
+
dashboard, screenshots, a Burp bridge) each pull in their own packages and
|
|
62
|
+
nothing else.
|
|
63
|
+
|
|
64
|
+
Two ideas run through it:
|
|
65
|
+
|
|
66
|
+
- **Observe before you touch.** Everything except the opt-in `--aggressive`
|
|
67
|
+
phase either reads what the target already sends or resolves DNS. Records that
|
|
68
|
+
the standard library cannot reach, such as TXT, MX and DNSKEY, are fetched
|
|
69
|
+
over DNS-over-HTTPS rather than by adding a DNS dependency.
|
|
70
|
+
- **Say something only when it means something.** Severities are set by what a
|
|
71
|
+
finding buys an attacker today, not by dated checklists. A missing `SameSite`
|
|
72
|
+
is hardening; a session cookie readable by script is not. A CVE that CISA
|
|
73
|
+
lists as exploited outranks a higher-scored one nobody uses. On a
|
|
74
|
+
well-configured target, PhantomProbe stays quiet.
|
|
75
|
+
|
|
76
|
+
## Quick start
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
git clone https://github.com/Ravel226/PhantomProbe.git
|
|
80
|
+
cd PhantomProbe
|
|
81
|
+
pip install -e .
|
|
82
|
+
phantomprobe example.com
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
That first scan is entirely passive. Add phases as you need them:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
phantomprobe example.com --phase2 # active recon (ports, subdomains, takeover)
|
|
89
|
+
phantomprobe example.com --phase2 --cve # correlate versions to CVEs (KEV/EPSS ranked)
|
|
90
|
+
phantomprobe example.com --phase2 --cve --js # add JavaScript endpoint/secret discovery
|
|
91
|
+
phantomprobe example.com --phase2 --aggressive # opt-in active probes (authorized targets only)
|
|
92
|
+
phantomprobe example.com --phase2 --cve --dashboard # serve results in the web UI
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Every scan writes `report-<target>.md` and `report-<target>.json` to the
|
|
96
|
+
`--output-dir` (default: the current directory).
|
|
97
|
+
|
|
98
|
+
## Installation
|
|
99
|
+
|
|
100
|
+
The core scanner is dependency-free. Install extras only for the features you
|
|
101
|
+
want; `pip install -e .` is enough for a full passive and active scan.
|
|
102
|
+
|
|
103
|
+
| Command | Adds |
|
|
104
|
+
|---------|------|
|
|
105
|
+
| `pip install -e .` | Core scanner (no dependencies) |
|
|
106
|
+
| `pip install -e ".[dashboard]"` | Interactive web dashboard (FastAPI, uvicorn) |
|
|
107
|
+
| `pip install -e ".[screenshot]"` | Full-page screenshots (Playwright) |
|
|
108
|
+
| `pip install -e ".[burp]"` | Burp Professional REST integration (requests) |
|
|
109
|
+
| `pip install -e ".[all]"` | Every feature above |
|
|
110
|
+
|
|
111
|
+
Screenshots need the browser as well as the package:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
pip install -e ".[screenshot]"
|
|
115
|
+
playwright install chromium
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Run it without installing at all, straight from a checkout:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
PYTHONPATH=src python -m phantomprobe example.com
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## What it checks
|
|
125
|
+
|
|
126
|
+
### Phase 1: passive (always on)
|
|
127
|
+
|
|
128
|
+
Reads what the target already sends and resolves DNS. No probing.
|
|
129
|
+
|
|
130
|
+
- **DNS** - A/AAAA records, reverse DNS, wildcard detection
|
|
131
|
+
- **SSL/TLS** - certificate details and expiry, weak ciphers, deprecated TLS versions
|
|
132
|
+
- **Security headers** - the six response headers that harden a browser session (CSP, HSTS, X-Frame-Options and the rest)
|
|
133
|
+
- **Cookies** - `Secure`, `HttpOnly` and `SameSite`, weighted by whether a
|
|
134
|
+
cookie looks like a session or a tracker
|
|
135
|
+
- **Email security** - SPF, DMARC and DKIM over DoH. Missing SPF or DMARC lets
|
|
136
|
+
anyone forge mail from the domain, the cheapest phishing route into an org
|
|
137
|
+
- **CAA and DNSSEC** - certificate-issuance restrictions and zone signing,
|
|
138
|
+
reported as hardening
|
|
139
|
+
- **HSTS preload eligibility** - judged against hstspreload.org's current
|
|
140
|
+
one-year `max-age` floor
|
|
141
|
+
- **Redirect chain** - flags plain HTTP that never reaches HTTPS, and redirects
|
|
142
|
+
that leave the target host
|
|
143
|
+
- **security.txt** - the RFC 9116 disclosure contact
|
|
144
|
+
|
|
145
|
+
### Phase 2: active reconnaissance (`--phase2`)
|
|
146
|
+
|
|
147
|
+
- **Port scan** - common service ports, concurrently
|
|
148
|
+
- **Subdomain enumeration** - common-name discovery
|
|
149
|
+
- **Technology fingerprinting** - server and framework detection
|
|
150
|
+
- **Subdomain takeover** - dangling-CNAME detection against a two-signal check
|
|
151
|
+
(the CNAME must point at a known service *and* the service must report the
|
|
152
|
+
resource unclaimed), using the [can-i-take-over-xyz](https://github.com/EdOverflow/can-i-take-over-xyz)
|
|
153
|
+
fingerprints. Disable with `--no-takeover`.
|
|
154
|
+
- **WAF / CDN** - passive fingerprinting of 35 WAFs from the wafw00f signature set
|
|
155
|
+
|
|
156
|
+
### CVE correlation (`--cve`)
|
|
157
|
+
|
|
158
|
+
Matches fingerprinted technology versions to NVD, across 74 products whose CPE
|
|
159
|
+
vendor/product pairs were each verified against the live API before being added
|
|
160
|
+
(a wrong vendor returns a clean empty result, so it fails silently). It only
|
|
161
|
+
correlates where a banner gave a version, reads CVSS v4.0/v3.1/v3.0/v2 scores,
|
|
162
|
+
and enriches every match with:
|
|
163
|
+
|
|
164
|
+
- **CISA KEV** - whether the CVE is exploited in the wild, with a ransomware marker
|
|
165
|
+
- **EPSS** - the probability of exploitation in the next 30 days
|
|
166
|
+
|
|
167
|
+
An exploited CVE is ranked above a higher-scored dormant one. Keep the CPE table
|
|
168
|
+
honest as vendors change hands:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
python scripts/audit_cpe_mapping.py # re-check every mapping against NVD
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Phase 3: active vulnerability probing (`--aggressive`, opt-in)
|
|
175
|
+
|
|
176
|
+
Off by default, and it prints an authorization notice when it runs, because
|
|
177
|
+
these checks send crafted requests to the target rather than observing it. All
|
|
178
|
+
four are non-destructive.
|
|
179
|
+
|
|
180
|
+
- **CORS** - a reflected origin with credentials is high; a bare `*`, which
|
|
181
|
+
browsers already block from credentialed use, is not reported
|
|
182
|
+
- **Open redirect** - common redirect parameters on the root path
|
|
183
|
+
- **HTTP parameter pollution** - flags a status-code change on a duplicated
|
|
184
|
+
parameter, filed as an informational hint
|
|
185
|
+
- **S3 buckets** - guesses bucket names from the domain; a public listing is high
|
|
186
|
+
|
|
187
|
+
Request smuggling is deliberately excluded: a faithful probe desyncs the
|
|
188
|
+
connection and can affect other users of a shared server, which belongs in a
|
|
189
|
+
dedicated tool under a scoped engagement.
|
|
190
|
+
|
|
191
|
+
### Other features
|
|
192
|
+
|
|
193
|
+
- **JavaScript analysis** (`--js`) - extracts API endpoints, exposed secrets
|
|
194
|
+
(API keys, tokens, AWS keys) and hidden paths from linked scripts
|
|
195
|
+
- **Screenshot** (`--screenshot`) - a full-page capture via headless Chromium
|
|
196
|
+
- **Burp Professional** (`--burp`) - runs a Burp scan and imports its issues; see below
|
|
197
|
+
|
|
198
|
+
## CLI options
|
|
199
|
+
|
|
200
|
+
| Flag | Description |
|
|
201
|
+
|------|-------------|
|
|
202
|
+
| `-a`, `--phase2` | Active recon: ports, subdomains, fingerprinting, takeover |
|
|
203
|
+
| `--no-takeover` | Skip the takeover check (it queries DoH and third-party services) |
|
|
204
|
+
| `--aggressive` | Phase 3 active probes. Sends crafted requests; authorized targets only |
|
|
205
|
+
| `-c`, `--cve` | CVE correlation via NVD, ranked by KEV and EPSS |
|
|
206
|
+
| `-s`, `--screenshot` | Full-page screenshot (needs `[screenshot]`) |
|
|
207
|
+
| `-j`, `--js` | JavaScript endpoint and secret discovery |
|
|
208
|
+
| `-b`, `--burp` | Run a Burp Professional scan and import its issues (needs `[burp]`) |
|
|
209
|
+
| `--burp-timeout SECONDS` | How long to wait for the Burp scan (default: 300) |
|
|
210
|
+
| `-d`, `--dashboard` | Serve the interactive web dashboard (needs `[dashboard]`) |
|
|
211
|
+
| `--output-dir DIR` | Where to write reports and screenshots (default: `.`) |
|
|
212
|
+
| `-v`, `--verbose` | Verbose output |
|
|
213
|
+
|
|
214
|
+
### Environment variables
|
|
215
|
+
|
|
216
|
+
| Variable | Purpose |
|
|
217
|
+
|----------|---------|
|
|
218
|
+
| `NVD_API_KEY` | Raises the NVD rate limit from 5 to 50 requests / 30s. Without it, `--cve` throttles to ~1 query every 6.5s. [Request one](https://nvd.nist.gov/developers/request-an-api-key). |
|
|
219
|
+
| `BURP_API_KEY` | Burp REST API key, used by `--burp`. Sent as a URL path prefix. |
|
|
220
|
+
| `BURP_API_URL` | Burp REST service URL (default: `http://127.0.0.1:1337`). |
|
|
221
|
+
| `PHANTOMPROBE_DASHBOARD_HOST` | Dashboard bind address (default: `127.0.0.1`). |
|
|
222
|
+
| `PHANTOMPROBE_DASHBOARD_PORT` | Dashboard port (default: `8080`). |
|
|
223
|
+
|
|
224
|
+
## Reports and dashboard
|
|
225
|
+
|
|
226
|
+
Each scan writes two reports next to the output directory:
|
|
227
|
+
|
|
228
|
+
- `report-<target>.md` - a HackerOne-style Markdown report
|
|
229
|
+
- `report-<target>.json` - the same findings as structured JSON, including the
|
|
230
|
+
CVE matches with their KEV and EPSS fields
|
|
231
|
+
|
|
232
|
+
The `--dashboard` flag serves the findings in a dark, dense web UI with
|
|
233
|
+
severity filtering, live WebSocket updates, and a CVE table that surfaces which
|
|
234
|
+
matches are actively exploited. Serve an empty dashboard, without running a
|
|
235
|
+
scan, straight from the ASGI app:
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
pip install -e ".[dashboard]"
|
|
239
|
+
uvicorn phantomprobe.asgi:app --host 127.0.0.1 --port 8080
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## Docker
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
git clone https://github.com/Ravel226/PhantomProbe.git
|
|
246
|
+
cd PhantomProbe
|
|
247
|
+
mkdir -p reports
|
|
248
|
+
|
|
249
|
+
# One-off scan (results land in ./reports)
|
|
250
|
+
docker build -t phantomprobe .
|
|
251
|
+
docker run -v "$(pwd)/reports:/app/reports" phantomprobe example.com --output-dir /app/reports
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
The container runs as uid 1000. If your host `reports/` directory is owned by a
|
|
255
|
+
different user, the scan fails with `Permission denied`; run it as yourself with
|
|
256
|
+
`--user "$(id -u):$(id -g)"`.
|
|
257
|
+
|
|
258
|
+
Compose ships a profile per edition:
|
|
259
|
+
|
|
260
|
+
```bash
|
|
261
|
+
docker compose --profile core up phantomprobe-core # CLI only, smallest image
|
|
262
|
+
docker compose --profile dashboard up phantomprobe-dashboard # dashboard at http://localhost:8080
|
|
263
|
+
docker compose --profile full up phantomprobe-full # every feature, includes Chromium
|
|
264
|
+
docker compose --profile dev up phantomprobe-dev # dashboard with source reload
|
|
265
|
+
docker compose --profile api up phantomprobe-api # dashboard API only, no scan
|
|
266
|
+
docker compose --profile burp up phantomprobe-burp # with a Burp REST endpoint
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## Burp Suite integration
|
|
270
|
+
|
|
271
|
+
PhantomProbe can run a scan in Burp Professional and pull its issues into the
|
|
272
|
+
same report. Burp's REST API only scans, so results flow one way: there is no
|
|
273
|
+
endpoint for pushing findings back or driving the proxy, and PhantomProbe does
|
|
274
|
+
not pretend to offer either.
|
|
275
|
+
|
|
276
|
+
1. Burp Professional: enable the REST API under Settings → Suite → REST API
|
|
277
|
+
2. Create an API key on that screen (Burp shows the value only once)
|
|
278
|
+
3. `pip install -e ".[burp]"`
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
export BURP_API_KEY=your-api-key
|
|
282
|
+
phantomprobe target.com --burp --burp-timeout 1800
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
The key is a URL path prefix, not a header: Burp serves the API under
|
|
286
|
+
`http://127.0.0.1:1337/<your-key>/v0.1/`. Opening that URL in a browser shows
|
|
287
|
+
the API documentation for your exact Burp version.
|
|
288
|
+
|
|
289
|
+
## Architecture
|
|
290
|
+
|
|
291
|
+
```
|
|
292
|
+
src/phantomprobe/
|
|
293
|
+
├── cli.py Argument parsing and scan orchestration
|
|
294
|
+
├── constants.py Version and User-Agent (single source of truth)
|
|
295
|
+
├── models.py Finding, Severity
|
|
296
|
+
├── http_client.py Fetch helper with a URL-scheme allowlist
|
|
297
|
+
├── doh.py DNS-over-HTTPS resolver (shared)
|
|
298
|
+
│
|
|
299
|
+
├── passive.py Phase 1: DNS, SSL/TLS, HTTP headers
|
|
300
|
+
├── cookies.py Cookie security attributes
|
|
301
|
+
├── dns_security.py SPF, DMARC, DKIM, CAA, DNSSEC
|
|
302
|
+
├── http_checks.py HSTS preload, redirect chain, security.txt
|
|
303
|
+
│
|
|
304
|
+
├── active.py Phase 2: ports, subdomains, fingerprinting
|
|
305
|
+
├── takeover.py Subdomain takeover (two-signal)
|
|
306
|
+
├── waf.py WAF/CDN fingerprinting
|
|
307
|
+
│
|
|
308
|
+
├── aggressive.py Phase 3: CORS, open redirect, HPP, S3 (opt-in)
|
|
309
|
+
│
|
|
310
|
+
├── cve.py NVD correlation + KEV/EPSS enrichment
|
|
311
|
+
├── js.py JavaScript endpoint/secret discovery
|
|
312
|
+
├── screenshot.py Playwright capture (extra: screenshot)
|
|
313
|
+
├── burp.py Burp REST integration (extra: burp)
|
|
314
|
+
├── report.py Markdown and JSON reports
|
|
315
|
+
├── dashboard.py FastAPI dashboard (extra: dashboard)
|
|
316
|
+
└── asgi.py Standalone ASGI entry point (extra: dashboard)
|
|
317
|
+
|
|
318
|
+
scripts/audit_cpe_mapping.py Re-check the CVE table against live NVD
|
|
319
|
+
tests/ 264 tests, network stubbed
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
## Development
|
|
323
|
+
|
|
324
|
+
```bash
|
|
325
|
+
pip install -r requirements-dev.txt # editable install with all extras + tooling
|
|
326
|
+
|
|
327
|
+
pytest # run the suite (network is stubbed; no target needed)
|
|
328
|
+
pytest --cov=phantomprobe # with coverage
|
|
329
|
+
black src tests # format
|
|
330
|
+
flake8 src tests # lint
|
|
331
|
+
bandit -r src -ll # security scan
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
The test suite stubs every network call, so it runs offline and touches no real
|
|
335
|
+
host. See [CONTRIBUTING.md](CONTRIBUTING.md) for the workflow.
|
|
336
|
+
|
|
337
|
+
## Security notice
|
|
338
|
+
|
|
339
|
+
**Use PhantomProbe only against systems you own or are explicitly authorized to
|
|
340
|
+
test.** Passive checks read what a target already exposes, but active
|
|
341
|
+
reconnaissance (`--phase2`) and vulnerability probing (`--aggressive`) send
|
|
342
|
+
traffic to it. Unauthorized scanning is illegal in most jurisdictions.
|
|
343
|
+
|
|
344
|
+
## Disclaimer
|
|
345
|
+
|
|
346
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
347
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
348
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
349
|
+
|
|
350
|
+
## Credits
|
|
351
|
+
|
|
352
|
+
- CVE data from [NVD](https://nvd.nist.gov/); exploitation data from
|
|
353
|
+
[CISA KEV](https://www.cisa.gov/known-exploited-vulnerabilities-catalog) and
|
|
354
|
+
[FIRST EPSS](https://www.first.org/epss/)
|
|
355
|
+
- Takeover fingerprints from [can-i-take-over-xyz](https://github.com/EdOverflow/can-i-take-over-xyz)
|
|
356
|
+
- WAF signatures derived from [wafw00f](https://github.com/EnableSecurity/wafw00f)
|
|
357
|
+
|
|
358
|
+
## License
|
|
359
|
+
|
|
360
|
+
MIT - see [LICENSE](LICENSE). Author: [@Ravel226](https://github.com/Ravel226).
|
|
361
|
+
|
|
362
|
+
## Changelog
|
|
363
|
+
|
|
364
|
+
Release history and unreleased changes are in [CHANGELOG.md](CHANGELOG.md).
|
|
365
|
+
|
|
366
|
+
## Contributing
|
|
367
|
+
|
|
368
|
+
Contributions are welcome. Fork, branch, add tests, and open a pull request.
|
|
369
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md).
|