danishrecon 0.7.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.
- danishrecon-0.7.0/LICENSE +21 -0
- danishrecon-0.7.0/PKG-INFO +190 -0
- danishrecon-0.7.0/README.md +134 -0
- danishrecon-0.7.0/pyproject.toml +64 -0
- danishrecon-0.7.0/setup.cfg +4 -0
- danishrecon-0.7.0/src/danishrecon/__init__.py +4 -0
- danishrecon-0.7.0/src/danishrecon/__main__.py +5 -0
- danishrecon-0.7.0/src/danishrecon/amplification.py +154 -0
- danishrecon-0.7.0/src/danishrecon/analysis_core.py +625 -0
- danishrecon-0.7.0/src/danishrecon/api_scanner_module.py +261 -0
- danishrecon-0.7.0/src/danishrecon/cli.py +276 -0
- danishrecon-0.7.0/src/danishrecon/cryptography_analyzer.py +222 -0
- danishrecon-0.7.0/src/danishrecon/cve_lookup.py +161 -0
- danishrecon-0.7.0/src/danishrecon/dirbuster_scanner.py +99 -0
- danishrecon-0.7.0/src/danishrecon/exploit_search.py +115 -0
- danishrecon-0.7.0/src/danishrecon/findings.py +184 -0
- danishrecon-0.7.0/src/danishrecon/gemini_analyzer.py +587 -0
- danishrecon-0.7.0/src/danishrecon/gui.py +3131 -0
- danishrecon-0.7.0/src/danishrecon/nuclei_scanner.py +412 -0
- danishrecon-0.7.0/src/danishrecon/openvas_scanner.py +630 -0
- danishrecon-0.7.0/src/danishrecon/preflight.py +485 -0
- danishrecon-0.7.0/src/danishrecon/recommendation_engine.py +278 -0
- danishrecon-0.7.0/src/danishrecon/recon_tools.py +377 -0
- danishrecon-0.7.0/src/danishrecon/scan_core.py +5470 -0
- danishrecon-0.7.0/src/danishrecon/scout_chatbot/__init__.py +1 -0
- danishrecon-0.7.0/src/danishrecon/scout_chatbot/danishrecon_bridge.py +393 -0
- danishrecon-0.7.0/src/danishrecon/scout_chatbot/index.html +262 -0
- danishrecon-0.7.0/src/danishrecon/scout_chatbot/requirements.txt +8 -0
- danishrecon-0.7.0/src/danishrecon/scout_chatbot/scout.py +724 -0
- danishrecon-0.7.0/src/danishrecon/scout_panel.py +233 -0
- danishrecon-0.7.0/src/danishrecon/web_vulnerability_scanner.py +287 -0
- danishrecon-0.7.0/src/danishrecon/webapp/__init__.py +0 -0
- danishrecon-0.7.0/src/danishrecon/webapp/index.html +258 -0
- danishrecon-0.7.0/src/danishrecon/webapp/server.py +225 -0
- danishrecon-0.7.0/src/danishrecon/yara_rules/botnet.yar +94 -0
- danishrecon-0.7.0/src/danishrecon/yara_rules/builtin.yar +45 -0
- danishrecon-0.7.0/src/danishrecon.egg-info/PKG-INFO +190 -0
- danishrecon-0.7.0/src/danishrecon.egg-info/SOURCES.txt +47 -0
- danishrecon-0.7.0/src/danishrecon.egg-info/dependency_links.txt +1 -0
- danishrecon-0.7.0/src/danishrecon.egg-info/entry_points.txt +7 -0
- danishrecon-0.7.0/src/danishrecon.egg-info/requires.txt +40 -0
- danishrecon-0.7.0/src/danishrecon.egg-info/top_level.txt +1 -0
- danishrecon-0.7.0/tests/test_benchmark.py +93 -0
- danishrecon-0.7.0/tests/test_phase0.py +300 -0
- danishrecon-0.7.0/tests/test_phase1.py +270 -0
- danishrecon-0.7.0/tests/test_phase2.py +288 -0
- danishrecon-0.7.0/tests/test_phase3.py +175 -0
- danishrecon-0.7.0/tests/test_phase4.py +175 -0
- danishrecon-0.7.0/tests/test_phase5.py +148 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 The DanishRecon contributors
|
|
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,190 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: danishrecon
|
|
3
|
+
Version: 0.7.0
|
|
4
|
+
Summary: Security toolkit: recon + web vulnerability scanning, static malware analysis and network-traffic analysis. For authorized testing only.
|
|
5
|
+
Author: Danish Dhanjal
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/DanishDhanjal15/DanishRecon-Main
|
|
8
|
+
Project-URL: Issues, https://github.com/DanishDhanjal15/DanishRecon-Main/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/DanishDhanjal15/DanishRecon-Main/blob/main/docs/CHANGES_AND_ROADMAP.md
|
|
10
|
+
Keywords: security,vulnerability-scanner,reconnaissance,pentest,dast,nuclei,nmap,malware-analysis,pcap
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Information Technology
|
|
13
|
+
Classifier: Intended Audience :: System Administrators
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Security
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: requests>=2.31
|
|
24
|
+
Requires-Dist: networkx>=3.0
|
|
25
|
+
Requires-Dist: matplotlib>=3.7
|
|
26
|
+
Requires-Dist: cryptography>=42
|
|
27
|
+
Requires-Dist: python-dotenv>=1.0
|
|
28
|
+
Requires-Dist: reportlab>=4.0
|
|
29
|
+
Provides-Extra: gui
|
|
30
|
+
Requires-Dist: PyQt5>=5.15; extra == "gui"
|
|
31
|
+
Provides-Extra: web
|
|
32
|
+
Requires-Dist: fastapi>=0.110; extra == "web"
|
|
33
|
+
Requires-Dist: uvicorn>=0.29; extra == "web"
|
|
34
|
+
Provides-Extra: malware
|
|
35
|
+
Requires-Dist: pefile>=2023.2.7; extra == "malware"
|
|
36
|
+
Requires-Dist: yara-python>=4.3; extra == "malware"
|
|
37
|
+
Requires-Dist: oletools>=0.60; extra == "malware"
|
|
38
|
+
Provides-Extra: ai
|
|
39
|
+
Requires-Dist: google-genai>=1.0; extra == "ai"
|
|
40
|
+
Provides-Extra: openvas
|
|
41
|
+
Requires-Dist: python-gvm<22; extra == "openvas"
|
|
42
|
+
Provides-Extra: scout
|
|
43
|
+
Requires-Dist: fastapi>=0.110; extra == "scout"
|
|
44
|
+
Requires-Dist: uvicorn>=0.29; extra == "scout"
|
|
45
|
+
Requires-Dist: pydantic; extra == "scout"
|
|
46
|
+
Requires-Dist: httpx; extra == "scout"
|
|
47
|
+
Requires-Dist: google-generativeai; extra == "scout"
|
|
48
|
+
Provides-Extra: all
|
|
49
|
+
Requires-Dist: danishrecon[ai,gui,malware,web]; extra == "all"
|
|
50
|
+
Provides-Extra: dev
|
|
51
|
+
Requires-Dist: danishrecon[malware,web]; extra == "dev"
|
|
52
|
+
Requires-Dist: build; extra == "dev"
|
|
53
|
+
Requires-Dist: twine; extra == "dev"
|
|
54
|
+
Requires-Dist: httpx; extra == "dev"
|
|
55
|
+
Dynamic: license-file
|
|
56
|
+
|
|
57
|
+
# DanishRecon
|
|
58
|
+
|
|
59
|
+

