├── Interactive.py ├── README.md ├── Utilsy.py ├── config.json ├── imgs ├── email.jpg ├── kibana.jpg ├── pepe.png └── pipl.jpg ├── pepe.py └── requirements.txt /Interactive.py: -------------------------------------------------------------------------------- 1 | import Utilsy 2 | from colorama import Fore 3 | import urllib3 4 | 5 | urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) 6 | 7 | utilsy = Utilsy.Utilsy() 8 | 9 | 10 | class Interactive: 11 | 12 | def interactive(self, domain, email, password, config, elastic): 13 | next = None 14 | text_input = "[A] Add domain " + Fore.BLUE + domain + Fore.RESET + " to blacklist\n[T] Test\n[G] Google search\n[H] HaveIBeenPwned\n[P] Pipl\n[F] FullContact\n[I] Inform\n[N] Next\n> " 15 | choice = input(text_input) 16 | while not next: 17 | # print(Fore.GREEN + email + Fore.RESET) 18 | if choice == "A": 19 | config['domains']['blacklist'].append(domain) 20 | print( 21 | 'Domain ' + Fore.BLUE + domain + Fore.RESET + ' has been added to blacklist and will be no longer checked\n') 22 | utilsy.save_config(config) 23 | choice = input( 24 | "[T] Test\n[G] Google search\n[H] HaveIBeenPwned\n[P] Pipl\n[F] FullContact\n[I] Inform\n[N] Next\n> ") 25 | if choice == "T": 26 | utilsy.test_mail(email) 27 | choice = input(text_input) 28 | elif choice == "G": 29 | utilsy.check_google(email, elastic=elastic, password=password) 30 | choice = input(text_input) 31 | elif choice == "H": 32 | utilsy.check_hibp(email, password, elastic=elastic) 33 | choice = input(text_input) 34 | elif choice == "P": 35 | utilsy.check_pipl(email, elastic=elastic, password=password) 36 | choice = input(text_input) 37 | elif choice == "F": 38 | utilsy.check_fullcontact(email, password, elastic=elastic, interactive_flag=True) 39 | choice = input(text_input) 40 | elif choice == "I": 41 | utilsy.send_mail(email, password.rstrip()) 42 | choice = input(text_input) 43 | elif choice == "N": 44 | next = True 45 | else: 46 | print("Wrong Choice") 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PEPE - Post Exploitation Pastebin Emails 2 | Collect information about leaked email addresses from Pastebin 3 | 4 | ![](https://github.com/woj-ciech/pepe/blob/master/imgs/pepe.png?raw=true) 5 | 6 | ## About 7 | Script parses Pastebin email:password dumps and gather information about each email address. It supports Google, Trumail, Pipl, FullContact and HaveIBeenPwned. Moreover, it allows you to send an informational mail to person about his leaked password, at the end every information lands in Elasticsearch for further exploration. 8 | 9 | **It supports only one format - email:password.** 10 | 11 | **Everything else will not work!** 12 | 13 | For now, notification works when it finds match on FullContact and next sends you email address and associated social media accounts. 14 | 15 | ## Requirements: 16 | - Python 3 17 | - FullContact API https://www.fullcontact.com/developer/ 18 | - Google 19 | - Pipl API https://pipl.com/api/ 20 | - HaveIBeenPwned 21 | - SafePush (for notification - optional - In progress) https://www.pushsafer.com/ 22 | - Trumail https://trumail.io/ 23 | - Gmail account (sending emails) 24 | - Elasticsearch (optional) 25 | 26 | ```python 27 | pip install -r requirements 28 | ``` 29 | 30 | ## Config 31 | ``` 32 | {"domains": 33 | { #domains to whitelist or blacklist 34 | "whitelist": [""], 35 | "blacklist": ["yahoo.com"] 36 | }, 37 | "keys": 38 | { #API KEYS 39 | "pushsafer": "API_KEY", 40 | "fullcontact": "API_KEY", 41 | "pipl": "API_KEY" 42 | }, 43 | "gmail": 44 | { #GMAIL credentials and informational message that will be send 45 | "username": "your_username@gmail.com", 46 | "password": "password", 47 | "message": "Hey,\n\nI am a security researcher and I want to inform you that your password !PASSWORD! has been leaked and you should change it immediately.\nThis email is part of the research, you can find more about it on https://medium.com/@wojciech\n\nStay safe!"}, 48 | "elasticsearch": 49 | { #ElasticSearch connection info 50 | "host": "127.0.0.1", 51 | "port": 9200} 52 | } 53 | ``` 54 | 55 | ## Usage 56 | ```python 57 | root@kali:~/PycharmProjects/pepe# python pepe.py -h 58 | usage: pepe.py [-h] [--file FILE] [--stream] [--interactive] 59 | [--modules MODULES [MODULES ...]] [--elasticsearch] 60 | [--whitelist] [--blacklist] 61 | 62 | ,=. 63 | ,=''''==.__.=" o".___ 64 | ,=.==" ___/ 65 | ,==.," , , \,==="" 66 | < ,==) "'"=._.==) `=='' `" ` 67 | 68 | clover/snark^ 69 | http://ascii.co.uk/art/platypus 70 | 71 | Post Exploitation Pastebin Emails 72 | github.com/woj-ciech 73 | medium.com/@woj_ciech 74 | 75 | Example: 76 | python pepe.py --file --interactive --whitelist 77 | python pepe.py --file --modules hibp google trumail --elasticsearch --blacklist 78 | 79 | optional arguments: 80 | -h, --help show this help message and exit 81 | --file FILE Load file 82 | --stream Stream Pastebin 83 | --interactive Interactive mode 84 | --modules MODULES [MODULES ...] 85 | Modules to check in non-interactive mode 86 | --elasticsearch Output to ElasticSearch 87 | --whitelist Whitelist 88 | --blacklist Blacklist 89 | ``` 90 | 91 | ## Example 92 | Interactive mode, each email is checked individually and specific module is executed. 93 | ``` 94 | root@kali:~/PycharmProjects/pepe# python pepe.py --file paste.txt --interactive --blacklist 95 | 96 | -----------------------Found email [REDACTED]@hotmail.com with password [REDACTED]----------------------- 97 | [A] Add domain hotmail.com to blacklist 98 | [T] Test 99 | [G] Google search 100 | [H] HaveIBeenPwned 101 | [P] Pipl 102 | [F] FullContact 103 | [I] Inform 104 | [N] Next 105 | > G 106 | ---Google Search--- 107 | http://[REDACTED] 108 | http://[REDACTED] 109 | http://[REDACTED] 110 | 111 | [A] Add domain gmail.com to blacklist 112 | [T] Test 113 | [G] Google search 114 | [H] HaveIBeenPwned 115 | [P] Pipl 116 | [F] FullContact 117 | [I] Inform 118 | [N] Next 119 | > N 120 | -----------------------Found email [REDACTED].[REDACTED]@gmail.com with password [REDACTED]----------------------- 121 | [A] Add domain gmail.com to blacklist 122 | [T] Test 123 | [G] Google search 124 | [H] HaveIBeenPwned 125 | [P] Pipl 126 | [F] FullContact 127 | [I] Inform 128 | [N] Next 129 | > F 130 | ---FullContact--- 131 | [REDACTED] [REDACTED] 132 | https://twitter.com/[REDACTED] 133 | https://facebook.com/[REDACTED] 134 | https:/linkedin.com/[REDACTED] 135 | [A] Add domain gmail.com to blacklist 136 | [T] Test 137 | [G] Google search 138 | [H] HaveIBeenPwned 139 | [P] Pipl 140 | [F] FullContact 141 | [I] Inform 142 | [N] Next 143 | > P 144 | ---Pipl--- 145 | Name: [REDACTED] 146 | [REDACTED] years old 147 | Jobs: 148 | Quality Control [REDACTED] (since 2018) 149 | [REDACTED] Review [REDACTED] (2017-2018) 150 | [REDACTED] Attorney [REDACTED] (2017-2018) 151 | [REDACTED] Attorney at [REDACTED] (2017-2017) 152 | ... 153 | [REDACTED] (2012-2012) 154 | [REDACTED] Assistant at [REDACTED] (2012-2012) 155 | Author/Founder at [REDACTED] (2009-2011) 156 | https://www.linkedin.com/in/[REDACTED] 157 | http://www.facebook.com/people/[REDACTED] 158 | http://twitter.com/[REDACTED] 159 | http://pinterest.com/[REDACTED] 160 | https://plus.google.com/[REDACTED] 161 | 162 | ... 163 | [REDACTED] 164 | ``` 165 | Non-interactive mode, when only choosen modules are executed against email addressess. 166 | ``` 167 | root@kali:~/PycharmProjects/# python pepe.py --file pastetest.txt --blacklist --modules hibp google fullcontact trumail --elasticsearch 168 | -----------------------Found email [REDACTED]@hotmail.com with password [REDACTED]----------------------- 169 | ---Google Search--- 170 | https://pastebin.com/[REDACTED] 171 | ---Have I Been Pwned--- 172 | LinkedIn 173 | ---FullContact--- 174 | No results 175 | ---Trumail--- 176 | Email test passed 177 | -----------------------Found email charlie.[REDACTED]@live.com with password [REDACTED]----------------------- 178 | ---Google Search--- 179 | https://justpaste.it/[REDACTED] 180 | https://pastebin.com/[REDACTED] 181 | ---Have I Been Pwned--- 182 | MyHeritage 183 | RiverCityMedia 184 | Tumblr 185 | YouveBeenScraped 186 | ---FullContact--- 187 | Charlie [REDACTED] 188 | https://twitter.com/[REDACTED] 189 | [REDACTED] 190 | ---Trumail--- 191 | Email test passed 192 | -----------------------Found email [REDACTED].[REDACTED]@gmail.com with password [REDACTED]----------------------- 193 | ---Google Search--- 194 | http://[REDACTED] 195 | http://[REDACTED] 196 | http://[REDACTED] 197 | https://pastebin.com/[REDACTED] 198 | ---Have I Been Pwned--- 199 | BTSec 200 | Exactis 201 | HauteLook 202 | Houzz 203 | LinkedIn 204 | ---FullContact--- 205 | [REDACTED] [REDACTED] 206 | https://www.facebook.com/[REDACTED] 207 | [REDACTED] 208 | ---Trumail--- 209 | Email test passed 210 | -----------------------Found email [REDACTED].[REDACTED]@gmail.com with password [REDACTED]----------------------- 211 | ---Google Search--- 212 | https://[REDACTED] 213 | https://[REDACTED] 214 | https://[REDACTED] 215 | https://pastebin.com/[REDACTED] 216 | ---Have I Been Pwned--- 217 | Lastfm 218 | LinkedIn 219 | MySpace 220 | Trillian 221 | Tumblr 222 | ---FullContact--- 223 | [REDACTED] [REDACTED] [REDACTED]. 224 | https://www.facebook.com/[REDACTED] 225 | https://plus.google.com/[REDACTED] 226 | https://www.linkedin.com/in/[REDACTED] 227 | http://www.pinterest.com/[REDACTED] 228 | https://twitter.com/[REDACTED] 229 | https://youtube.com/user/[REDACTED] 230 | [REDACTED] 231 | ``` 232 | ## Screens 233 | ![](https://github.com/woj-ciech/pepe/blob/master/imgs/pipl.jpg?raw=true) 234 | 235 | ![](https://github.com/woj-ciech/pepe/blob/master/imgs/kibana.jpg?raw=true) 236 | 237 | ![](https://github.com/woj-ciech/pepe/blob/master/imgs/email.jpg?raw=true) 238 | ## Other 239 | I'm not responsible for any damage caused. 240 | You know, it was made for educational purposes. 241 | -------------------------------------------------------------------------------- /Utilsy.py: -------------------------------------------------------------------------------- 1 | import json 2 | import smtplib 3 | import ssl 4 | import time 5 | 6 | import pyhibp 7 | import requests 8 | from colorama import Fore 9 | from elasticsearch import Elasticsearch 10 | from fullcontact import FullContact 11 | from googlesearch import search 12 | from piplapis.search import SearchAPIRequest 13 | from pushsafer import Client, init 14 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 15 | 16 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 17 | import sys 18 | 19 | with open('config.json', 'r') as f: 20 | conf = json.load(f) 21 | 22 | 23 | # noinspection PyPep8,PyPep8 24 | class Utilsy: 25 | 26 | def get_paste(self): 27 | try: 28 | # Create the API uri 29 | url = 'https://scrape.pastebin.com/api_scraping.php?limit=200' 30 | req = requests.get(url) 31 | 32 | if 'DOES NOT HAVE ACCESS' in req.text: 33 | print( 34 | Fore.RED + "Your IP is not whitelisted" + Fore.RESET + " go to https://pastebin.com/doc_scraping_api") 35 | return [] 36 | paste_json = json.loads(req.content) 37 | return paste_json 38 | except Exception as e: 39 | print(Fore.RED + str(e) + Fore.RESET) 40 | return False 41 | 42 | def check_google(self, email, password, elastic=False): 43 | print('---' + Fore.CYAN + 'Google Search' + Fore.RESET + '---') 44 | to_elastic = {"email": email, "password": password, "results": []} 45 | try: 46 | for url in search("\"" + email + "\"", stop=10, tbs="li:1"): 47 | to_elastic['results'].append(url) 48 | print(url) 49 | 50 | except Exception as e: 51 | print(str(e) + Fore.RESET) 52 | 53 | if len(to_elastic['results']) > 0: 54 | if elastic: 55 | self.put_elastic('google', 'email', to_elastic) 56 | return True 57 | else: 58 | print(Fore.RED + "Nothing found" + Fore.RESET) 59 | return False 60 | 61 | def calc_score(self, email, google=None, fc=None, hibp=None, trumail=None): 62 | if fc: 63 | print("Found social media profile, sending notification") 64 | social_string = " ".join(str(x) for x in fc) 65 | self.send_push("Found email " + email + " with following social media: " + social_string) 66 | 67 | def check_hibp(self, email, password, elastic=False): 68 | print("---" + Fore.CYAN + "Have I Been Pwned" + Fore.RESET + "---") 69 | to_elastic = {"email": email, "password": password, "results": []} 70 | try: 71 | resp = pyhibp.get_account_breaches(account=email, truncate_response=True) 72 | if resp: 73 | for name in resp: 74 | to_elastic['results'].append(name['Name']) 75 | print(Fore.MAGENTA + name['Name'] + Fore.RESET) 76 | else: 77 | print(Fore.RED + "Nothing found" + Fore.RESET) 78 | except Exception as e: 79 | print(Fore.RED + str(e) + Fore.RESET) 80 | 81 | if len(to_elastic['results']) > 0: 82 | if elastic: 83 | self.put_elastic('hibp', 'email', to_elastic) 84 | return True 85 | else: 86 | return False 87 | 88 | def send_push(self, message): 89 | try: 90 | init(privatekey=conf['keys']['pushsafer']) 91 | client = Client("") 92 | client.send_message(message=message, title="Found", device='a', sound="1", icon="20", vibration="2", 93 | answer=0, 94 | picture1=None, picture2=None, picture3=None, expire=None, time2live=None, url="", 95 | retry=None, 96 | urltitle=None, priority=5) 97 | print("Push notification has been send") 98 | except Exception as e: 99 | print(Fore.RED + str(e) + Fore.RESET) 100 | 101 | def check_fullcontact(self, email, password, interactive_flag=False, elastic=False): 102 | print("---" + Fore.CYAN + "FullContact" + Fore.RESET + "---") 103 | fc = FullContact(conf['keys']['fullcontact']) 104 | person = fc.person(email=email) 105 | decoded_person_json = person.content.decode("utf-8") 106 | person_json = json.loads(decoded_person_json) 107 | social_to_push = [] 108 | to_elastic = {"email": email, "password": password} 109 | 110 | try: 111 | if person_json['status'] == 200: 112 | if 'contactInfo' in person_json: 113 | if 'fullName' in person_json['contactInfo']: 114 | print(person_json['contactInfo']['fullName'] 115 | ) 116 | 117 | if 'socialProfiles' in person_json: 118 | for social in person_json['socialProfiles']: 119 | social_to_push.append(social['url']) 120 | print(social['url']) 121 | 122 | if 'demographics' in person_json: 123 | if 'locationGeneral' in person_json['demographics']: 124 | print(person_json['demographics']['locationGeneral']) 125 | 126 | to_elastic.update(person_json) 127 | if elastic: 128 | self.put_elastic('fullcontact', 'email', to_elastic) 129 | 130 | elif person_json['status'] == 202: 131 | if interactive_flag: 132 | time_dec = input("Your search is queued, do you want to wait for 2 minutes? [Y/N] \n> ") 133 | if time_dec == "Y": 134 | print("Sleeping...") 135 | time.sleep(60 * 2) 136 | self.check_fullcontact(email, elastic) 137 | else: 138 | pass 139 | 140 | else: 141 | print("No results") 142 | 143 | except Exception as e: 144 | print(Fore.RED + str(e) + Fore.RESET) 145 | 146 | if len(social_to_push) > 0 and interactive_flag: 147 | return social_to_push 148 | else: 149 | return False 150 | 151 | def save_config(self, config): 152 | with open('config.json', 'w') as f: 153 | json.dump(config, f) 154 | print("Config has been saved") 155 | 156 | def check_pipl(self, email, password, elastic=False): 157 | print("---" + Fore.CYAN + "Pipl" + Fore.RESET + '---') 158 | request = SearchAPIRequest(email=email, 159 | show_sources=True, use_https=True, api_key=conf['keys']['pipl']) 160 | to_elastic = {"email": email, "password": password, "name": [], "dob": "", 'jobs': [], 'addresses': [], 161 | "images": [], "urls": []} 162 | try: 163 | response = request.send() 164 | if response.person: 165 | if response.person.names: 166 | print("Name: " + response.person.names[0].display) 167 | for name in response.person.names: 168 | to_elastic['name'].append(name.display) 169 | if response.person.dob: 170 | print(response.person.dob.display) 171 | to_elastic['dob'].append(str(response.person.dob.display)) 172 | if response.person.jobs: 173 | print("Jobs:") 174 | for job in response.person.jobs: 175 | # if "Director" in job.display or "CEO" in job.display 176 | # self.send_push("Found big fish " + email + password) 177 | 178 | print(job.display) 179 | if response.person.urls: 180 | for url in response.person.urls: 181 | print(url.display) 182 | to_elastic['urls'].append(url.display) 183 | 184 | for address in response.person.addresses: 185 | to_elastic['addresses'].append(address.display) 186 | 187 | for image in response.person.images: 188 | to_elastic['images'].append(image.display) 189 | 190 | if elastic: 191 | self.put_elastic('pipl', 'email', to_elastic) 192 | else: 193 | print("Nothing was found :(") 194 | except Exception as e: 195 | print(Fore.RED + str(e) + Fore.RESET) 196 | 197 | def test_mail(self, email): 198 | print("---" + Fore.CYAN + "Trumail" + Fore.RESET + '---') 199 | req_trumail = requests.get("https://api.trumail.io/v2/lookups/json?email=" + email) 200 | json_trumail = json.loads(req_trumail.content) 201 | try: 202 | if not json_trumail['validFormat']: 203 | print(Fore.RED + "[*] Wrong email format") 204 | return False 205 | elif not json_trumail['deliverable']: 206 | print("It seems like email address " + email + " is not deliverable") 207 | elif not json_trumail['hostExists']: 208 | print(email + " may be not real because host does not exists" + Fore.RESET) 209 | else: 210 | print(Fore.GREEN + "Email test passed" + Fore.RESET) 211 | return True 212 | except KeyError: 213 | print(Fore.RED + 'Rate limit' + Fore.RESET) 214 | 215 | def send_mail(self, email, password): 216 | print("Sending email to " + Fore.GREEN + email + Fore.RESET) 217 | port = 587 # For starttls 218 | smtp_server = "smtp.gmail.com" 219 | sender_email = conf['gmail']['username'] # from config 220 | receiver_email = email # from paste 221 | account_password = conf['gmail']['password'] # password to account 222 | msg = conf['gmail']['message'] 223 | message = 'Subject: {}\n\n{}'.format("You password has been leaked", msg) 224 | 225 | try: 226 | context = ssl.create_default_context() 227 | with smtplib.SMTP(smtp_server, port) as server: 228 | server.ehlo() # Can be omitted 229 | server.starttls(context=context) 230 | server.ehlo() # Can be omitted 231 | server.login(sender_email, account_password) 232 | server.sendmail(sender_email, receiver_email, message.replace("!PASSWORD!", password)) 233 | print(Fore.MAGENTA + "Email has been sent successfully\n" + Fore.RESET) 234 | except Exception as e: 235 | print(Fore.RED + str(e) + Fore.RESET) 236 | 237 | def test_elastic_connection(self): 238 | 239 | es = Elasticsearch(host=conf['elasticsearch']['host'], port=conf['elasticsearch']['port']) 240 | 241 | if not es.ping(): 242 | print('Unable to connect to Elasticsearch. \nCheck your connection and settings.json file') 243 | sys.exit() 244 | else: 245 | print("Succesfully connected to ElasticSearch") 246 | return es 247 | 248 | def put_elastic(self, index, doc_type, body): 249 | es = Elasticsearch(host=conf['elasticsearch']['host'], port=conf['elasticsearch']['port']) 250 | # es = Elasticsearch([{'host': 'localhost', 'port': 9200}]) 251 | ids = [] 252 | print("[*] Saving output to Elasticsearch") 253 | try: 254 | resp = es.search(index=index) 255 | for i in resp['hits']['hits']: 256 | int_id = int(i['_id']) 257 | ids.append(int_id) 258 | 259 | last_id = max(ids) 260 | 261 | es.index(index=index, doc_type=doc_type, id=last_id + 1, body=body) 262 | print(Fore.GREEN + "Success" + Fore.RESET) 263 | except Exception as e: 264 | try: 265 | es.index(index=index, doc_type=doc_type, id=1, body=body) 266 | print(Fore.GREEN + "Success" + Fore.RESET) 267 | except Exception as e: 268 | print(Fore.RED + str(e) + Fore.RESET) 269 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "domains":{ 3 | "whitelist":[ 4 | "" 5 | ], 6 | "blacklist":[ 7 | "" 8 | ] 9 | }, 10 | "keys":{ 11 | "pushsafer":"api_key", 12 | "fullcontact":"api_key", 13 | "pipl":"api_key" 14 | }, 15 | "gmail":{ 16 | "username":"gmail_username", 17 | "password":"gmail_password", 18 | "message":"Hey,\n\nI am a security researcher and I want to inform you that your password !PASSWORD! has been leaked and you should change it immediately.\nThis email is part of the research, you can find more about it on https://medium.com/@wojciech\n\nStay safe!" 19 | }, 20 | "elasticsearch":{ 21 | "host":"127.0.0.1", 22 | "port":9200 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /imgs/email.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/woj-ciech/pepe/b81889ba1976c0186d2987793598bff1ebe1fb55/imgs/email.jpg -------------------------------------------------------------------------------- /imgs/kibana.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/woj-ciech/pepe/b81889ba1976c0186d2987793598bff1ebe1fb55/imgs/kibana.jpg -------------------------------------------------------------------------------- /imgs/pepe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/woj-ciech/pepe/b81889ba1976c0186d2987793598bff1ebe1fb55/imgs/pepe.png -------------------------------------------------------------------------------- /imgs/pipl.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/woj-ciech/pepe/b81889ba1976c0186d2987793598bff1ebe1fb55/imgs/pipl.jpg -------------------------------------------------------------------------------- /pepe.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from validate_email import validate_email 3 | import json 4 | from colorama import Fore 5 | import Utilsy 6 | import argparse 7 | from argparse import RawTextHelpFormatter 8 | import time 9 | import Interactive 10 | import requests 11 | import os 12 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 13 | 14 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 15 | 16 | desc = """ ,=. 17 | ,=''''==.__.=" o".___ 18 | ,=.==" ___/ 19 | ,==.," , , \,==="" 20 | < ,==) \"'"=._.==) \ 21 | `=='' `" `\n 22 | clover/snark^ 23 | http://ascii.co.uk/art/platypus 24 | 25 | Post Exploitation Pastebin Emails 26 | github.com/woj-ciech 27 | medium.com/@woj_ciech 28 | 29 | Example: 30 | python pepe.py --file --interactive --whitelist 31 | python pepe.py --file --modules hibp google trumail --elasticsearch --blacklist""" 32 | 33 | parser = argparse.ArgumentParser( 34 | description=desc, formatter_class=RawTextHelpFormatter) 35 | 36 | parser.add_argument("--file", help="Load file", default=None) 37 | parser.add_argument("--stream", help="Stream Pastebin", action='store_true') 38 | parser.add_argument("--interactive", help="Interactive mode", action='store_true') 39 | parser.add_argument("--modules", help="Modules to check in non-interactive mode", nargs='+', type=str, 40 | default="google hibp") 41 | parser.add_argument("--elasticsearch", help="Output to ElasticSearch", action='store_true') 42 | parser.add_argument("--whitelist", help="Whitelist", action="store_true") 43 | parser.add_argument("--blacklist", help="Blacklist", action="store_true") 44 | 45 | utilsy = Utilsy.Utilsy() 46 | 47 | args = parser.parse_args() 48 | file = args.file 49 | stream = args.stream 50 | interactive = args.interactive 51 | modules = args.modules 52 | elasticsearch = args.elasticsearch 53 | whitelist = args.whitelist 54 | blacklist = args.blacklist 55 | 56 | if elasticsearch: 57 | utilsy.test_elastic_connection() 58 | 59 | if not stream and not file: 60 | print(Fore.RED + "Choose stream or file" + Fore.RESET) 61 | sys.exit() 62 | 63 | if not whitelist and not blacklist: 64 | print(Fore.RED + "You need to choose between whitelist and blacklist" + Fore.RESET) 65 | 66 | with open('config.json', 'r+') as f: 67 | config = json.load(f) 68 | 69 | if not os.path.exists(file): 70 | print(desc) 71 | print(Fore.RED + "File does not exist" + Fore.RESET) 72 | sys.exit() 73 | 74 | 75 | c = 0 76 | if stream: 77 | print(desc) 78 | while 1: 79 | paste = utilsy.get_paste() 80 | if paste: 81 | for link in paste: 82 | req = requests.get(link['scrape_url']) 83 | ##match = rule.match(data=req.content) 84 | splitted = req.text.splitlines()[0].split(":") 85 | print(link['scrape_url']) 86 | c = c + 1 87 | print(c) 88 | try: 89 | if validate_email(splitted[0]) and splitted[1]: 90 | username_domain_list = splitted[0].split('@') 91 | if interactive: 92 | interact = Interactive.Interactive() 93 | print(Fore.GREEN + "Found email/pass leak") 94 | print(link['scrape_url']) 95 | print('-----------------------Found email ' + Fore.GREEN + splitted[ 96 | 0] + Fore.RESET + " with password " + Fore.RED + splitted[ 97 | 1].rstrip() + Fore.RESET + "-----------------------") 98 | interactive(username_domain_list[1], splitted[0], splitted[1], config, elasticsearch) 99 | else: 100 | if 'google' in modules: 101 | utilsy.check_google(splitted[0], splitted[1], elasticsearch) 102 | if "hibp" in modules: 103 | utilsy.check_hibp(splitted[0], splitted[1], elasticsearch) 104 | if 'pipl' in modules: 105 | utilsy.check_pipl(splitted[0], splitted[1], elasticsearch) 106 | if 'fullcontact' in modules: 107 | utilsy.check_fullcontact(splitted[0], splitted[1], elasticsearch) 108 | except: 109 | pass 110 | print("Sleeping for 2 minutes...") 111 | time.sleep(2 * 60) 112 | 113 | elif file: 114 | print(desc) 115 | with open(file) as f: 116 | lines = f.readlines() 117 | ###only checks if first string before colon is email address and password is not empty 118 | first_email_password_list = lines[0].split(":") 119 | if validate_email(first_email_password_list[0]) and first_email_password_list[1]: 120 | for line in lines: 121 | fc = False 122 | ggg = False 123 | hibp = False 124 | trum = False 125 | 126 | email_password_list = line.split(':') 127 | username_domain_list = email_password_list[0].split('@') 128 | if whitelist: 129 | if username_domain_list[1] in config['domains']['whitelist']: 130 | print('-----------------------Found email ' + Fore.GREEN + email_password_list[ 131 | 0] + Fore.RESET + " with password " + Fore.RED + email_password_list[ 132 | 1].rstrip() + Fore.RESET + "-----------------------") 133 | if interactive: 134 | interact = Interactive.Interactive() 135 | interact.interactive(username_domain_list[1], email_password_list[0], 136 | email_password_list[1], config, elastic=elasticsearch) 137 | else: 138 | if 'google' in modules: 139 | ggg = utilsy.check_google(email_password_list[0], email_password_list[1], elasticsearch) 140 | if "hibp" in modules: 141 | hibp = utilsy.check_hibp(email_password_list[0], email_password_list[1], elasticsearch) 142 | if 'pipl' in modules: 143 | pipl = utilsy.check_pipl(email_password_list[0], elasticsearch) 144 | if 'fullcontact' in modules: 145 | fc = utilsy.check_fullcontact(email_password_list[0], password=email_password_list[1], 146 | interactive_flag=False, elastic=elasticsearch) 147 | if 'trumail' in modules: 148 | trum = utilsy.test_mail(email_password_list[0]) 149 | 150 | utilsy.calc_score(email=email_password_list[0], google=ggg, fc=fc, hibp=hibp, trumail=trum) 151 | 152 | if blacklist: 153 | if username_domain_list[1] not in config['domains']['blacklist']: 154 | print('-----------------------Found email ' + Fore.GREEN + email_password_list[ 155 | 0] + Fore.RESET + " with password " + Fore.RED + email_password_list[ 156 | 1].rstrip() + Fore.RESET + "-----------------------") 157 | if interactive: 158 | interact = Interactive.Interactive() 159 | interact.interactive(username_domain_list[1], email_password_list[0], 160 | email_password_list[1], config, elasticsearch) 161 | else: 162 | if 'google' in modules: 163 | ggg = utilsy.check_google(email_password_list[0], email_password_list[1], elasticsearch) 164 | if "hibp" in modules: 165 | hibp = utilsy.check_hibp(email_password_list[0], email_password_list[1], elasticsearch) 166 | if 'pipl' in modules: 167 | pipl = utilsy.check_pipl(email_password_list[0], elasticsearch) 168 | if 'fullcontact' in modules: 169 | fc = utilsy.check_fullcontact(email_password_list[0], password=email_password_list[1], 170 | interactive_flag=False, elastic=elasticsearch) 171 | if 'trumail' in modules: 172 | trum = utilsy.test_mail(email_password_list[0]) 173 | 174 | utilsy.calc_score(email=email_password_list[0], google=ggg, fc=fc, hibp=hibp, trumail=trum) 175 | else: 176 | print(desc) 177 | print(Fore.RED + "Check your file, dump has to be in email:password format.") 178 | f.close() 179 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | colorama==0.4.1 2 | elasticsearch==6.3.1 3 | FullContact.py==0.0.6 4 | google==2.0.1 5 | google-search==1.0.2 6 | piplapis-python==5.1.5 7 | pyhibp==3.0.0 8 | python-pushsafer==0.4 9 | requests==2.11.1 10 | urllib3==1.24.1 11 | validate-email==1.3 12 | --------------------------------------------------------------------------------