Last active
October 8, 2024 15:29
-
-
Save mgeeky/1df141b18082b6f424df98fa6a630435 to your computer and use it in GitHub Desktop.
SMTP VRFY python tool intended to check whether SMTP server is leaking usernames.
This file contains hidden or 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/python | |
# | |
# Simple script intended to abuse SMTP server's VRFY command to leak | |
# usernames having accounts registered within it. | |
# | |
# Mariusz B., 2016 | |
# | |
import socket | |
import sys | |
import os | |
# Specify below your default, fallback wordlist | |
DEFAULT_WORDLIST = '/root/data/fuzzdb/wordlists-user-passwd/names/namelist.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 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, e: | |
print '[!] Connection failed with {}:{} - "{}"'.format(server, port, str(e)) | |
return False | |
try: | |
print '[+] Service banner: "{}"'.format(s.recv(1024).strip()) | |
s.send('HELO [email protected]\r\n') | |
print '[>] Response for HELO from {}:{} - '.format(server, port) + s.recv(1024).strip() | |
except socket.error, 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] | |
s.send('VRFY ' + user + '\r\n') | |
res = s.recv(1024).strip() | |
print '({}/{}) Server: {}:{} | VRFY {} | Result: [{}]'.format( | |
i, len(username), server, port, user, interpret_smtp_status_code(res)) | |
else: | |
s.send('VRFY ' + username + '\r\n') | |
res = s.recv(1024).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)) | |
vrfy(server, 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