|
|
60
|
+

|
|
61
|
+
|
|
62
|
+
An open-source **security toolkit** with three modes that share one engine, one database
|
|
63
|
+
and one report format:
|
|
64
|
+
|
|
65
|
+
| Mode | Input | Command |
|
|
66
|
+
|---|---|---|
|
|
67
|
+
| Recon + web vulnerability scan | a host or URL | `danishrecon scan <target> --i-am-authorized` |
|
|
68
|
+
| Static malware analysis | file(s) or a folder | `danishrecon malware <path>` |
|
|
69
|
+
| Network traffic analysis | a .pcap, or a live interface | `danishrecon sniff <pcap>` |
|
|
70
|
+
|
|
71
|
+
It does not reinvent detection engines. It orchestrates proven open-source tools (nmap,
|
|
72
|
+
nuclei, katana, httpx, tshark, YARA), keeps every result in one evidence-backed finding
|
|
73
|
+
model, and reports only what was actually observed.
|
|
74
|
+
|
|
75
|
+
> **Authorized use only.** Scan systems you own or have explicit written permission to
|
|
76
|
+
> test. The CLI refuses to scan without `--i-am-authorized`, and the GUI and dashboard ask
|
|
77
|
+
> for the same confirmation.
|
|
78
|
+
|
|
79
|
+
## Install
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
pip install danishrecon # scan engine + CLI
|
|
83
|
+
pip install "danishrecon[gui]" # + desktop GUI (PyQt5)
|
|
84
|
+
pip install "danishrecon[web]" # + web dashboard
|
|
85
|
+
pip install "danishrecon[malware]" # + YARA, PE and Office-macro analysis
|
|
86
|
+
pip install "danishrecon[all]" # everything above
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
pip installs the Python code only. The scanners it drives are separate programs:
|
|
90
|
+
|
|
91
|
+
| Tool | Needed for | Install |
|
|
92
|
+
|---|---|---|
|
|
93
|
+
| **nmap** (required) | ports, services, TLS cipher audit | https://nmap.org/download |
|
|
94
|
+
| nuclei, katana, httpx, subfinder (recommended) | crawl, injection tests, exposure templates | `go install github.com/projectdiscovery/<tool>/...@latest` |
|
|
95
|
+
| tshark / Wireshark | traffic analysis | https://www.wireshark.org/download.html |
|
|
96
|
+
| rustscan (optional) | fast all-ports discovery on the `Full` profile | `cargo install rustscan` |
|
|
97
|
+
| Nikto, an exploit-database checkout, OpenVAS (optional) | extra checks, exploit references | see `docs/FEATURES.md` |
|
|
98
|
+
|
|
99
|
+
Run `danishrecon-preflight` to see what is installed. A missing optional tool is reported
|
|
100
|
+
in the scan log as "not tested"; it never produces simulated results.
|
|
101
|
+
|
|
102
|
+
## Use
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
# recon + vulnerability scan
|
|
106
|
+
danishrecon scan example.com --i-am-authorized
|
|
107
|
+
danishrecon scan https://app.example.com --i-am-authorized --profile Full --nuclei
|
|
108
|
+
danishrecon scan https://app.example.com --i-am-authorized --cookie "session=abc123"
|
|
109
|
+
danishrecon scan example.com --i-am-authorized --fail-on high # exit code 1 for CI
|
|
110
|
+
|
|
111
|
+
# static malware analysis (files are never executed)
|
|
112
|
+
danishrecon malware suspicious.exe
|
|
113
|
+
danishrecon malware ./samples --reputation # + MalwareBazaar lookup (sends the hash only)
|
|
114
|
+
|
|
115
|
+
# traffic analysis
|
|
116
|
+
danishrecon sniff capture.pcap --ioc-file bad_domains.txt
|
|
117
|
+
danishrecon sniff "Wi-Fi" --live --i-am-authorized --duration 60
|
|
118
|
+
|
|
119
|
+
# front-ends
|
|
120
|
+
danishrecon-gui # desktop GUI
|
|
121
|
+
danishrecon-web # dashboard on http://127.0.0.1:8787
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Every command writes to `./results/` (or `--output-dir`): an HTML report, `scan_<id>.json`,
|
|
125
|
+
`findings_<id>.json` and `scan_<id>.sarif`.
|
|
126
|
+
|
|
127
|
+
## What a scan does
|
|
128
|
+
|
|
129
|
+
DNS and subdomains, ports and versions (a fast path on CDN hosts), TLS certificate /
|
|
130
|
+
protocol / cipher checks, known CVEs for the detected versions (NVD, CISA KEV, EPSS), a
|
|
131
|
+
crawl followed by injection tests on every parameter and submitted form (nuclei DAST),
|
|
132
|
+
exposure and misconfiguration templates, leaked secrets, DDoS amplification exposure, and
|
|
133
|
+
Exploit-DB references. Details: [docs/FEATURES.md](docs/FEATURES.md).
|
|
134
|
+
|
|
135
|
+
Every finding carries a **source** (which tool) and a **confidence**:
|
|
136
|
+
|
|
137
|
+
- `confirmed` - a tool observed the vulnerable behaviour
|
|
138
|
+
- `version-match` - the detected version is listed as affected (not verified)
|
|
139
|
+
- `exposure` - a service is reachable; not a vulnerability by itself
|
|
140
|
+
- `heuristic` - weak signal, needs manual review
|
|
141
|
+
|
|
142
|
+
## Accuracy
|
|
143
|
+
|
|
144
|
+
The repository ships a benchmark with known ground truth (`benchmark/`):
|
|
145
|
+
|
|
146
|
+
- Local ground-truth app: **5/5 expected issues detected, 0 false positives**
|
|
147
|
+
(GET parameter, POST body, behind a login, exposed secret).
|
|
148
|
+
- OWASP Juice Shop: **2/10 detected, 0 false positives**. Partial on purpose to show: it is
|
|
149
|
+
a single-page app whose API calls come from JavaScript, which the crawler only partly
|
|
150
|
+
discovers.
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
python benchmark/run_benchmark.py --min-recall 1.0 --max-false-positives 0
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Privacy
|
|
157
|
+
|
|
158
|
+
Scan data stays on your machine. Four things can leave it, all optional:
|
|
159
|
+
|
|
160
|
+
- **NVD / EPSS lookup** sends product identifiers and CVE ids only (`--no-nvd` to disable)
|
|
161
|
+
- **MalwareBazaar lookup** sends a file hash, only with `--reputation`
|
|
162
|
+
- **Gemini analysis** sends finding summaries to Google, only with `--ai`
|
|
163
|
+
- **Login alert (GUI)** sends a WhatsApp message through Twilio, only if you configure it in `.env`
|
|
164
|
+
|
|
165
|
+
nuclei runs with interactsh disabled, so no out-of-band callbacks go to third parties.
|
|
166
|
+
|
|
167
|
+
## Limitations
|
|
168
|
+
|
|
169
|
+
- Form login is a plain POST; logins that need a CSRF token, JavaScript or MFA need `--cookie`.
|
|
170
|
+
- No access-control (IDOR) testing and no business-logic testing.
|
|
171
|
+
- `version-match` CVEs are not verified; distributions back-port fixes.
|
|
172
|
+
- Malware analysis is static only. There is no sandbox, by design.
|
|
173
|
+
- The Nikto stage is unreliable on Windows.
|
|
174
|
+
- The GUI launches recon scans only; malware and traffic analysis run from the CLI.
|
|
175
|
+
|
|
176
|
+
## Development
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
git clone https://github.com/DanishDhanjal15/DanishRecon-Main
|
|
180
|
+
cd DanishRecon-Main
|
|
181
|
+
pip install -e ".[dev]"
|
|
182
|
+
python -m unittest discover -s tests -v
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md), [SECURITY.md](SECURITY.md) and
|
|
186
|
+
[docs/CHANGES_AND_ROADMAP.md](docs/CHANGES_AND_ROADMAP.md).
|
|
187
|
+
|
|
188
|
+
## License
|
|
189
|
+
|
|
190
|
+
MIT - see [LICENSE](LICENSE). DanishRecon started as the CyberRecon-Pro hackathon project.
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# DanishRecon
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+

