stackscan 2.6.3__tar.gz → 2.7.1__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.
- {stackscan-2.6.3 → stackscan-2.7.1}/PKG-INFO +64 -2
- {stackscan-2.6.3 → stackscan-2.7.1}/README.md +62 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/pyproject.toml +14 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/__init__.py +1 -1
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/cli.py +295 -61
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/config/__init__.py +10 -1
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/config/sources.py +3 -1
- stackscan-2.7.1/src/stackscan/embed.py +387 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/render.py +59 -12
- stackscan-2.7.1/src/stackscan/runner.py +286 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/scan.py +30 -10
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/theme.py +2 -30
- stackscan-2.7.1/src/stackscan/utils/__init__.py +13 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/utils/urls.py +8 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/tests/test_brute.py +47 -1
- {stackscan-2.6.3 → stackscan-2.7.1}/tests/test_cli_helpers.py +9 -1
- stackscan-2.7.1/tests/test_embed.py +162 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/tests/test_ports.py +3 -1
- stackscan-2.7.1/tests/test_reekeer_host.py +148 -0
- stackscan-2.7.1/tests/test_render.py +46 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/tests/test_scan.py +50 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/tests/test_services.py +6 -2
- stackscan-2.7.1/tests/test_theme.py +20 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/tests/test_vhost.py +36 -0
- stackscan-2.6.3/src/stackscan/utils/__init__.py +0 -4
- stackscan-2.6.3/tests/test_theme.py +0 -26
- {stackscan-2.6.3 → stackscan-2.7.1}/.gitignore +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/LICENSE +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/scripts/build_cve_db.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/__main__.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/analyzers/__init__.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/analyzers/creds.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/analyzers/cve.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/analyzers/exposure.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/analyzers/generic.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/analyzers/infra.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/analyzers/osdetect.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/analyzers/security.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/analyzers/services.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/analyzers/social.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/analyzers/tech.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/analyzers/vibe.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/config/sigdb_loader.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/core/__init__.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/core/core.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/data/builtin.sigdb +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/data/cve.json.gz +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/data/reekeer-logo.png +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/data/subdomains.txt +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/export.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/net/__init__.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/net/dns.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/net/fingerprint.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/net/geo.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/net/ipinfo.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/net/ports.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/net/resolver.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/net/subdomains.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/net/tld.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/net/tls.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/net/whois.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/scanners/__init__.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/scanners/isp_blocked.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/scanners/secrets.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/scanners/takeover.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/types/__init__.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/types/models.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/types/output.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/src/stackscan/utils/paths.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/tests/test_builtin_sigdb.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/tests/test_creds.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/tests/test_cve.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/tests/test_dns_records.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/tests/test_export.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/tests/test_extra.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/tests/test_infra.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/tests/test_osdetect.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/tests/test_scanners.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/tests/test_social.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/tests/test_sources.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/tests/test_subdomains.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/tests/test_tech.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/tests/test_vibe.py +0 -0
- {stackscan-2.6.3 → stackscan-2.7.1}/tests/test_whois.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: stackscan
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.7.1
|
|
4
4
|
Summary: Full web stack, infrastructure, DNS, port, subdomain and CVE analyzer.
|
|
5
5
|
Project-URL: Source, https://github.com/reekeer/stackscan
|
|
6
6
|
Project-URL: Issues, https://github.com/reekeer/stackscan/issues
|
|
@@ -77,6 +77,26 @@ pip install "stackscan[geo]" # offline IP geolocation via geoip2 + a MaxMind .
|
|
|
77
77
|
`nmap` is used for port scans when present; without it a pure-Python scanner is
|
|
78
78
|
used automatically.
|
|
79
79
|
|
|
80
|
+
### Inside the reekeer shell
|
|
81
|
+
|
|
82
|
+
stackscan is also a [reekeer](https://github.com/reekeer/reekeer) plugin, mounted
|
|
83
|
+
at `/tools/recon/stackscan` (alias `ss`):
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
reekeer exec /plugins install reekeer/stackscan
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Hosted there it drops the banner and the window title and hands the scan back as
|
|
90
|
+
data for reekeer to render in the shell's own tables, so it reads as a command of
|
|
91
|
+
the shell rather than a script being shelled out to. Every flag behaves the same,
|
|
92
|
+
and standalone (`pip`, `uvx stackscan`) is unchanged.
|
|
93
|
+
|
|
94
|
+
In reekeer's window the scan also gets a form. stackscan says which of its flags
|
|
95
|
+
are worth a control — the targets, the four switches that decide how deep a scan
|
|
96
|
+
goes, and the bounds worth changing when one is too slow — and reekeer draws
|
|
97
|
+
those. The rest are not hidden: the argument line under the form still takes
|
|
98
|
+
anything argparse takes, `--help` included.
|
|
99
|
+
|
|
80
100
|
---
|
|
81
101
|
|
|
82
102
|
## ✨ Features
|
|
@@ -194,6 +214,46 @@ Below are performance benchmarks conducted on two production targets using diffe
|
|
|
194
214
|
|
|
195
215
|
---
|
|
196
216
|
|
|
217
|
+
## 🛰 Runner mode
|
|
218
|
+
|
|
219
|
+
`stackscan --runner` turns the scanner into a worker for a StackScan panel: it
|
|
220
|
+
claims jobs (`POST /api/jobs/claim`), fingerprints each target with the normal
|
|
221
|
+
engine, and posts the results back (`POST /api/results`). It needs nothing but
|
|
222
|
+
network access to the panel — no database, no Redis, no shared filesystem.
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
STACKSCAN_BACKEND_URL=https://panel.example STACKSCAN_WORKER_TOKEN=… \
|
|
226
|
+
stackscan --runner
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
| Variable | Default | What it is |
|
|
230
|
+
| --- | --- | --- |
|
|
231
|
+
| `STACKSCAN_BACKEND_URL` | `http://localhost:8787` | Panel base URL |
|
|
232
|
+
| `STACKSCAN_WORKER_TOKEN` | — | Shared worker token, sent as `X-Worker-Token` |
|
|
233
|
+
| `STACKSCAN_RUNNER_ID` | `runner-<host>-<pid>` | Stable id for this runner |
|
|
234
|
+
| `STACKSCAN_RUNNER_BATCH` | `5` | Jobs claimed per cycle |
|
|
235
|
+
| `STACKSCAN_RUNNER_IDLE` | `5` | Seconds to wait when the queue is empty |
|
|
236
|
+
| `STACKSCAN_RUNNER` | — | Truthy value selects runner mode without the flag |
|
|
237
|
+
|
|
238
|
+
Every one has a flag (`--backend`, `--worker-token`, `--runner-id`, `--batch`,
|
|
239
|
+
`--sigdb`, `--user-agent`), and `--once` runs a single claim/scan/report cycle,
|
|
240
|
+
which is what you want in a cron job or a smoke test. The runner profile is
|
|
241
|
+
deliberately lean — DNS, TLS, geo and IP info, no ports, CVEs or brute passes —
|
|
242
|
+
because it is meant for volume rather than depth.
|
|
243
|
+
|
|
244
|
+
Packaged for it:
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
docker build -t stackscan:latest .
|
|
248
|
+
docker run --rm -e STACKSCAN_BACKEND_URL=http://panel:8787 \
|
|
249
|
+
-e STACKSCAN_WORKER_TOKEN=… stackscan:latest
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Runner mode is refused inside the reekeer shell: it is a loop that runs until it
|
|
253
|
+
is killed, and a shell command that never answers is not a command.
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
197
257
|
## 🚀 Smart Scan Pipeline
|
|
198
258
|
|
|
199
259
|
The Smart Scan engine performs multiple analysis stages to collect infrastructure, technology, and security information about the target before generating the final report.
|
|
@@ -325,6 +385,8 @@ stackscan/
|
|
|
325
385
|
│ ├── config/ ← bundled + sourced sigdb loading
|
|
326
386
|
│ ├── data/ ← builtin.sigdb, cve.json.gz, subdomains.txt
|
|
327
387
|
│ ├── render.py ← the colorized panel report
|
|
388
|
+
│ ├── embed.py ← findings as data, and the form, for reekeer to draw
|
|
389
|
+
│ ├── runner.py ← panel worker: claim jobs, scan, report back
|
|
328
390
|
│ ├── scan.py ← per-target orchestration
|
|
329
391
|
│ └── cli.py ← argument parsing and entry point
|
|
330
392
|
├── scripts/ ← build_cve_db.py (NVD → offline dataset)
|
|
@@ -39,6 +39,26 @@ pip install "stackscan[geo]" # offline IP geolocation via geoip2 + a MaxMind .
|
|
|
39
39
|
`nmap` is used for port scans when present; without it a pure-Python scanner is
|
|
40
40
|
used automatically.
|
|
41
41
|
|
|
42
|
+
### Inside the reekeer shell
|
|
43
|
+
|
|
44
|
+
stackscan is also a [reekeer](https://github.com/reekeer/reekeer) plugin, mounted
|
|
45
|
+
at `/tools/recon/stackscan` (alias `ss`):
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
reekeer exec /plugins install reekeer/stackscan
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Hosted there it drops the banner and the window title and hands the scan back as
|
|
52
|
+
data for reekeer to render in the shell's own tables, so it reads as a command of
|
|
53
|
+
the shell rather than a script being shelled out to. Every flag behaves the same,
|
|
54
|
+
and standalone (`pip`, `uvx stackscan`) is unchanged.
|
|
55
|
+
|
|
56
|
+
In reekeer's window the scan also gets a form. stackscan says which of its flags
|
|
57
|
+
are worth a control — the targets, the four switches that decide how deep a scan
|
|
58
|
+
goes, and the bounds worth changing when one is too slow — and reekeer draws
|
|
59
|
+
those. The rest are not hidden: the argument line under the form still takes
|
|
60
|
+
anything argparse takes, `--help` included.
|
|
61
|
+
|
|
42
62
|
---
|
|
43
63
|
|
|
44
64
|
## ✨ Features
|
|
@@ -156,6 +176,46 @@ Below are performance benchmarks conducted on two production targets using diffe
|
|
|
156
176
|
|
|
157
177
|
---
|
|
158
178
|
|
|
179
|
+
## 🛰 Runner mode
|
|
180
|
+
|
|
181
|
+
`stackscan --runner` turns the scanner into a worker for a StackScan panel: it
|
|
182
|
+
claims jobs (`POST /api/jobs/claim`), fingerprints each target with the normal
|
|
183
|
+
engine, and posts the results back (`POST /api/results`). It needs nothing but
|
|
184
|
+
network access to the panel — no database, no Redis, no shared filesystem.
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
STACKSCAN_BACKEND_URL=https://panel.example STACKSCAN_WORKER_TOKEN=… \
|
|
188
|
+
stackscan --runner
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
| Variable | Default | What it is |
|
|
192
|
+
| --- | --- | --- |
|
|
193
|
+
| `STACKSCAN_BACKEND_URL` | `http://localhost:8787` | Panel base URL |
|
|
194
|
+
| `STACKSCAN_WORKER_TOKEN` | — | Shared worker token, sent as `X-Worker-Token` |
|
|
195
|
+
| `STACKSCAN_RUNNER_ID` | `runner-<host>-<pid>` | Stable id for this runner |
|
|
196
|
+
| `STACKSCAN_RUNNER_BATCH` | `5` | Jobs claimed per cycle |
|
|
197
|
+
| `STACKSCAN_RUNNER_IDLE` | `5` | Seconds to wait when the queue is empty |
|
|
198
|
+
| `STACKSCAN_RUNNER` | — | Truthy value selects runner mode without the flag |
|
|
199
|
+
|
|
200
|
+
Every one has a flag (`--backend`, `--worker-token`, `--runner-id`, `--batch`,
|
|
201
|
+
`--sigdb`, `--user-agent`), and `--once` runs a single claim/scan/report cycle,
|
|
202
|
+
which is what you want in a cron job or a smoke test. The runner profile is
|
|
203
|
+
deliberately lean — DNS, TLS, geo and IP info, no ports, CVEs or brute passes —
|
|
204
|
+
because it is meant for volume rather than depth.
|
|
205
|
+
|
|
206
|
+
Packaged for it:
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
docker build -t stackscan:latest .
|
|
210
|
+
docker run --rm -e STACKSCAN_BACKEND_URL=http://panel:8787 \
|
|
211
|
+
-e STACKSCAN_WORKER_TOKEN=… stackscan:latest
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Runner mode is refused inside the reekeer shell: it is a loop that runs until it
|
|
215
|
+
is killed, and a shell command that never answers is not a command.
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
159
219
|
## 🚀 Smart Scan Pipeline
|
|
160
220
|
|
|
161
221
|
The Smart Scan engine performs multiple analysis stages to collect infrastructure, technology, and security information about the target before generating the final report.
|
|
@@ -287,6 +347,8 @@ stackscan/
|
|
|
287
347
|
│ ├── config/ ← bundled + sourced sigdb loading
|
|
288
348
|
│ ├── data/ ← builtin.sigdb, cve.json.gz, subdomains.txt
|
|
289
349
|
│ ├── render.py ← the colorized panel report
|
|
350
|
+
│ ├── embed.py ← findings as data, and the form, for reekeer to draw
|
|
351
|
+
│ ├── runner.py ← panel worker: claim jobs, scan, report back
|
|
290
352
|
│ ├── scan.py ← per-target orchestration
|
|
291
353
|
│ └── cli.py ← argument parsing and entry point
|
|
292
354
|
├── scripts/ ← build_cve_db.py (NVD → offline dataset)
|
|
@@ -67,6 +67,20 @@ Issues = "https://github.com/reekeer/stackscan/issues"
|
|
|
67
67
|
[project.scripts]
|
|
68
68
|
stackscan = "stackscan.cli:main"
|
|
69
69
|
|
|
70
|
+
# Mounts stackscan inside the reekeer shell as /recon/stackscan.
|
|
71
|
+
#
|
|
72
|
+
# Not `/tools/recon`: a root that holds every plugin distinguishes none of them, so the category is
|
|
73
|
+
# the top-level group.
|
|
74
|
+
#
|
|
75
|
+
# Name, version, description, authors and dependencies are read from [project] above, so nothing is
|
|
76
|
+
# repeated here. No arguments are declared on purpose: stackscan's own argparse keeps ownership of all
|
|
77
|
+
# of them, including `--help` and the `sigdb` subcommand, and reekeer hands it the raw tokens.
|
|
78
|
+
[tool.reekeer]
|
|
79
|
+
group = "/recon"
|
|
80
|
+
entrypoint = "stackscan.cli:main"
|
|
81
|
+
python-root = "src"
|
|
82
|
+
aliases = ["ss"]
|
|
83
|
+
|
|
70
84
|
[tool.hatch.version]
|
|
71
85
|
path = "src/stackscan/__init__.py"
|
|
72
86
|
|