-
-
Save kmahyyg/f5b934aa52df3b3b0b631dc08921fd08 to your computer and use it in GitHub Desktop.
SMTP VRFY python tool intended to check whether SMTP server is leaking usernames. Updated to Python 3.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
# | |
# Simple script intended to abuse SMTP server's VRFY command to leak | |
# usernames having accounts registered within it. | |
# | |
# Mariusz B., 2016 | |
# | |
# Converted to Python3 by kmahyyg, 20230404 | |
# | |
# Designed to split per 18 names, since my environment per 20 failed attempts | |
# will trigger connection reset. | |
# | |
import socket | |
import sys | |
import os | |
# Specify below your default, fallback wordlist | |
DEFAULT_WORDLIST = '/home/htb-ac-295543/Desktop/footprinting-wordlist.txt' | |
DEFAULT_TIMEOUT = 20 | |
def interpret_smtp_status_code(resp): | |
code = int(resp.split(' ')[0]) | |
messages = { | |
250:'Requested mail action okay, completed', | |
251:'User not local; will forward to <forward-path>', | |
252:'Cannot VRFY user, but will accept message and attempt delivery', | |
502:'Command not implemented', | |
530:'Access denied (???a Sendmailism)', | |
550:'Requested action not taken: mailbox unavailable', | |
551:'User not local; please try <forward-path>', | |
} | |
if code in list(messages.keys()): | |
return '({} {})'.format(code, messages[code]) | |
else: | |
return '({} code unknown)'.format(code) | |
def vrfy(server, username, port, timeout, brute=False): | |
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
s.settimeout(timeout) | |
try: | |
conn = s.connect((server, port)) | |
except socket.error as e: | |
print('[!] Connection failed with {}:{} - "{}"'.format(server, port, str(e))) | |
return False | |
try: | |
print('[+] Service banner: "{}"'.format(s.recv(1024).strip())) | |
s.send('HELO test@test.com\r\n'.encode()) | |
print('[>] Response for HELO from {}:{} - '.format(server, port) + s.recv(1024).decode().strip()) | |
except socket.error as e: | |
print('[!] Failed at initial session setup: "{}"'.format(str(e))) | |
return False | |
if brute: | |
print('[?] Engaging brute-force enumeration...') | |
if brute: | |
for i in range(len(username)): | |
user = username[i] | |
payload = 'VRFY ' + user + '\r\n' | |
try: | |
s.send(payload.encode()) | |
res = s.recv(1024).decode().strip() | |
print('({}/{}) Server: {}:{} | VRFY {} | Result: [{}]'.format( | |
i+1, len(username), server, port, user, interpret_smtp_status_code(res))) | |
except Exception as e: | |
print(e) | |
else: | |
payload = 'VRFY ' + username + '\r\n' | |
s.send(payload.encode()) | |
res = s.recv(1024).decode().strip() | |
print('[>] Response from {}:{} - '.format(server, port) + interpret_smtp_status_code(res)) | |
if 'User unknown' in res: | |
print('[!] User not found.') | |
elif (res.startswith('25') and username in res and '<' in res and '>' in res): | |
print('[+] User found: "{}"'.format(res.strip())) | |
else: | |
print('[?] Response: "{}"'.format(res.strip())) | |
s.close() | |
if __name__ == '__main__': | |
if len(sys.argv) < 2: | |
print('[?] Usage: smtpvrfy.py <smtpserver> [username|wordlist] [timeout]') | |
print('\t(to specify a port provide it after a colon \':\' in server parameter)') | |
sys.exit(0) | |
server = sys.argv[1] | |
port = 25 if ':' not in server else int(server[server.find(':')+1:]) | |
username = sys.argv[2] if len(sys.argv) >= 3 else DEFAULT_WORDLIST | |
timeout = DEFAULT_TIMEOUT if len(sys.argv) < 4 else int(sys.argv[3]) | |
if os.path.isfile(username): | |
names = [] | |
with open(username, 'r') as f: | |
for a in f: | |
names.append(a.strip()) | |
print('[>] Provided wordlist file with {} entries.'.format(len(names))) | |
# split per 18 items, since 20 will trigger ips | |
split_gate = 18 | |
splited_names = [names[i:i+split_gate] for i in range(0, len(names), split_gate)] | |
for per_names in splited_names: | |
vrfy(server, per_names, port, timeout, brute=True) | |
else: | |
vrfy(server, username, port, timeout) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment