Repository navigation
Expand file tree
/
Copy pathcheck_localhost.py
More file actions
129 lines (116 loc) · 3.97 KB
/
Copy pathcheck_localhost.py
File metadata and controls
129 lines (116 loc) · 3.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#!/usr/bin/env python3
"""
Attemps to check if the target localhost can be scanned with Host Header
"""
from utils.style import Colors
from utils.utils import configure_logger, requests
logger = configure_logger(__name__)
def check_localhost(
url: str, s: requests.Session, domain: str, authent: tuple[str, str] | None
) -> None:
list_test = [
# Original list
"127.0.0.1",
"localhost",
"192.168.0.1",
"127.0.1",
"127.1",
"::1",
"127.0.0.2",
"127.0.0.1",
"127.0.0.1:22",
"0.0.0.0", # nosec B104 - Test payload for localhost bypass testing
"0.0.0.0:443",
"[::]:80",
"127.0.0.1.nip.io",
"127.127.127.127",
# Extended checks
"[::1]",
"[::1]:80",
"[::1]:443",
"192.168.1.1",
"10.0.0.1",
"172.16.0.1",
"127.0.0.1:80",
"127.0.0.1:443",
"127.0.0.1:8080",
"127.0.0.1:3306",
"127.0.0.1:5432",
"127.0.0.1:6379",
"127.0.0.1:27017",
"localhost:22",
"localhost:3389",
"localhost:8080",
"127.0.0.1.xip.io",
"localtest.me",
"lvh.me",
"127.0.0.1.traefik.me",
f"127.0.0.1.{domain}",
"0x7f000001",
"017700000001",
"2130706433",
"127.000.000.1",
"127.0.0.01",
"127.0.0.001",
"customer1.app.localhost",
"admin.127.0.0.1.nip.io",
"127.0.0.1.",
"127.0.0.1/",
"127.0.0.1#",
"127.0.0.1?",
"metadata.google.internal",
"169.254.169.254",
"consul.service.consul",
"vault.service.consul",
"127.0.0.1:80@evil.com",
"127.0.0.1#evil.com",
"127.0.0.1 evil.com",
"http://127.0.0.1/",
"https://admin.localhost/",
"127.0.0.1%00.evil.com",
"127.0.0.1%0A",
"localhost%2eevil%2ecom",
]
print(f"{Colors.CYAN} ├ Host analysis{Colors.RESET}")
results_tracker: dict[tuple, list] = {}
def add_result(key: tuple, host: str) -> None:
if key not in results_tracker:
results_tracker[key] = []
results_tracker[key].append(host)
for lt in list_test:
headers = {"Host": lt}
try:
req = s.get(
url, headers=headers, verify=False, allow_redirects=False, timeout=10
)
if req.status_code in [301, 302, 303, 307, 308]:
location = req.headers.get("location", "No location")
result_key = (req.status_code, "redirect", location)
else:
result_key = (req.status_code, "normal", str(len(req.content)))
add_result(result_key, lt)
print(f" ├─ {Colors.BLUE}{lt}:{req.status_code}{Colors.RESET}\r", end="")
print("\033[K", end="")
except Exception:
logger.exception(f"Request error with Host header: {lt}")
# Display deduplicated results
displayed_groups: set[tuple] = set()
for result_key, hosts_list in results_tracker.items():
# Unpack result_key and determine format based on middle element
status_code, result_type, value = result_key
if result_type == "redirect":
result_info = f"{status_code:>3}{'→':^3}{value}"
else: # result_type == "normal"
result_info = f"{status_code:>3} [{value} bytes]"
# Handle grouped results (3+ similar hosts)
if len(hosts_list) >= 3 and result_key not in displayed_groups:
first_host = hosts_list[0]
similar_count = len(hosts_list) - 1
print(
f" ├── Host: {first_host:<25}{'→':^3} {result_info} ({Colors.CYAN}+{similar_count} similar{Colors.RESET})"
)
displayed_groups.add(result_key)
# Handle individual results (< 3 hosts)
elif len(hosts_list) < 3:
for host in hosts_list:
print(f" ├── Host: {host:<25}{'→':^3} {result_info}")