|
| 1 | +import httpx |
| 2 | +import json |
| 3 | +import urllib.parse |
| 4 | +from user_scanner.core.result import Result |
| 5 | + |
| 6 | + |
| 7 | +async def _check(email: str) -> Result: |
| 8 | + show_url = "https://hackthebox.com" |
| 9 | + register_url = "https://account.hackthebox.com/register" |
| 10 | + api_url = "https://account.hackthebox.com/api/v1/user/email/verify" |
| 11 | + |
| 12 | + headers = { |
| 13 | + 'User-Agent': "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Mobile Safari/537.36", |
| 14 | + 'Accept': "application/json", |
| 15 | + 'Accept-Encoding': "identity", |
| 16 | + 'Content-Type': "application/json", |
| 17 | + 'sec-ch-ua-platform': '"Android"', |
| 18 | + 'sec-ch-ua': '"Not:A-Brand";v="99\", \"Google Chrome\";v=\"145\", \"Chromium\";v=\"145"', |
| 19 | + 'sec-ch-ua-mobile': "?1", |
| 20 | + 'x-requested-with': "XMLHttpRequest", |
| 21 | + 'origin': "https://account.hackthebox.com", |
| 22 | + 'sec-fetch-site': "same-origin", |
| 23 | + 'sec-fetch-mode': "cors", |
| 24 | + 'sec-fetch-dest': "empty", |
| 25 | + 'referer': "https://account.hackthebox.com/register", |
| 26 | + 'accept-language': "en-US,en;q=0.9", |
| 27 | + 'priority': "u=1, i" |
| 28 | + } |
| 29 | + |
| 30 | + try: |
| 31 | + async with httpx.AsyncClient(timeout=15.0, follow_redirects=True) as client: |
| 32 | + r_init = await client.get(register_url, headers={'User-Agent': headers['User-Agent']}) |
| 33 | + |
| 34 | + if r_init.status_code == 403: |
| 35 | + return Result.error("Caught by WAF or IP Block (403) during Handshake") |
| 36 | + |
| 37 | + xsrf_token_encoded = client.cookies.get("XSRF-TOKEN") |
| 38 | + if not xsrf_token_encoded: |
| 39 | + return Result.error("Failed to extract XSRF-TOKEN from HackTheBox") |
| 40 | + |
| 41 | + xsrf_token = urllib.parse.unquote(xsrf_token_encoded) |
| 42 | + headers['x-xsrf-token'] = xsrf_token |
| 43 | + |
| 44 | + payload = {"email": email} |
| 45 | + response = await client.post(api_url, content=json.dumps(payload), headers=headers) |
| 46 | + |
| 47 | + status = response.status_code |
| 48 | + |
| 49 | + if status == 403: |
| 50 | + return Result.error("Caught by WAF or IP Block (403) during Validation") |
| 51 | + |
| 52 | + if status == 422: |
| 53 | + resp_data = response.json() |
| 54 | + if "cannot use this email address" in str(resp_data): |
| 55 | + return Result.taken(url=show_url) |
| 56 | + return Result.error(f"Validation error: {resp_data.get('message')}") |
| 57 | + |
| 58 | + if status in [200, 204]: |
| 59 | + return Result.available(url=show_url) |
| 60 | + |
| 61 | + if status == 429: |
| 62 | + return Result.error("Rate limited by HackTheBox") |
| 63 | + |
| 64 | + return Result.error(f"Unexpected status code: {status}") |
| 65 | + |
| 66 | + except httpx.ConnectTimeout: |
| 67 | + return Result.error("Connection timed out! maybe region blocks") |
| 68 | + except Exception as e: |
| 69 | + return Result.error(e) |
| 70 | + |
| 71 | + |
| 72 | +async def validate_hackthebox(email: str) -> Result: |
| 73 | + return await _check(email) |
0 commit comments