|
|
5
|
+
|
|
6
|
+
An open-source **security toolkit** with three modes that share one engine, one database
|
|
7
|
+
and one report format:
|
|
8
|
+
|
|
9
|
+
| Mode | Input | Command |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| Recon + web vulnerability scan | a host or URL | `danishrecon scan <target> --i-am-authorized` |
|
|
12
|
+
| Static malware analysis | file(s) or a folder | `danishrecon malware <path>` |
|
|
13
|
+
| Network traffic analysis | a .pcap, or a live interface | `danishrecon sniff <pcap>` |
|
|
14
|
+
|
|
15
|
+
It does not reinvent detection engines. It orchestrates proven open-source tools (nmap,
|
|
16
|
+
nuclei, katana, httpx, tshark, YARA), keeps every result in one evidence-backed finding
|
|
17
|
+
model, and reports only what was actually observed.
|
|
18
|
+
|
|
19
|
+
> **Authorized use only.** Scan systems you own or have explicit written permission to
|
|
20
|
+
> test. The CLI refuses to scan without `--i-am-authorized`, and the GUI and dashboard ask
|
|
21
|
+
> for the same confirmation.
|
|
22
|
+
|
|
23
|
+
## Install
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pip install danishrecon # scan engine + CLI
|
|
27
|
+
pip install "danishrecon[gui]" # + desktop GUI (PyQt5)
|
|
28
|
+
pip install "danishrecon[web]" # + web dashboard
|
|
29
|
+
pip install "danishrecon[malware]" # + YARA, PE and Office-macro analysis
|
|
30
|
+
pip install "danishrecon[all]" # everything above
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
pip installs the Python code only. The scanners it drives are separate programs:
|
|
34
|
+
|
|
35
|
+
| Tool | Needed for | Install |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| **nmap** (required) | ports, services, TLS cipher audit | https://nmap.org/download |
|
|
38
|
+
| nuclei, katana, httpx, subfinder (recommended) | crawl, injection tests, exposure templates | `go install github.com/projectdiscovery/<tool>/...@latest` |
|
|
39
|
+
| tshark / Wireshark | traffic analysis | https://www.wireshark.org/download.html |
|
|
40
|
+
| rustscan (optional) | fast all-ports discovery on the `Full` profile | `cargo install rustscan` |
|
|
41
|
+
| Nikto, an exploit-database checkout, OpenVAS (optional) | extra checks, exploit references | see `docs/FEATURES.md` |
|
|
42
|
+
|
|
43
|
+
Run `danishrecon-preflight` to see what is installed. A missing optional tool is reported
|
|
44
|
+
in the scan log as "not tested"; it never produces simulated results.
|
|
45
|
+
|
|
46
|
+
## Use
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# recon + vulnerability scan
|
|
50
|
+
danishrecon scan example.com --i-am-authorized
|
|
51
|
+
danishrecon scan https://app.example.com --i-am-authorized --profile Full --nuclei
|
|
52
|
+
danishrecon scan https://app.example.com --i-am-authorized --cookie "session=abc123"
|
|
53
|
+
danishrecon scan example.com --i-am-authorized --fail-on high # exit code 1 for CI
|
|
54
|
+
|
|
55
|
+
# static malware analysis (files are never executed)
|
|
56
|
+
danishrecon malware suspicious.exe
|
|
57
|
+
danishrecon malware ./samples --reputation # + MalwareBazaar lookup (sends the hash only)
|
|
58
|
+
|
|
59
|
+
# traffic analysis
|
|
60
|
+
danishrecon sniff capture.pcap --ioc-file bad_domains.txt
|
|
61
|
+
danishrecon sniff "Wi-Fi" --live --i-am-authorized --duration 60
|
|
62
|
+
|
|
63
|
+
# front-ends
|
|
64
|
+
danishrecon-gui # desktop GUI
|
|
65
|
+
danishrecon-web # dashboard on http://127.0.0.1:8787
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Every command writes to `./results/` (or `--output-dir`): an HTML report, `scan_<id>.json`,
|
|
69
|
+
`findings_<id>.json` and `scan_<id>.sarif`.
|
|
70
|
+
|
|
71
|
+
## What a scan does
|
|
72
|
+
|
|
73
|
+
DNS and subdomains, ports and versions (a fast path on CDN hosts), TLS certificate /
|
|
74
|
+
protocol / cipher checks, known CVEs for the detected versions (NVD, CISA KEV, EPSS), a
|
|
75
|
+
crawl followed by injection tests on every parameter and submitted form (nuclei DAST),
|
|
76
|
+
exposure and misconfiguration templates, leaked secrets, DDoS amplification exposure, and
|
|
77
|
+
Exploit-DB references. Details: [docs/FEATURES.md](docs/FEATURES.md).
|
|
78
|
+
|
|
79
|
+
Every finding carries a **source** (which tool) and a **confidence**:
|
|
80
|
+
|
|
81
|
+
- `confirmed` - a tool observed the vulnerable behaviour
|
|
82
|
+
- `version-match` - the detected version is listed as affected (not verified)
|
|
83
|
+
- `exposure` - a service is reachable; not a vulnerability by itself
|
|
84
|
+
- `heuristic` - weak signal, needs manual review
|
|
85
|
+
|
|
86
|
+
## Accuracy
|
|
87
|
+
|
|
88
|
+
The repository ships a benchmark with known ground truth (`benchmark/`):
|
|
89
|
+
|
|
90
|
+
- Local ground-truth app: **5/5 expected issues detected, 0 false positives**
|
|
91
|
+
(GET parameter, POST body, behind a login, exposed secret).
|
|
92
|
+
- OWASP Juice Shop: **2/10 detected, 0 false positives**. Partial on purpose to show: it is
|
|
93
|
+
a single-page app whose API calls come from JavaScript, which the crawler only partly
|
|
94
|
+
discovers.
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
python benchmark/run_benchmark.py --min-recall 1.0 --max-false-positives 0
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Privacy
|
|
101
|
+
|
|
102
|
+
Scan data stays on your machine. Four things can leave it, all optional:
|
|
103
|
+
|
|
104
|
+
- **NVD / EPSS lookup** sends product identifiers and CVE ids only (`--no-nvd` to disable)
|
|
105
|
+
- **MalwareBazaar lookup** sends a file hash, only with `--reputation`
|
|
106
|
+
- **Gemini analysis** sends finding summaries to Google, only with `--ai`
|
|
107
|
+
- **Login alert (GUI)** sends a WhatsApp message through Twilio, only if you configure it in `.env`
|
|
108
|
+
|
|
109
|
+
nuclei runs with interactsh disabled, so no out-of-band callbacks go to third parties.
|
|
110
|
+
|
|
111
|
+
## Limitations
|
|
112
|
+
|
|
113
|
+
- Form login is a plain POST; logins that need a CSRF token, JavaScript or MFA need `--cookie`.
|
|
114
|
+
- No access-control (IDOR) testing and no business-logic testing.
|
|
115
|
+
- `version-match` CVEs are not verified; distributions back-port fixes.
|
|
116
|
+
- Malware analysis is static only. There is no sandbox, by design.
|
|
117
|
+
- The Nikto stage is unreliable on Windows.
|
|
118
|
+
- The GUI launches recon scans only; malware and traffic analysis run from the CLI.
|
|
119
|
+
|
|
120
|
+
## Development
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
git clone https://github.com/DanishDhanjal15/DanishRecon-Main
|
|
124
|
+
cd DanishRecon-Main
|
|
125
|
+
pip install -e ".[dev]"
|
|
126
|
+
python -m unittest discover -s tests -v
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md), [SECURITY.md](SECURITY.md) and
|
|
130
|
+
[docs/CHANGES_AND_ROADMAP.md](docs/CHANGES_AND_ROADMAP.md).
|
|
131
|
+
|
|
132
|
+
## License
|
|
133
|
+
|
|
134
|
+
MIT - see [LICENSE](LICENSE). DanishRecon started as the CyberRecon-Pro hackathon project.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "danishrecon"
|
|
7
|
+
version = "0.7.0"
|
|
8
|
+
description = "Security toolkit: recon + web vulnerability scanning, static malware analysis and network-traffic analysis. For authorized testing only."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
authors = [{ name = "Danish Dhanjal" }]
|
|
14
|
+
keywords = ["security", "vulnerability-scanner", "reconnaissance", "pentest", "dast", "nuclei", "nmap", "malware-analysis", "pcap"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 4 - Beta",
|
|
17
|
+
"Intended Audience :: Information Technology",
|
|
18
|
+
"Intended Audience :: System Administrators",
|
|
19
|
+
"Operating System :: OS Independent",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.10",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Topic :: Security",
|
|
25
|
+
]
|
|
26
|
+
# Core = scan engine + CLI. External tools (nmap, nuclei, katana, httpx, tshark, ...) are
|
|
27
|
+
# separate programs and are NOT installed by pip - see the README.
|
|
28
|
+
dependencies = [
|
|
29
|
+
"requests>=2.31",
|
|
30
|
+
"networkx>=3.0",
|
|
31
|
+
"matplotlib>=3.7",
|
|
32
|
+
"cryptography>=42",
|
|
33
|
+
"python-dotenv>=1.0",
|
|
34
|
+
"reportlab>=4.0",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
[project.optional-dependencies]
|
|
38
|
+
gui = ["PyQt5>=5.15"]
|
|
39
|
+
web = ["fastapi>=0.110", "uvicorn>=0.29"]
|
|
40
|
+
malware = ["pefile>=2023.2.7", "yara-python>=4.3", "oletools>=0.60"]
|
|
41
|
+
ai = ["google-genai>=1.0"]
|
|
42
|
+
openvas = ["python-gvm<22"]
|
|
43
|
+
scout = ["fastapi>=0.110", "uvicorn>=0.29", "pydantic", "httpx", "google-generativeai"]
|
|
44
|
+
all = ["danishrecon[gui,web,malware,ai]"]
|
|
45
|
+
dev = ["danishrecon[web,malware]", "build", "twine", "httpx"]
|
|
46
|
+
|
|
47
|
+
[project.scripts]
|
|
48
|
+
danishrecon = "danishrecon.cli:main"
|
|
49
|
+
danishrecon-web = "danishrecon.webapp.server:main"
|
|
50
|
+
danishrecon-preflight = "danishrecon.preflight:main"
|
|
51
|
+
|
|
52
|
+
[project.gui-scripts]
|
|
53
|
+
danishrecon-gui = "danishrecon.gui:main"
|
|
54
|
+
|
|
55
|
+
[project.urls]
|
|
56
|
+
Homepage = "https://github.com/DanishDhanjal15/DanishRecon-Main"
|
|
57
|
+
Issues = "https://github.com/DanishDhanjal15/DanishRecon-Main/issues"
|
|
58
|
+
Changelog = "https://github.com/DanishDhanjal15/DanishRecon-Main/blob/main/docs/CHANGES_AND_ROADMAP.md"
|
|
59
|
+
|
|
60
|
+
[tool.setuptools.packages.find]
|
|
61
|
+
where = ["src"]
|
|
62
|
+
|
|
63
|
+
[tool.setuptools.package-data]
|
|
64
|
+
danishrecon = ["yara_rules/*.yar", "webapp/*.html", "scout_chatbot/*.html", "scout_chatbot/*.txt"]
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
DDoS amplification / reflection exposure checks (defensive).
|
|
4
|
+
|
|
5
|
+
For each UDP service that attackers abuse as a reflector, send ONE small, well-formed probe
|
|
6
|
+
to the target and see whether it answers - and how much bigger the answer is than the probe
|
|
7
|
+
(the amplification factor). A service that answers an unauthenticated UDP probe with a larger
|
|
8
|
+
reply can be abused to reflect/amplify traffic at a third party, so it is a real exposure on
|
|
9
|
+
the owner's own host.
|
|
10
|
+
|
|
11
|
+
This is a single probe packet per vector (standard scanning), never a flood. Run it only
|
|
12
|
+
against hosts you are authorized to scan - the engine already gates that.
|
|
13
|
+
"""
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import socket
|
|
17
|
+
import struct
|
|
18
|
+
from typing import Dict, List, Optional
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# ── probe payload builders ──────────────────────────────────────────────────────
|
|
22
|
+
def dns_query(name: str = "peacecorps.gov", qtype: int = 255) -> bytes:
|
|
23
|
+
"""Recursive DNS query (RD=1) for an external name. A host that is not authoritative
|
|
24
|
+
for it yet returns answers is an OPEN RESOLVER (type 255 = ANY maximises the reply)."""
|
|
25
|
+
header = b"\x13\x37" + b"\x01\x00" + struct.pack(">HHHH", 1, 0, 0, 0) # RD=1, 1 question
|
|
26
|
+
q = b"".join(bytes([len(lbl)]) + lbl.encode() for lbl in name.split(".")) + b"\x00"
|
|
27
|
+
q += struct.pack(">HH", qtype, 1) # qtype, class IN
|
|
28
|
+
return header + q
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def ntp_monlist() -> bytes:
|
|
32
|
+
"""NTP mode 7 MON_GETLIST_1 (monlist). A reply means the classic ~556x amplifier."""
|
|
33
|
+
return b"\x17\x00\x03\x2a" + b"\x00" * 4
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def memcached_stats() -> bytes:
|
|
37
|
+
"""UDP memcached 'stats' (8-byte UDP header + command). A reply = exposed (huge amp)."""
|
|
38
|
+
return b"\x00\x01\x00\x00\x00\x01\x00\x00" + b"stats\r\n"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def ssdp_msearch() -> bytes:
|
|
42
|
+
return ("M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\n"
|
|
43
|
+
'MAN: "ssdp:discover"\r\nMX: 2\r\nST: ssdp:all\r\n\r\n').encode()
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def chargen_probe() -> bytes:
|
|
47
|
+
return b"\x01"
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _ber(tag: int, value: bytes) -> bytes:
|
|
51
|
+
"""Minimal definite-length BER TLV (lengths < 128 only, enough for this probe)."""
|
|
52
|
+
return bytes([tag]) + bytes([len(value)]) + value
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _ber_oid(oid: str) -> bytes:
|
|
56
|
+
parts = [int(x) for x in oid.split(".")]
|
|
57
|
+
body = bytes([parts[0] * 40 + parts[1]])
|
|
58
|
+
for n in parts[2:]:
|
|
59
|
+
if n < 128:
|
|
60
|
+
body += bytes([n])
|
|
61
|
+
else:
|
|
62
|
+
chunk = []
|
|
63
|
+
while n:
|
|
64
|
+
chunk.insert(0, n & 0x7F)
|
|
65
|
+
n >>= 7
|
|
66
|
+
for i in range(len(chunk) - 1):
|
|
67
|
+
chunk[i] |= 0x80
|
|
68
|
+
body += bytes(chunk)
|
|
69
|
+
return _ber(0x06, body)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def snmp_get(community: str = "public", oid: str = "1.3.6.1.2.1.1.1.0") -> bytes:
|
|
73
|
+
"""SNMPv1 GetRequest for sysDescr.0 with the given community. A reply from 'public'
|
|
74
|
+
means SNMP is open (info leak + reflection/amplification vector)."""
|
|
75
|
+
varbind = _ber(0x30, _ber_oid(oid) + _ber(0x05, b"")) # OID + NULL
|
|
76
|
+
varbinds = _ber(0x30, varbind)
|
|
77
|
+
pdu = _ber(0xA0, # GetRequest PDU
|
|
78
|
+
_ber(0x02, b"\x13\x37") + # request-id
|
|
79
|
+
_ber(0x02, b"\x00") + # error-status
|
|
80
|
+
_ber(0x02, b"\x00") + # error-index
|
|
81
|
+
varbinds)
|
|
82
|
+
msg = _ber(0x30,
|
|
83
|
+
_ber(0x02, b"\x00") + # version 0 (v1)
|
|
84
|
+
_ber(0x04, community.encode()) + # community
|
|
85
|
+
pdu)
|
|
86
|
+
return msg
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
# ── vector catalogue ────────────────────────────────────────────────────────────
|
|
90
|
+
# severity reflects the amplification potential of the vector when it responds.
|
|
91
|
+
VECTORS = {
|
|
92
|
+
"memcached": {"port": 11211, "name": "memcached exposed on UDP", "payload": memcached_stats,
|
|
93
|
+
"severity": "HIGH", "note": "memcached over UDP can amplify traffic by ~10,000-50,000x"},
|
|
94
|
+
"ntp": {"port": 123, "name": "NTP monlist enabled", "payload": ntp_monlist,
|
|
95
|
+
"severity": "HIGH", "note": "ntp monlist amplifies by ~556x (CVE-2013-5211)"},
|
|
96
|
+
"dns": {"port": 53, "name": "Open DNS resolver (recursion)", "payload": dns_query,
|
|
97
|
+
"severity": "HIGH", "note": "open resolvers are abused for DNS amplification (~28-54x)"},
|
|
98
|
+
"ssdp": {"port": 1900, "name": "SSDP/UPnP responder exposed", "payload": ssdp_msearch,
|
|
99
|
+
"severity": "MEDIUM", "note": "SSDP amplifies by ~30x and leaks device info"},
|
|
100
|
+
"snmp": {"port": 161, "name": "SNMP open with 'public' community", "payload": snmp_get,
|
|
101
|
+
"severity": "MEDIUM", "note": "SNMP GetBulk amplifies by ~6x and leaks system info"},
|
|
102
|
+
"chargen": {"port": 19, "name": "chargen (UDP) enabled", "payload": chargen_probe,
|
|
103
|
+
"severity": "MEDIUM", "note": "chargen amplifies by ~358x and should be disabled"},
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def probe_vector(host: str, vector: str, timeout: float = 3.0) -> Optional[Dict]:
|
|
108
|
+
"""Send one probe for ``vector`` to ``host``. Returns a result dict when the service
|
|
109
|
+
answers (so it is a confirmed reflector), else None. Never raises."""
|
|
110
|
+
spec = VECTORS.get(vector)
|
|
111
|
+
if not spec:
|
|
112
|
+
return None
|
|
113
|
+
payload = spec["payload"]()
|
|
114
|
+
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
115
|
+
sock.settimeout(timeout)
|
|
116
|
+
try:
|
|
117
|
+
sock.sendto(payload, (host, spec["port"]))
|
|
118
|
+
total = 0
|
|
119
|
+
first = None
|
|
120
|
+
# UDP amplifiers often answer with several datagrams; read what arrives in the window.
|
|
121
|
+
while True:
|
|
122
|
+
try:
|
|
123
|
+
data, _ = sock.recvfrom(65535)
|
|
124
|
+
except socket.timeout:
|
|
125
|
+
break
|
|
126
|
+
if first is None:
|
|
127
|
+
first = data
|
|
128
|
+
total += len(data)
|
|
129
|
+
if total > 200000:
|
|
130
|
+
break
|
|
131
|
+
if not total:
|
|
132
|
+
return None
|
|
133
|
+
factor = round(total / max(len(payload), 1), 1)
|
|
134
|
+
return {"vector": vector, "port": spec["port"], "name": spec["name"],
|
|
135
|
+
"severity": spec["severity"], "note": spec["note"],
|
|
136
|
+
"request_bytes": len(payload), "response_bytes": total,
|
|
137
|
+
"amplification_factor": factor}
|
|
138
|
+
except (socket.gaierror, OSError):
|
|
139
|
+
return None
|
|
140
|
+
finally:
|
|
141
|
+
sock.close()
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def check_host(host: str, vectors: Optional[List[str]] = None, timeout: float = 3.0,
|
|
145
|
+
stop_check=None) -> List[Dict]:
|
|
146
|
+
"""Probe all (or the given) amplification vectors on one host; return confirmed hits."""
|
|
147
|
+
results = []
|
|
148
|
+
for v in (vectors or list(VECTORS)):
|
|
149
|
+
if stop_check and stop_check():
|
|
150
|
+
break
|
|
151
|
+
hit = probe_vector(host, v, timeout)
|
|
152
|
+
if hit:
|
|
153
|
+
results.append(hit)
|
|
154
|
+
return results
|