From a515023be01021975f7e54fc1a7d07b637c608df Mon Sep 17 00:00:00 2001 From: William <53403209+LeakCheck@users.noreply.github.com> Date: Fri, 4 Oct 2024 18:58:23 +0000 Subject: [PATCH 1/5] Add LeakCheck service --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 16e70b2..6a0edc9 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,9 @@ | [scylla.so](https://scylla.so/) - Service (free) | Cleartext passwords, hashs and salts, usernames, IPs, domain | :construction: | | [Dehashed.com](https://dehashed.com/) - Service | Cleartext passwords, hashs and salts, usernames, IPs, domain | :white_check_mark: :key: | | [IntelX.io](https://intelx.io/signup) - Service (free trial) | Cleartext passwords, hashs and salts, usernames, IPs, domain, Bitcoin Wallets, IBAN | :white_check_mark: :key: | -| :new: [Breachdirectory.org](https://breachdirectory.org) - Service (free) | Cleartext passwords, hashs and salts, usernames, domain | :construction: :key: | +| [Breachdirectory.org](https://breachdirectory.org) - Service (free) | Cleartext passwords, hashs and salts, usernames, domain | :construction: :key: | +| :new: [LeakCheck.io](https://leakcheck.io/?from=h8mail) - Public | List of data breaches by e-mail or username and compromised fields | :white_check_mark: | +| :new: [LeakCheck.io](https://leakcheck.io/?from=h8mail) - Service | Cleartext passwords, e-mails, usernames, ZIPs, IPs, full names, phones, stealer logs | :white_check_mark: :key: | *:key: - API key required* From 0df97c9c9524db570ff14593926832cdf1d623e2 Mon Sep 17 00:00:00 2001 From: William <53403209+LeakCheck@users.noreply.github.com> Date: Fri, 4 Oct 2024 20:20:59 +0000 Subject: [PATCH 2/5] Add LeakCheck service --- h8mail/utils/classes.py | 80 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/h8mail/utils/classes.py b/h8mail/utils/classes.py index 53799af..c8807dd 100644 --- a/h8mail/utils/classes.py +++ b/h8mail/utils/classes.py @@ -9,6 +9,7 @@ import platform from .version import __version__ +LC_SUPPORTED = ['email', 'domain', 'keyword', 'username', 'phone', 'phash', 'origin', 'password'] class local_breach_target: """ @@ -750,6 +751,85 @@ def get_weleakinfo_pub(self, api_key): ) print(ex) + def get_leakcheck_pub(self): + try: + c.info_news("[" + self.target + "]>[leakcheck public]") + url = "https://leakcheck.io/api/public?check={query}".format( + query=self.target + ) + req = self.make_request(url, timeout=30) + response = req.json() + if req.status_code != 200: + c.bad_news(f"Got LC API response code {req.status_code} (public)") + return + else: + c.good_news( + "Found {num} entries for {target} using LeakCheck (public)".format( + num=response["found"], target=self.target + ) + ) + if response["success"] is False: + c.bad_news(response["error"]) + return + self.data.append(("LC_PUB_TOTAL", response["found"])) + if response["found"] == 0: + return + for src in response["sources"]: + self.data.append(("LC_PUB_SOURCE", src['name'] + " (" + src['date'] + ")")) + self.pwned += 1 + except Exception as ex: + c.bad_news( + f"LeakCheck error with {self.target} (public)" + ) + print(ex) + + def get_leakcheck_priv(self, api_key, user_query): + if user_query == 'hash': user_query = 'phash' + + if user_query not in LC_SUPPORTED: + c.bad_news( + f"LeakCheck does not support {user_query} search (yet)" + ) + return + try: + c.info_news("[" + self.target + "]>[leakcheck pro]") + url = "https://leakcheck.io/api/v2/query/{query}?type={user_query}".format( + query=self.target, + user_query=user_query + ) + self.headers.update({"X-API-KEY": api_key}) + req = self.make_request(url, timeout=30) + response = req.json() + if req.status_code != 200: + c.bad_news(f"Got LC API response code {req.status_code} - {response.get('error')} (Pro)") + return + else: + c.good_news( + "Found {num} entries for {target} using LeakCheck (Pro)".format( + num=response["found"], target=self.target + ) + ) + self.data.append(("LC_PRIV_TOTAL", response["found"])) + if response["found"] == 0: + return + for result in response["result"]: + breach_name = result['source']['name'] or "N/A" + breach_date = result['source']['breach_date'] or "Unknown" + self.data.append(("LC_PRIV_SOURCE", breach_name + " (" + breach_date + ")")) + self.pwned += 1 + result['fields'].remove(user_query) + for field in result['fields']: + field_name = field + if field == 'username': field_name = 'USER' + if field == 'password': field_name = 'PASS' + + self.data.append(("LC_PRIV_" + field_name.upper(), result[field])) + except Exception as ex: + c.bad_news( + f"LeakCheck error with {self.target} (private)" + ) + print(ex) + def get_dehashed(self, api_email, api_key, user_query): try: if user_query == "hash": From a2a16058dbdeaec95c9bc56f7196411be8279799 Mon Sep 17 00:00:00 2001 From: William <53403209+LeakCheck@users.noreply.github.com> Date: Fri, 4 Oct 2024 20:21:23 +0000 Subject: [PATCH 3/5] Add LeakCheck service --- h8mail/utils/gen_config.py | 1 + 1 file changed, 1 insertion(+) diff --git a/h8mail/utils/gen_config.py b/h8mail/utils/gen_config.py index ba59343..8221c4c 100644 --- a/h8mail/utils/gen_config.py +++ b/h8mail/utils/gen_config.py @@ -24,6 +24,7 @@ def gen_config_file(): ;intelx_maxfile = 10 ;breachdirectory_user = ;breachdirectory_pass = +;leakcheck_apikey = """ dest_config.write(config) c.good_news( From a173375278b64591e73a115b51c509262564f64e Mon Sep 17 00:00:00 2001 From: William <53403209+LeakCheck@users.noreply.github.com> Date: Fri, 4 Oct 2024 20:21:40 +0000 Subject: [PATCH 4/5] Add LeakCheck service --- h8mail/utils/print_results.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/h8mail/utils/print_results.py b/h8mail/utils/print_results.py index 31b43bc..e5e7743 100644 --- a/h8mail/utils/print_results.py +++ b/h8mail/utils/print_results.py @@ -49,6 +49,8 @@ def print_results(results, hide=False): c.print_result(t.target, t.data[i][1], t.data[i][0]) if "WLI" in t.data[i][0]: c.print_result(t.target, t.data[i][1], t.data[i][0]) + if "LC" in t.data[i][0]: + c.print_result(t.target, t.data[i][1], t.data[i][0]) if "SCYLLA" in t.data[i][0]: c.print_result(t.target, t.data[i][1], t.data[i][0]) if "DHASHD" in t.data[i][0]: From 9b0c723872edb389d3fb744a8bdb54d787e8bf14 Mon Sep 17 00:00:00 2001 From: William <53403209+LeakCheck@users.noreply.github.com> Date: Fri, 4 Oct 2024 20:22:04 +0000 Subject: [PATCH 5/5] Add LeakCheck service --- h8mail/utils/run.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/h8mail/utils/run.py b/h8mail/utils/run.py index 4d9bd35..59b0ceb 100644 --- a/h8mail/utils/run.py +++ b/h8mail/utils/run.py @@ -8,7 +8,7 @@ import sys from .breachcompilation import breachcomp_check -from .classes import target +from .classes import target, LC_SUPPORTED from .colors import colors as c from .helpers import ( fetch_emails, @@ -64,6 +64,7 @@ def target_factory(targets, user_args): current_target = target(t) if not skip_default_queries: if not user_args.skip_defaults: + current_target.get_leakcheck_pub() current_target.get_hunterio_public() ## emailrep seems to insta-block h8mail user agent without a key # if api_keys is None or "emailrep" not in api_keys: @@ -83,6 +84,8 @@ def target_factory(targets, user_args): ) if "hibp" in api_keys and query == "email": current_target.get_hibp3(api_keys["hibp"]) + if "leakcheck_apikey" in api_keys and query in LC_SUPPORTED: + current_target.get_leakcheck_priv(api_keys["leakcheck_apikey"], query) if "emailrep" in api_keys and query == "email": current_target.get_emailrepio(api_keys["emailrep"]) if "hunterio" in api_keys and query == "email": @@ -284,7 +287,7 @@ def parse_args(args): "-sk", "--skip-defaults", dest="skip_defaults", - help="Skips Scylla and HunterIO check. Ideal for local scans", + help="Skips Scylla, LeakCheck and HunterIO check. Ideal for local scans", action="store_true", default=False, )