diff --git a/pwnedornot.py b/pwnedornot.py index 9685f7a..f157d08 100755 --- a/pwnedornot.py +++ b/pwnedornot.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import os import re @@ -8,6 +8,7 @@ import time import argparse import requests import cfscrape +import threading import subprocess R = '\033[31m' # red @@ -15,11 +16,15 @@ G = '\033[32m' # green C = '\033[36m' # cyan W = '\033[0m' # white -if sys.version_info[0] >= 3: - raw_input = input - unicode = str +if sys.version_info[0] != 3: + print (R + '\n[-]' + C + ' Only Python 3 is Supported.\n') + exit() -version = '1.1.1' +version = '1.1.2' + +useragent = {'User-Agent' : 'pwnedornot'} +cookies = '' +start = '' def update(): print (G + '[+]' + C + ' Checking for updates...' + W + '\n') @@ -28,7 +33,7 @@ def update(): updated_version = updated_version.strip() if updated_version != version: print (G + '[!]' + C + ' A New Version is Available : ' + W + updated_version) - ans = raw_input(G + '[!]' + C + ' Update ? [y/n] : ' + W) + ans = input(G + '[!]' + C + ' Update ? [y/n] : ' + W) if ans == 'y': print ('\n' + G + '[+]' + C + ' Updating...' + '\n' + W) subprocess.check_output(['git', 'reset', '--hard', 'origin/master']) @@ -39,100 +44,168 @@ def update(): print (G + '[+]' + C + ' Script is up-to-date...' + '\n') -# commandline arguments -ap = argparse.ArgumentParser() -ap.add_argument('-e', '--email', required=False, -help='Email account you want to test') -ap.add_argument('-f', '--file', required=False, -help='Load a file with multiple email accounts') - -arg = ap.parse_args() - -status = False -fparse = False - -addr = arg.email -file = arg.file - -if arg.email: - status = True -if arg.file: - fparse = True -if not status: - pass def banner(): if sys.platform == 'win32': - os.system('cls') # Windows + os.system('cls') else: - os.system('clear') # UNIX + os.system('clear') - banner = r""" - ______ _ __ __ - ___ _ _____ ___ ___/ / __ \____/ |/ /__ / /_ - / _ \ |/|/ / _ \/ -_) _ / /_/ / __/ / _ \/ __/ - / .__/__,__/_//_/\__/\_,_/\____/_/ /_/|_/\___/\__/ + banner = r''' + ______ _ __ __ + ____ _ ______ ___ ____/ / __ \_____/ | / /___ / /_ + / __ \ | /| / / __ \/ _ \/ __ / / / / ___/ |/ / __ \/ __/ + / /_/ / |/ |/ / / / / __/ /_/ / /_/ / / / /| / /_/ / /_ + / .___/|__/|__/_/ /_/\___/\__,_/\____/_/ /_/ |_/\____/\__/ /_/ -""" + ''' print (G + banner + W) print (G + '[>]' + C + ' Created by : ' + W + 'thewhiteh4t') print (G + '[>]' + C + ' Version : ' + W + version + '\n') def main(): - global addr, file - - print (G + '[+]' + C + ' Bypassing Cloudflare Restriction...' + W + '\n') - useragent = {'User-Agent' : 'pwnedornot'} + global addr, cookies, start + print (G + '[+]' + C + ' Bypassing Cloudflare Restriction...' + W) cookies, user_agent = cfscrape.get_tokens('https://haveibeenpwned.com/api/v2/breachedaccount/test@example.com', user_agent='pwnedornot') - - # starts calculating script runtime start = time.time() - # quit function prints total script runtime and exits - def quit(): - print ('\n' + G + '[+]' + C + ' Completed in ' + W + str(time.time()-start) + C + ' seconds.' + W) + if list_domain is True: + domains_list() + elif check_domain: + domain_check() + elif addr == None and domain != None or file == None and domain != None: + print ('\n' + R + '[-]' + C + ' Error : Use -e or -f with Domain Filter') + exit() + elif addr == None and nodumps == True or file == None and nodumps == True: + print ('\n' + R + '[+]' + C + ' Error : Use -e or if with -n') + exit() + elif addr != None and domain != None: + filtered_check() + elif addr != None and domain == None: + check() + elif file != None and domain == None: + print ('\n' + G + '[+]' + C + ' Reading Emails Addresses from ' + W + '{}'.format(file)) + with open(file) as dict: + for line in dict: + line = line.strip() + addr = line + if addr != '': + check() + time.sleep(2) + elif file != None and domain != None: + print ('\n' + G + '[+]' + C + ' Reading Emails Addresses from ' + W + '{}'.format(file)) + print ('\n' + G + '[+]' + C + ' Domain : ' + W + domain) + with open(file) as dict: + for line in dict: + line = line.strip() + addr = line + if addr != '': + filtered_check() + time.sleep(2) + else: + print ('\n' + R + '[-]' + C + ' Error : Atleast 1 Argument is Required, Try : python3 pwnedornot.py -h' + W) exit() - def dump(): - dumplist = [] - # r2 is the query for pastebin accounts if we get a 404, account does not have any dumps - r2 = requests.get('https://haveibeenpwned.com/api/v2/pasteaccount/{}'.format(addr), headers= useragent, cookies= cookies) - check2 = r2.status_code +def check(): + print ('\n' + G + '[+]' + C + ' Checking Breach status for ' + W + '{}'.format(addr), end = '') + r1 = requests.get('https://haveibeenpwned.com/api/v2/breachedaccount/{}'.format(addr), headers= useragent, cookies= cookies, verify = True) + check1 = r1.status_code - if check2 != 200: - print ('\n' + R + '[-]' + C + ' No Dumps Found... :(' + W) - else: - print ('\n' + G + '[+]' + C + ' Dumps Available...!' + W) - print ('\n' + G + '[+]' + C + ' Getting Dumps...this may take a while...' + W) - json2 = r2.content.decode('utf-8', 'ignore') - simple2 = json.loads(json2) + if check1 == 404: + print (R + ' [ Not Breached ]' + W) + if nodumps is not True: + dump() - # checking if dump is accessible - for item in simple2: - if (item['Source']) == 'Pastebin': - link = item['Id'] + else: + print (G + ' [ pwned ]' + W) + json1 = r1.content.decode('utf8', 'ignore') + simple1 = json.loads(json1) + for item in simple1: + print ( '\n' + + G + '[+]' + C + ' Breach : ' + W + str(item['Title']) + '\n' + + G + '[+]' + C + ' Domain : ' + W + str(item['Domain']) + '\n' + + G + '[+]' + C + ' Date : ' + W + str(item['BreachDate']) + '\n' + + G + '[+]' + C + ' Fabricated : ' + W + str(item['IsFabricated']) + '\n' + + G + '[+]' + C + ' Verified : ' + W + str(item['IsVerified']) + '\n' + + G + '[+]' + C + ' Retired : ' + W + str(item['IsRetired']) + '\n' + + G + '[+]' + C + ' Spam : ' + W + str(item['IsSpamList'])) + if nodumps is not True: + dump() + +def filtered_check(): + print ('\n' + G + '[+]' + C + ' Checking Breach status for ' + W + '{}'.format(addr), end = '') + r1 = requests.get('https://haveibeenpwned.com/api/v2/breachedaccount/{}?domain={}'.format(addr, domain), headers= useragent, cookies= cookies, verify = True) + check1 = r1.status_code + + if check1 == 404: + print (R + ' [ Not Breached ]' + W) + if nodumps is not True: + dump() + + else: + print (G + ' [ pwned ]' + W) + json1 = r1.content.decode('utf8', 'ignore') + simple1 = json.loads(json1) + + for item in simple1: + print ( '\n' + + G + '[+]' + C + ' Breach : ' + W + str(item['Title']) + '\n' + + G + '[+]' + C + ' Domain : ' + W + str(item['Domain']) + '\n' + + G + '[+]' + C + ' Date : ' + W + str(item['BreachDate']) + '\n' + + G + '[+]' + C + ' Fabricated : ' + W + str(item['IsFabricated']) + '\n' + + G + '[+]' + C + ' Verified : ' + W + str(item['IsVerified']) + '\n' + + G + '[+]' + C + ' Retired : ' + W + str(item['IsRetired']) + '\n' + + G + '[+]' + C + ' Spam : ' + W + str(item['IsSpamList'])) + if nodumps is not True: + dump() + +def dump(): + dumplist = [] + print ('\n' + G + '[+]' + C + ' Looking for Dumps...' + W, end = '') + r2 = requests.get('https://haveibeenpwned.com/api/v2/pasteaccount/{}'.format(addr), headers= useragent, cookies= cookies) + check2 = r2.status_code + + if check2 != 200: + print (R + ' [ No Dumps Found ]' + W) + else: + print (G + ' [ Dumps Found ]' + W) + json2 = r2.content.decode('utf-8', 'ignore') + simple2 = json.loads(json2) + + def fetch(): + if (item['Source']) == 'Pastebin': + link = item['Id'] + try: url = 'https://www.pastebin.com/raw/{}'.format(link) page = requests.get(url, timeout = 5) sc = page.status_code if sc != 404: dumplist.append(url) + except requests.exceptions.ConnectionError: + pass + elif (item['Source']) == 'AdHocUrl': + url = item['Id'] + try: + page = requests.get(url, timeout = 5) + sc = page.status_code + if sc != 404: + dumplist.append(url) + except requests.exceptions.ConnectionError: + pass - elif (item['Source']) == 'AdHocUrl': - url = item['Id'] - try: - page = requests.get(url, timeout = 5) - sc = page.status_code - if sc != 404: - dumplist.append(url) - except requests.exceptions.ConnectionError: - pass + for item in simple2: + t1 = threading.Thread(target=fetch) + t1.daemon = True + t1.start() - print ('\n' + G + '[+]' + C + ' Got ' + W + str(len(dumplist)) + C + ' Dumps' + W) + t1.join() + print ('\n' + G + '[+]' + C + ' Found ' + W + str(len(dumplist)) + C + ' Dumps' + W) - if str(len(dumplist)) != '0': - print ('\n' + G + '[+]' + C + ' Passwords:' + W + '\n') - - for entry in dumplist: + if len(dumplist) != 0: + print ('\n' + G + '[+]' + C + ' Passwords:' + W + '\n') + for entry in dumplist: + time.sleep(1) + try: page = requests.get(entry) dict = page.content.decode('utf-8', 'ignore') passwd = re.search('{}:(\w+)'.format(addr), dict) @@ -143,82 +216,76 @@ def main(): passwd = re.search('(.*{}.*)'.format(addr), line) if passwd: print (G + '[+] ' + W + passwd.group(0)) + except requests.exceptions.ConnectionError: + pass - def check(): - print ('\n' + G + '[+]' + C + ' Looking for Breaches...' + W) - # sleep 2 seconds to avoid rate limit - time.sleep(2) - # r1 is the query for the account user enters - r1 = requests.get('https://haveibeenpwned.com/api/v2/breachedaccount/{}'.format(addr), headers= useragent, cookies= cookies, verify = True) - #check1 is the status code for the account if we get a 404, account is not breached - check1 = r1.status_code +def domains_list(): + print ('\n' + G + '[+]' + C + ' Fetching List of Breached Domains...' + W + '\n') + r = requests.get('https://haveibeenpwned.com/api/v2/breaches') + json_out = r.content.decode('utf8', 'ignore') + simple_out = json.loads(json_out) + for item in simple_out: + domain_name = item['Domain'] + if len(domain_name) != 0: + print (G + '[+] ' + W + str(domain_name)) + domains.append(domain_name) + print ('\n' + G + '[+]' + C + ' Total : ' + W + str(len(domains))) - if check1 == 404: - print ('\n' + R + '[-]' + C + ' No Breaches Found... :(' + W) - print ('\n' + G + '[+]' + C + ' Looking for Dumps...' + W) - dump() - - else: - print ( '\n' + G + '[!]' + C + ' Account pwned...Listing Breaches...' + W) - json1 = r1.content.decode('utf8', 'ignore') - simple1 = json.loads(json1) - - for item in simple1: +def domain_check(): + print ('\n' + G + '[+]' + C + ' Domain Name : ' + W + check_domain, end = '') + r = requests.get('https://haveibeenpwned.com/api/v2/breaches?domain={}'.format(check_domain)) + sc = r.status_code + if sc == 200: + json_out = r.content.decode('utf8', 'ignore') + simple_out = json.loads(json_out) + if len(simple_out) != 0: + print (G + ' [ pwned ]' + W) + for item in simple_out: print ( '\n' - + G + '[+]' + C + ' Breach : ' + W + unicode(item['Title']) + '\n' - + G + '[+]' + C + ' Domain : ' + W + unicode(item['Domain']) + '\n' - + G + '[+]' + C + ' Date : ' + W + unicode(item['BreachDate']) + '\n' - + G + '[+]' + C + ' Fabricated : ' + W + unicode(item['IsFabricated']) + '\n' - + G + '[+]' + C + ' Verified : ' + W + unicode(item['IsVerified']) + '\n' - + G + '[+]' + C + ' Retired : ' + W + unicode(item['IsRetired']) + '\n' - + G + '[+]' + C + ' Spam : ' + W + unicode(item['IsSpamList'])) - - dump() - - def filecheck(): - time.sleep(2) - r3 = requests.get('https://haveibeenpwned.com/api/v2/breachedaccount/{}'.format(addr), headers= useragent, cookies= cookies, verify = True) - check3 = r3.status_code - - if check3 == 404: - print ( '\n' + R + '[-]' + C + ' Account not pwned... :(' + W) + + G + '[+]' + C + ' Breach : ' + W + str(item['Title']) + '\n' + + G + '[+]' + C + ' Domain : ' + W + str(item['Domain']) + '\n' + + G + '[+]' + C + ' Date : ' + W + str(item['BreachDate']) + '\n' + + G + '[+]' + C + ' Pwn Count : ' + W + str(item['PwnCount']) + '\n' + + G + '[+]' + C + ' Fabricated : ' + W + str(item['IsFabricated']) + '\n' + + G + '[+]' + C + ' Verified : ' + W + str(item['IsVerified']) + '\n' + + G + '[+]' + C + ' Retired : ' + W + str(item['IsRetired']) + '\n' + + G + '[+]' + C + ' Spam : ' + W + str(item['IsSpamList']) + '\n' + + G + '[+]' + C + ' Data Types : ' + W + str(item['DataClasses'])) else: - print ( '\n' + G + '[!]' + C + ' Account pwned...Listing Breaches...' + W) - json1 = r3.content.decode('utf8', 'ignore') - simple1 = json.loads(json1) + print (R + ' [ Not Breached ]' + W) - for item in simple1: - print ( '\n' - + G + '[+]' + C + ' Breach : ' + W + unicode(item['Title']) + '\n' - + G + '[+]' + C + ' Domain : ' + W + unicode(item['Domain']) + '\n' - + G + '[+]' + C + ' Date : ' + W + unicode(item['BreachDate']) + '\n' - + G + '[+]' + C + ' Fabricated : ' + W + unicode(item['IsFabricated']) + '\n' - + G + '[+]' + C + ' Verified : ' + W + unicode(item['IsVerified']) + '\n' - + G + '[+]' + C + ' Retired : ' + W + unicode(item['IsRetired']) + '\n' - + G + '[+]' + C + ' Spam : ' + W + unicode(item['IsSpamList'])) +def quit(): + global start + print ('\n' + G + '[+]' + C + ' Completed in ' + W + str(time.time()-start) + C + ' seconds.' + W) + exit() - dump() - - if not status and not fparse: - addr = raw_input(G + '[+]' + C + ' Enter Email Address : ' + W) - check() - elif status == True: - print (G + '[+]' + C + ' Checking Breach status for ' + W + '{}'.format(addr)) - check() - elif fparse == True: - print (G + '[+]' + C + ' Reading Emails Accounts from ' + W + '{}'.format(file)) - with open(file) as dict: - for line in dict: - line = line.strip() - addr = line - if addr != '': - print ('\n' + G + '[+]' + C + ' Checking Breach status for ' + W + '{}'.format(addr)) - check() - quit() try: banner() + + ap = argparse.ArgumentParser() + ap.add_argument('-e', '--email', required=False, + help='Email Address You Want to Test') + ap.add_argument('-f', '--file', required=False, + help='Load a File with Multiple Email Addresses') + ap.add_argument('-d', '--domain', required=False, + help='Filter Results by Domain Name') + ap.add_argument('-n', '--nodumps', required=False, action='store_true', + help='Only Check Breach Info and Skip Password Dumps') + ap.add_argument('-l', '--list', required=False, action='store_true', + help='Get List of all pwned Domains') + ap.add_argument('-c', '--check', required=False, + help='Check if your Domain is pwned') + arg = ap.parse_args() + addr = arg.email + file = arg.file + domain = arg.domain + nodumps = arg.nodumps + list_domain = arg.list + check_domain = arg.check + update() main() + quit() except KeyboardInterrupt: print ('\n' + R + '[!]' + C + ' Keyboard Interrupt.' + W) exit()