Advertisement
opexxx

smtpenum.py

Jun 24th, 2014
351
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.11 KB | None | 0 0
  1. # packages required for framework integration
  2. import module
  3. # module specific packages
  4. import socket
  5. import re
  6. import time
  7.  
  8. # Module is a simple port of smtp-user-enum.pl from
  9. # http://pentestmonkey.net/tools/user-enumeration/smtp-user-enum
  10.  
  11. class Module(module.Module):
  12.  
  13.     def __init__(self, params):
  14.         module.Module.__init__(self, params)
  15.         # module options
  16.         self.register_option('rhost', None, 'yes', 'Remote mail server to query.')
  17.         self.register_option('rport', 25, 'yes', 'Remote port of listening mail server.')
  18.         self.register_option('method', 'VRFY', 'yes', 'Method of verification to use: VRFY, EXPN, or RCPT.')
  19.         self.register_option('delay', 3000, 'yes', 'Delay (ms) between sequential requests to the mail server.')
  20.         self.register_option('clobber', False, 'yes', 'Drop existing entries in \'verified\' table.')
  21.         self.register_option('from', None, 'no', 'MAIL FROM address to use with RCPT verification method.')
  22.         self.info = {
  23.                      'Name': 'SMTP User Enumerator',
  24.                      'Author': 'Cody Wass',
  25.                      'Description': 'Queries a mail server using addresses in the \'contacts\' database to determine which are valid. Results are currently stored in a newly created \'verified\' table.',
  26.                      }
  27.  
  28.     def module_run(self):
  29.         self.output("Starting smtp-user-enum module...")
  30.         self.output("---------------------------------------------------------")
  31.         self.output("| Scan Results |")
  32.         self.output("---------------------------------------------------------")
  33.  
  34.         if not self.options['from'] and self.options['method'] == 'RCPT':
  35.             self.alert('Using RCPT with no \'from\' address specified - using user@example.com.')
  36.             self.options['from'] = 'user@example.com'
  37.        
  38.         # Prepare table to hold results
  39.         if self.options['clobber']:
  40.             self.query("DROP TABLE IF EXISTS verified")
  41.             self.query("CREATE TABLE verified (email TEXT)")
  42.         else:
  43.             self.query("CREATE TABLE IF NOT EXISTS verified (email TEXT)")
  44.        
  45.         # Grab email addresses from the database
  46.         email_list = self.query('SELECT email FROM contacts WHERE email IS NOT NULL')
  47.        
  48.         # Make sure we actually got results
  49.         if len(email_list) == 0:
  50.                 self.error('No email addresses found in table')
  51.                 return
  52.        
  53.         # Step through entries in our result set
  54.         for entry in email_list:
  55.             self.verify_email(entry[0])
  56.             time.sleep(self.options['delay'] / 1000)
  57.  
  58.         self.output("---------------------------------------------------------")
  59.         self.output("| Scan Finished |")
  60.         self.output("---------------------------------------------------------")
  61.  
  62.  
  63.     def verify_email(self, email):
  64.  
  65.         # Make sure we successfully create the socket for SMTP communication.
  66.         # Would wrap in try, but framework catches timeout/socket errors.
  67.         server_conn = socket.create_connection([self.options['rhost'], self.options['rport']])
  68.         # Read server's 220 ready.
  69.         data = server_conn.recv(1024)
  70.         self.verbose('Server says: ' + data)
  71.  
  72.         if (data[:3] == '220'):
  73.         # server responded with '220 go ahead'
  74.  
  75.             if (self.options['method'] == 'VRFY'):
  76.                 # Send our HELO.
  77.                 server_conn.send('HELO\r\n')
  78.                 data = server_conn.recv(1024)
  79.                 # Send VRFY and grab response.
  80.                 self.verbose('Trying address: ' + email + '...')
  81.                 server_conn.send('VRFY ' + email + '\r\n')
  82.  
  83.             elif (self.options['method'] == 'EXPN'):
  84.                 # Send our HELO.
  85.                 server_conn.send('HELO\r\n')
  86.                 data = server_conn.recv(1024)
  87.                 # Send EXPN and grab response.
  88.                 self.verbose('Trying address: ' + email + '...')
  89.                 server_conn.send('EXPN ' + email + '\r\n')
  90.  
  91.             elif (self.options['method'] == 'RCPT'):
  92.                 # Send our HELO.
  93.                 server_conn.send('HELO\r\n')
  94.                 data = server_conn.recv(1024)
  95.                 server_conn.send('MAIL FROM:<' + self.options['from'] + '>\r\n')
  96.                 data = server_conn.recv(1024)
  97.                 self.verbose('Trying address: ' + email + '...')
  98.                 server_conn.send('RCPT TO:<' + email + '>\r\n')
  99.  
  100.             else:
  101.                 self.error('Unknown method: ' + self.options['method'] + ' in use.')
  102.        
  103.  
  104.             # Grab server's response.
  105.             data = server_conn.recv(1024)
  106.  
  107.             # Check server response for match.
  108.             if (re.search(r'2\d\d', data)):
  109.                 # We got a 2xx response, should mean user exists.
  110.                 self.output(email + ' exists!')
  111.                 self.verbose('Server reponse: ' + data)
  112.  
  113.                 # Add email to verified-contacts table.
  114.                 self.query('INSERT INTO verified VALUES (?)', (email,))
  115.                
  116.             elif (re.search(r'5\d\d', data)):
  117.                 # 5xx response, user does not exist.
  118.                 self.verbose(email + ' does not exist.')
  119.                 self.verbose('Server response: ' + data)
  120.  
  121.             else:
  122.                 # Other (4xx or similar) response. Print out to user.
  123.                 self.output('Unknown response: ' + data)
  124.  
  125.             # Reset SMTP connection in preparation for another loop.
  126.             server_conn.send('RSET\r\n')
  127.             data = server_conn.recv(1024)
  128.            
  129.             # Blow away socket for next connection.
  130.             server_conn.shutdown(socket.SHUT_RDWR)
  131.             server_conn.close()
  132.             return
  133.  
  134.         else:
  135.             self.error('ERROR: Server didn\'t respond with \'220\'.')
  136.             self.error('ERROR: Response was: ' + data)
  137.  
  138.             server_conn.shutdown(socket.SHUT_RDWR)
  139.             server_conn.close()
  140.             return
  141.  
  142.     Status
  143.     API
  144.     Training
  145.     Shop
  146.     Blog
  147.     About
  148.  
  149.     © 2014 GitHub, Inc.
  150.     Terms
  151.     Privacy
  152.     Security
  153.     Contact
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement