webpeek 1.2.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.
- webpeek-1.2.1/PKG-INFO +195 -0
- webpeek-1.2.1/README.md +165 -0
- webpeek-1.2.1/pyproject.toml +40 -0
- webpeek-1.2.1/setup.cfg +4 -0
- webpeek-1.2.1/setup.py +42 -0
- webpeek-1.2.1/webpeek/__init__.py +1 -0
- webpeek-1.2.1/webpeek/cli.py +137 -0
- webpeek-1.2.1/webpeek/core/__init__.py +0 -0
- webpeek-1.2.1/webpeek/core/output.py +51 -0
- webpeek-1.2.1/webpeek/core/scanner.py +252 -0
- webpeek-1.2.1/webpeek/modules/__init__.py +0 -0
- webpeek-1.2.1/webpeek/modules/emails.py +437 -0
- webpeek-1.2.1/webpeek/modules/exposed.py +67 -0
- webpeek-1.2.1/webpeek/modules/geo.py +12 -0
- webpeek-1.2.1/webpeek/modules/headers.py +15 -0
- webpeek-1.2.1/webpeek/modules/robots.py +181 -0
- webpeek-1.2.1/webpeek/modules/security_headers.py +42 -0
- webpeek-1.2.1/webpeek/modules/sitemap.py +87 -0
- webpeek-1.2.1/webpeek/modules/ssl_info.py +20 -0
- webpeek-1.2.1/webpeek/modules/subdomains.py +54 -0
- webpeek-1.2.1/webpeek/modules/tech.py +117 -0
- webpeek-1.2.1/webpeek/modules/wplugins.py +67 -0
- webpeek-1.2.1/webpeek/utils/__init__.py +0 -0
- webpeek-1.2.1/webpeek/utils/colors.py +200 -0
- webpeek-1.2.1/webpeek.egg-info/PKG-INFO +195 -0
- webpeek-1.2.1/webpeek.egg-info/SOURCES.txt +28 -0
- webpeek-1.2.1/webpeek.egg-info/dependency_links.txt +1 -0
- webpeek-1.2.1/webpeek.egg-info/entry_points.txt +2 -0
- webpeek-1.2.1/webpeek.egg-info/requires.txt +16 -0
- webpeek-1.2.1/webpeek.egg-info/top_level.txt +2 -0
webpeek-1.2.1/PKG-INFO
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: webpeek
|
|
3
|
+
Version: 1.2.1
|
|
4
|
+
Summary: OSINT CLI tool for web reconnaissance
|
|
5
|
+
Home-page: https://github.com/JorgeRosbel/webpeek
|
|
6
|
+
Author: JorgeRosbel
|
|
7
|
+
Author-email: JorgeRosbel <jorge@rosbel.dev>
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Homepage, https://github.com/JorgeRosbel/webpeek
|
|
10
|
+
Requires-Python: >=3.8
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
Requires-Dist: click>=8.0
|
|
13
|
+
Requires-Dist: requests>=2.28
|
|
14
|
+
Requires-Dist: dnspython>=2.1
|
|
15
|
+
Requires-Dist: whois>=0.9
|
|
16
|
+
Requires-Dist: beautifulsoup4>=4.9
|
|
17
|
+
Requires-Dist: lxml>=4.6
|
|
18
|
+
Requires-Dist: colorama>=0.4
|
|
19
|
+
Requires-Dist: tldextract>=3.1
|
|
20
|
+
Requires-Dist: pwntools>=4.0
|
|
21
|
+
Requires-Dist: playwright>=1.40
|
|
22
|
+
Requires-Dist: pyee>=10.0
|
|
23
|
+
Requires-Dist: greenlet>=3.0
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: twine; extra == "dev"
|
|
26
|
+
Requires-Dist: build; extra == "dev"
|
|
27
|
+
Dynamic: author
|
|
28
|
+
Dynamic: home-page
|
|
29
|
+
Dynamic: requires-python
|
|
30
|
+
|
|
31
|
+
# webpeek
|
|
32
|
+
|
|
33
|
+
OSINT CLI tool for web reconnaissance - gather passive and active information about websites.
|
|
34
|
+
|
|
35
|
+
## Installation
|
|
36
|
+
|
|
37
|
+
### From PyPI (recommended when published)
|
|
38
|
+
```bash
|
|
39
|
+
pip install webpeek
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### From GitHub
|
|
43
|
+
```bash
|
|
44
|
+
pip install git+https://github.com/JorgeRosbel/webpeek.git
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Local development
|
|
48
|
+
```bash
|
|
49
|
+
git clone https://github.com/JorgeRosbel/webpeek.git
|
|
50
|
+
cd webpeek
|
|
51
|
+
pip install -e .
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Usage
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# Basic scan
|
|
58
|
+
webpeek example.com
|
|
59
|
+
|
|
60
|
+
# Hybrid mode (active + passive)
|
|
61
|
+
webpeek example.com -H
|
|
62
|
+
|
|
63
|
+
# Passive only
|
|
64
|
+
webpeek example.com -P
|
|
65
|
+
|
|
66
|
+
# Active only
|
|
67
|
+
webpeek example.com -A
|
|
68
|
+
|
|
69
|
+
# Dynamic mode (for JavaScript sites)
|
|
70
|
+
webpeek example.com -H -y
|
|
71
|
+
|
|
72
|
+
# Specific modules
|
|
73
|
+
webpeek example.com -T -l -e -p
|
|
74
|
+
|
|
75
|
+
# Save to file
|
|
76
|
+
webpeek example.com -H -oN result.txt
|
|
77
|
+
|
|
78
|
+
# Without colors
|
|
79
|
+
webpeek example.com -C
|
|
80
|
+
|
|
81
|
+
# Help
|
|
82
|
+
webpeek --help
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Options
|
|
86
|
+
|
|
87
|
+
| Short | Flag | Description |
|
|
88
|
+
|-------|------|-------------|
|
|
89
|
+
| `-H` | `--hybrid` | Run both active and passive modules |
|
|
90
|
+
| `-A` | `--active` | Run all active modules |
|
|
91
|
+
| `-P` | `--passive` | Run all passive modules |
|
|
92
|
+
| `-y` | `--dynamic` | Use headless browser (Playwright) |
|
|
93
|
+
| `-oN` | `--output` | Save output to file |
|
|
94
|
+
| `-C` | `--no-color` | Disable colors |
|
|
95
|
+
| `-v` | `--verbose` | Verbose output |
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Passive Modules
|
|
100
|
+
|
|
101
|
+
Gather information from public sources without connecting directly to the target.
|
|
102
|
+
|
|
103
|
+
| Short | Flag | Description |
|
|
104
|
+
|-------|------|-------------|
|
|
105
|
+
| `-w` | `--whois` | Domain registration info |
|
|
106
|
+
| `-d` | `--dns` | DNS A records |
|
|
107
|
+
| `-m` | `--mx` | MX records |
|
|
108
|
+
| `-t` | `--txt` | TXT records (SPF, DKIM) |
|
|
109
|
+
| `-S` | `--subdomains` | Find subdomains |
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Active Modules
|
|
114
|
+
|
|
115
|
+
Gather information by connecting directly to the target.
|
|
116
|
+
|
|
117
|
+
| Short | Flag | Description |
|
|
118
|
+
|-------|------|-------------|
|
|
119
|
+
| `-h` | `--headers` | HTTP headers |
|
|
120
|
+
| `-c` | `--security` | Security headers |
|
|
121
|
+
| `-T` | `--tech` | Detect technologies |
|
|
122
|
+
| `-W` | `--wplugins` | WordPress plugins |
|
|
123
|
+
| `-s` | `--ssl` | SSL certificate info |
|
|
124
|
+
| `-g` | `--geo` | Geolocation |
|
|
125
|
+
| `-O` | `--os` | OS detection |
|
|
126
|
+
| `-i` | `--title` | Page title |
|
|
127
|
+
| `-D` | `--description` | Meta description |
|
|
128
|
+
| `-e` | `--emails` | Extract emails |
|
|
129
|
+
| `-p` | `--phones` | Extract phone numbers |
|
|
130
|
+
| `-M` | `--sitemap` | Sitemap URLs |
|
|
131
|
+
| `-r` | `--robots` | Robots.txt |
|
|
132
|
+
| `-l` | `--social` | Social networks |
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Dynamic Mode
|
|
137
|
+
|
|
138
|
+
Use `-y` for JavaScript-rendered sites (React, Vue, Angular, etc.):
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
webpeek example.com -T -y
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
First time using dynamic mode will download Chromium (~150MB).
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Example Output
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
╔════════════════════════════════════════════════════════╗
|
|
152
|
+
║ 🌐 WEBPEEK v1.0.0 - example.com ║
|
|
153
|
+
╚════════════════════════════════════════════════════════╝
|
|
154
|
+
|
|
155
|
+
📡 PASSIVE MODE
|
|
156
|
+
─────────────────────
|
|
157
|
+
◉ WHOIS:
|
|
158
|
+
└─ Registrar: NameCheap, Inc.
|
|
159
|
+
└─ Created: 2025-12-14
|
|
160
|
+
└─ Expires: 2026-12-14
|
|
161
|
+
|
|
162
|
+
◉ DNS:
|
|
163
|
+
└─ 93.184.216.34
|
|
164
|
+
|
|
165
|
+
⚡ ACTIVE MODE
|
|
166
|
+
─────────────────────
|
|
167
|
+
◉ IP:
|
|
168
|
+
└─ 93.184.216.34
|
|
169
|
+
|
|
170
|
+
◉ Geo:
|
|
171
|
+
└─ US, California (Cloudflare, Inc.)
|
|
172
|
+
|
|
173
|
+
◉ Technologies:
|
|
174
|
+
└─ Cloudflare
|
|
175
|
+
└─ Nginx
|
|
176
|
+
|
|
177
|
+
◉ SSL:
|
|
178
|
+
└─ example.com (expires in 90 days)
|
|
179
|
+
|
|
180
|
+
╔════════════════════════════════════════════════════════╗
|
|
181
|
+
║ Scan complete! ║
|
|
182
|
+
╚════════════════════════════════════════════════════════╝
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Uninstall
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
pip uninstall webpeek
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## License
|
|
194
|
+
|
|
195
|
+
MIT
|
webpeek-1.2.1/README.md
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# webpeek
|
|
2
|
+
|
|
3
|
+
OSINT CLI tool for web reconnaissance - gather passive and active information about websites.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
### From PyPI (recommended when published)
|
|
8
|
+
```bash
|
|
9
|
+
pip install webpeek
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
### From GitHub
|
|
13
|
+
```bash
|
|
14
|
+
pip install git+https://github.com/JorgeRosbel/webpeek.git
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### Local development
|
|
18
|
+
```bash
|
|
19
|
+
git clone https://github.com/JorgeRosbel/webpeek.git
|
|
20
|
+
cd webpeek
|
|
21
|
+
pip install -e .
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# Basic scan
|
|
28
|
+
webpeek example.com
|
|
29
|
+
|
|
30
|
+
# Hybrid mode (active + passive)
|
|
31
|
+
webpeek example.com -H
|
|
32
|
+
|
|
33
|
+
# Passive only
|
|
34
|
+
webpeek example.com -P
|
|
35
|
+
|
|
36
|
+
# Active only
|
|
37
|
+
webpeek example.com -A
|
|
38
|
+
|
|
39
|
+
# Dynamic mode (for JavaScript sites)
|
|
40
|
+
webpeek example.com -H -y
|
|
41
|
+
|
|
42
|
+
# Specific modules
|
|
43
|
+
webpeek example.com -T -l -e -p
|
|
44
|
+
|
|
45
|
+
# Save to file
|
|
46
|
+
webpeek example.com -H -oN result.txt
|
|
47
|
+
|
|
48
|
+
# Without colors
|
|
49
|
+
webpeek example.com -C
|
|
50
|
+
|
|
51
|
+
# Help
|
|
52
|
+
webpeek --help
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Options
|
|
56
|
+
|
|
57
|
+
| Short | Flag | Description |
|
|
58
|
+
|-------|------|-------------|
|
|
59
|
+
| `-H` | `--hybrid` | Run both active and passive modules |
|
|
60
|
+
| `-A` | `--active` | Run all active modules |
|
|
61
|
+
| `-P` | `--passive` | Run all passive modules |
|
|
62
|
+
| `-y` | `--dynamic` | Use headless browser (Playwright) |
|
|
63
|
+
| `-oN` | `--output` | Save output to file |
|
|
64
|
+
| `-C` | `--no-color` | Disable colors |
|
|
65
|
+
| `-v` | `--verbose` | Verbose output |
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Passive Modules
|
|
70
|
+
|
|
71
|
+
Gather information from public sources without connecting directly to the target.
|
|
72
|
+
|
|
73
|
+
| Short | Flag | Description |
|
|
74
|
+
|-------|------|-------------|
|
|
75
|
+
| `-w` | `--whois` | Domain registration info |
|
|
76
|
+
| `-d` | `--dns` | DNS A records |
|
|
77
|
+
| `-m` | `--mx` | MX records |
|
|
78
|
+
| `-t` | `--txt` | TXT records (SPF, DKIM) |
|
|
79
|
+
| `-S` | `--subdomains` | Find subdomains |
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Active Modules
|
|
84
|
+
|
|
85
|
+
Gather information by connecting directly to the target.
|
|
86
|
+
|
|
87
|
+
| Short | Flag | Description |
|
|
88
|
+
|-------|------|-------------|
|
|
89
|
+
| `-h` | `--headers` | HTTP headers |
|
|
90
|
+
| `-c` | `--security` | Security headers |
|
|
91
|
+
| `-T` | `--tech` | Detect technologies |
|
|
92
|
+
| `-W` | `--wplugins` | WordPress plugins |
|
|
93
|
+
| `-s` | `--ssl` | SSL certificate info |
|
|
94
|
+
| `-g` | `--geo` | Geolocation |
|
|
95
|
+
| `-O` | `--os` | OS detection |
|
|
96
|
+
| `-i` | `--title` | Page title |
|
|
97
|
+
| `-D` | `--description` | Meta description |
|
|
98
|
+
| `-e` | `--emails` | Extract emails |
|
|
99
|
+
| `-p` | `--phones` | Extract phone numbers |
|
|
100
|
+
| `-M` | `--sitemap` | Sitemap URLs |
|
|
101
|
+
| `-r` | `--robots` | Robots.txt |
|
|
102
|
+
| `-l` | `--social` | Social networks |
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Dynamic Mode
|
|
107
|
+
|
|
108
|
+
Use `-y` for JavaScript-rendered sites (React, Vue, Angular, etc.):
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
webpeek example.com -T -y
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
First time using dynamic mode will download Chromium (~150MB).
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Example Output
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
╔════════════════════════════════════════════════════════╗
|
|
122
|
+
║ 🌐 WEBPEEK v1.0.0 - example.com ║
|
|
123
|
+
╚════════════════════════════════════════════════════════╝
|
|
124
|
+
|
|
125
|
+
📡 PASSIVE MODE
|
|
126
|
+
─────────────────────
|
|
127
|
+
◉ WHOIS:
|
|
128
|
+
└─ Registrar: NameCheap, Inc.
|
|
129
|
+
└─ Created: 2025-12-14
|
|
130
|
+
└─ Expires: 2026-12-14
|
|
131
|
+
|
|
132
|
+
◉ DNS:
|
|
133
|
+
└─ 93.184.216.34
|
|
134
|
+
|
|
135
|
+
⚡ ACTIVE MODE
|
|
136
|
+
─────────────────────
|
|
137
|
+
◉ IP:
|
|
138
|
+
└─ 93.184.216.34
|
|
139
|
+
|
|
140
|
+
◉ Geo:
|
|
141
|
+
└─ US, California (Cloudflare, Inc.)
|
|
142
|
+
|
|
143
|
+
◉ Technologies:
|
|
144
|
+
└─ Cloudflare
|
|
145
|
+
└─ Nginx
|
|
146
|
+
|
|
147
|
+
◉ SSL:
|
|
148
|
+
└─ example.com (expires in 90 days)
|
|
149
|
+
|
|
150
|
+
╔════════════════════════════════════════════════════════╗
|
|
151
|
+
║ Scan complete! ║
|
|
152
|
+
╚════════════════════════════════════════════════════════╝
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Uninstall
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
pip uninstall webpeek
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## License
|
|
164
|
+
|
|
165
|
+
MIT
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "webpeek"
|
|
7
|
+
version = "1.2.1"
|
|
8
|
+
description = "OSINT CLI tool for web reconnaissance"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
authors = [
|
|
12
|
+
{name = "JorgeRosbel", email = "jorge@rosbel.dev"}
|
|
13
|
+
]
|
|
14
|
+
requires-python = ">=3.8"
|
|
15
|
+
dependencies = [
|
|
16
|
+
"click>=8.0",
|
|
17
|
+
"requests>=2.28",
|
|
18
|
+
"dnspython>=2.1",
|
|
19
|
+
"whois>=0.9",
|
|
20
|
+
"beautifulsoup4>=4.9",
|
|
21
|
+
"lxml>=4.6",
|
|
22
|
+
"colorama>=0.4",
|
|
23
|
+
"tldextract>=3.1",
|
|
24
|
+
"pwntools>=4.0",
|
|
25
|
+
"playwright>=1.40",
|
|
26
|
+
"pyee>=10.0",
|
|
27
|
+
"greenlet>=3.0",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[project.urls]
|
|
31
|
+
Homepage = "https://github.com/JorgeRosbel/webpeek"
|
|
32
|
+
|
|
33
|
+
[project.scripts]
|
|
34
|
+
webpeek = "webpeek.cli:cli"
|
|
35
|
+
|
|
36
|
+
[project.optional-dependencies]
|
|
37
|
+
dev = ["twine", "build"]
|
|
38
|
+
|
|
39
|
+
[tool.setuptools.packages.find]
|
|
40
|
+
where = ["."]
|
webpeek-1.2.1/setup.cfg
ADDED
webpeek-1.2.1/setup.py
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
|
|
3
|
+
setup(
|
|
4
|
+
name='webpeek',
|
|
5
|
+
version='1.2.0',
|
|
6
|
+
description='OSINT CLI tool for web reconnaissance',
|
|
7
|
+
author='JorgeRosbel',
|
|
8
|
+
author_email='jorge@rosbel.dev',
|
|
9
|
+
url='https://github.com/JorgeRosbel/webpeek',
|
|
10
|
+
packages=find_packages(),
|
|
11
|
+
install_requires=[
|
|
12
|
+
'click>=8.0',
|
|
13
|
+
'requests>=2.28',
|
|
14
|
+
'dnspython>=2.1',
|
|
15
|
+
'Whois>=0.9',
|
|
16
|
+
'beautifulsoup4>=4.9',
|
|
17
|
+
'lxml>=4.6',
|
|
18
|
+
'colorama>=0.4',
|
|
19
|
+
'tldextract>=3.1',
|
|
20
|
+
'pwntools>=4.0',
|
|
21
|
+
'playwright>=1.40',
|
|
22
|
+
'pyee>=10.0',
|
|
23
|
+
'greenlet>=3.0',
|
|
24
|
+
],
|
|
25
|
+
entry_points={
|
|
26
|
+
'console_scripts': [
|
|
27
|
+
'webpeek=webpeek.cli:cli',
|
|
28
|
+
],
|
|
29
|
+
},
|
|
30
|
+
python_requires='>=3.8',
|
|
31
|
+
classifiers=[
|
|
32
|
+
'Development Status :: 4 - Beta',
|
|
33
|
+
'Intended Audience :: Developers',
|
|
34
|
+
'License :: OSI Approved :: MIT License',
|
|
35
|
+
'Programming Language :: Python :: 3',
|
|
36
|
+
'Programming Language :: Python :: 3.8',
|
|
37
|
+
'Programming Language :: Python :: 3.9',
|
|
38
|
+
'Programming Language :: Python :: 3.10',
|
|
39
|
+
'Programming Language :: Python :: 3.11',
|
|
40
|
+
'Programming Language :: Python :: 3.12',
|
|
41
|
+
],
|
|
42
|
+
)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.0.0"
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import click
|
|
2
|
+
import tldextract
|
|
3
|
+
import socket
|
|
4
|
+
import re
|
|
5
|
+
from pwn import log
|
|
6
|
+
from webpeek.core.scanner import Scanner
|
|
7
|
+
from webpeek.core.output import print_results, save_to_file
|
|
8
|
+
from webpeek.utils.colors import Colors, RESET
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def is_valid_domain(domain):
|
|
12
|
+
pattern = r'^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$'
|
|
13
|
+
return bool(re.match(pattern, domain))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def validate_target(target):
|
|
17
|
+
ext = tldextract.extract(target)
|
|
18
|
+
if not ext.domain or not ext.suffix:
|
|
19
|
+
return None
|
|
20
|
+
|
|
21
|
+
domain = f"{ext.domain}.{ext.suffix}"
|
|
22
|
+
|
|
23
|
+
if not is_valid_domain(domain):
|
|
24
|
+
return None
|
|
25
|
+
|
|
26
|
+
try:
|
|
27
|
+
socket.gethostbyname(domain)
|
|
28
|
+
return domain
|
|
29
|
+
except socket.gaierror:
|
|
30
|
+
return None
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
ALL_ACTIVE_MODULES = ['headers', 'tech', 'ssl', 'geo', 'title', 'description', 'security', 'wplugins', 'sitemap', 'robots', 'os', 'emails', 'phones']
|
|
34
|
+
ALL_PASSIVE_MODULES = ['whois', 'dns', 'mx', 'txt', 'subdomains']
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@click.command()
|
|
38
|
+
@click.argument('target')
|
|
39
|
+
@click.option('-H', '--hybrid', 'hybrid_mode', is_flag=True, help='Run both active and passive modules')
|
|
40
|
+
@click.option('-A', '--active', is_flag=True, help='Run all active modules')
|
|
41
|
+
@click.option('-P', '--passive', is_flag=True, help='Run all passive modules')
|
|
42
|
+
@click.option('-w', '--whois', is_flag=True, help='WHOIS lookup')
|
|
43
|
+
@click.option('-d', '--dns', is_flag=True, help='DNS lookup')
|
|
44
|
+
@click.option('-m', '--mx', is_flag=True, help='MX records')
|
|
45
|
+
@click.option('-t', '--txt', is_flag=True, help='TXT records (SPF, DKIM)')
|
|
46
|
+
@click.option('-h', '--headers', is_flag=True, help='HTTP headers')
|
|
47
|
+
@click.option('-T', '--tech', is_flag=True, help='Detect technologies')
|
|
48
|
+
@click.option('-s', '--ssl', is_flag=True, help='SSL certificate info')
|
|
49
|
+
@click.option('-g', '--geo', is_flag=True, help='Geolocation')
|
|
50
|
+
@click.option('-O', '--os', is_flag=True, help='OS detection via TTL')
|
|
51
|
+
@click.option('-i', '--title', is_flag=True, help='Page title')
|
|
52
|
+
@click.option('-D', '--description', 'desc', is_flag=True, help='Meta description')
|
|
53
|
+
@click.option('-e', '--emails', is_flag=True, help='Extract emails')
|
|
54
|
+
@click.option('-p', '--phones', is_flag=True, help='Extract phone numbers')
|
|
55
|
+
@click.option('-S', '--subdomains', is_flag=True, help='Find subdomains')
|
|
56
|
+
@click.option('-c', '--security', is_flag=True, help='Security headers audit')
|
|
57
|
+
@click.option('-W', '--wplugins', is_flag=True, help='WordPress plugins')
|
|
58
|
+
@click.option('-M', '--sitemap', is_flag=True, help='Extract URLs from sitemap')
|
|
59
|
+
@click.option('-r', '--robots', is_flag=True, help='Fetch robots.txt')
|
|
60
|
+
@click.option('-oN', '--output', type=click.Path(), help='Save output to file')
|
|
61
|
+
@click.option('-C', '--no-color', is_flag=True, help='Disable colors')
|
|
62
|
+
@click.option('-v', '--verbose', is_flag=True, help='Verbose output')
|
|
63
|
+
def cli(target, hybrid_mode, active, passive, whois, dns, mx, txt, headers, tech, ssl, geo, os, title, desc, emails, phones, subdomains, security, wplugins, sitemap, robots, output, no_color, verbose):
|
|
64
|
+
use_color = not no_color
|
|
65
|
+
|
|
66
|
+
domain = validate_target(target)
|
|
67
|
+
if not domain:
|
|
68
|
+
print(f"{Colors.error('[ERROR] Invalid domain: ' + target)}")
|
|
69
|
+
return
|
|
70
|
+
|
|
71
|
+
scanner = Scanner(domain, verbose, use_color)
|
|
72
|
+
|
|
73
|
+
active_modules = []
|
|
74
|
+
passive_modules = []
|
|
75
|
+
|
|
76
|
+
specific_flags = [whois, dns, mx, txt, subdomains, headers, tech, ssl, geo, os, title, desc, emails, phones, security, wplugins, sitemap, robots]
|
|
77
|
+
is_custom = any(specific_flags) and not hybrid_mode and not active and not passive
|
|
78
|
+
|
|
79
|
+
if hybrid_mode:
|
|
80
|
+
active_modules = ALL_ACTIVE_MODULES.copy()
|
|
81
|
+
passive_modules = ALL_PASSIVE_MODULES.copy()
|
|
82
|
+
elif active:
|
|
83
|
+
active_modules = ALL_ACTIVE_MODULES.copy()
|
|
84
|
+
elif passive:
|
|
85
|
+
passive_modules = ALL_PASSIVE_MODULES.copy()
|
|
86
|
+
elif any(specific_flags):
|
|
87
|
+
active_modules = []
|
|
88
|
+
passive_modules = []
|
|
89
|
+
else:
|
|
90
|
+
active_modules = ALL_ACTIVE_MODULES.copy()
|
|
91
|
+
passive_modules = ALL_PASSIVE_MODULES.copy()
|
|
92
|
+
|
|
93
|
+
if whois: passive_modules.append('whois')
|
|
94
|
+
if dns: passive_modules.append('dns')
|
|
95
|
+
if mx: passive_modules.append('mx')
|
|
96
|
+
if txt: passive_modules.append('txt')
|
|
97
|
+
if subdomains: passive_modules.append('subdomains')
|
|
98
|
+
if emails: active_modules.append('emails')
|
|
99
|
+
if phones: active_modules.append('phones')
|
|
100
|
+
if headers: active_modules.append('headers')
|
|
101
|
+
if tech: active_modules.append('tech')
|
|
102
|
+
if ssl: active_modules.append('ssl')
|
|
103
|
+
if geo: active_modules.append('geo')
|
|
104
|
+
if os: active_modules.append('os')
|
|
105
|
+
if title: active_modules.append('title')
|
|
106
|
+
if desc: active_modules.append('description')
|
|
107
|
+
if security: active_modules.append('security')
|
|
108
|
+
if wplugins: active_modules.append('wplugins')
|
|
109
|
+
if sitemap: active_modules.append('sitemap')
|
|
110
|
+
if robots: active_modules.append('robots')
|
|
111
|
+
|
|
112
|
+
active_modules = list(set(active_modules))
|
|
113
|
+
passive_modules = list(set(passive_modules))
|
|
114
|
+
|
|
115
|
+
results = {}
|
|
116
|
+
|
|
117
|
+
if passive_modules:
|
|
118
|
+
results.update(scanner.scan_passive(passive_modules))
|
|
119
|
+
|
|
120
|
+
if active_modules:
|
|
121
|
+
results.update(scanner.scan_active(active_modules))
|
|
122
|
+
|
|
123
|
+
print_results(domain, results, use_color, is_custom)
|
|
124
|
+
|
|
125
|
+
if output:
|
|
126
|
+
from webpeek.utils.colors import format_plain
|
|
127
|
+
plain_output = format_plain(domain, results)
|
|
128
|
+
|
|
129
|
+
if save_to_file(output, plain_output):
|
|
130
|
+
if use_color:
|
|
131
|
+
click.echo(f"{Colors.pass_('Results saved to ' + output)}")
|
|
132
|
+
else:
|
|
133
|
+
click.echo(f"Results saved to {output}")
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
if __name__ == '__main__':
|
|
137
|
+
cli()
|
|
File without changes
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from webpeek.utils.colors import format_output, Colors
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def format_list_value(value):
|
|
5
|
+
if isinstance(value, dict):
|
|
6
|
+
return value
|
|
7
|
+
|
|
8
|
+
if not isinstance(value, list):
|
|
9
|
+
return str(value)
|
|
10
|
+
|
|
11
|
+
if not value:
|
|
12
|
+
return ""
|
|
13
|
+
|
|
14
|
+
if isinstance(value[0], dict):
|
|
15
|
+
if 'name' in value[0] and 'version' in value[0]:
|
|
16
|
+
return "\n".join(f" • {v['name']} ({v['version']})" for v in value)
|
|
17
|
+
return "\n".join(f" • {v}" for v in value)
|
|
18
|
+
|
|
19
|
+
return "\n".join(f" • {v}" for v in value)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def print_results(target, results, use_color=True, is_custom=False):
|
|
23
|
+
clean_results = {}
|
|
24
|
+
for key, value in results.items():
|
|
25
|
+
if key == 'IP' and is_custom:
|
|
26
|
+
continue
|
|
27
|
+
if value and (isinstance(value, dict) or str(value).strip()):
|
|
28
|
+
if isinstance(value, dict):
|
|
29
|
+
clean_results[key] = value
|
|
30
|
+
else:
|
|
31
|
+
formatted = format_list_value(value)
|
|
32
|
+
clean_results[key] = formatted[:200]
|
|
33
|
+
|
|
34
|
+
if not clean_results:
|
|
35
|
+
if use_color:
|
|
36
|
+
print(f"{Colors.warning('No results found')}")
|
|
37
|
+
else:
|
|
38
|
+
print("No results found")
|
|
39
|
+
return
|
|
40
|
+
|
|
41
|
+
output = format_output(target, clean_results, use_color, is_custom)
|
|
42
|
+
print(output)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def save_to_file(filename, content):
|
|
46
|
+
try:
|
|
47
|
+
with open(filename, 'w') as f:
|
|
48
|
+
f.write(content)
|
|
49
|
+
return True
|
|
50
|
+
except Exception as e:
|
|
51
|
+
return False
|