Metasploit mailing list archives

Re: Auxiliary Module - Generation of usernames for target company


From: Jabra <jabra () spl0it org>
Date: Wed, 16 Jun 2010 19:54:11 -0400

Nice! I have been using this method for a long time now.

Here are a few more suggestions:


Schemes Examples:                   
        Scheme                  Separator     
        ------                  ----------  
        1                       none            (ex: johnsmith\@domain)
        2                       dash            (ex: john-smith\@domain)
        3                       underscore      (ex: john_smith\@domain)
        4                       dot             (ex: john.smith\@domain)

        11                      no separator    (ex: jsmith\@domain)
        22                      dash            (ex: j-smith\@domain)

        ...  This continues for all the types below    ...
       
Schemes Definition:
        Scheme      Group     
        1-10        1           firstname lastname
        11-20       2           first_char_firstname lastname
        21-30       3           five_chars_firstname lastname
        31-40       4           five_chars_firstname first_char_lastname


code: http://spl0it.org/files/genemailaddrs.pl


-Jabra

On 16.Jun.2010 05:31PM -0600, Jason Wood wrote:
I think that my first email got stuck in the moderation queue, so I thought
I'd resend it now that I'm a list member.  Hope this is of interest to
folks.

Jason

---------- Forwarded message ----------
From: Jason Wood <tadaka () gmail com>
Date: Tue, Jun 15, 2010 at 10:36 AM
Subject: Auxiliary Module - Generation of usernames for target company
To: framework () spool metasploit com


Hi all,
I've finished an auxiliary/gather module which creates possible username
combinations for a target company.  It does this by searching Google or
Yahoo's XML API for "site:linkedin.com targetcompanyname", gathers up the
names of all the people with the target company as part of their profile and
then munges them into possible usernames.  The results can be thrown to the
console window or dumped to a directory of the pen tester's choice.

Current username combinations are:

first name + last initial
first name + last name
first initial + last name
first initial + middle initial + last name
last name + first initial

I've included the module on this email or it can be downloaded from
SourceForge at https://sourceforge.net/projects/reconnoiter/files/.  I'm
still doing some testing and am asking for more eyes on it, so any feed back
is extremely welcome.  Also, if it appears worthy I'd like to submit it for
possible inclusion to the framework.

Thanks,
Jason

-- 

irc: Tadaka
Twitter:  Jason_Wood
jwnetworkconsulting.com


require 'msf/core'
require 'net/http'

class Metasploit3 < Msf::Auxiliary
              
              include Msf::Auxiliary::Report
              def initialize(info = {})
                      super(update_info(info,
                                              'Name' => 'Username Generator using Linkedin',
                                              'Description' => %q{
                                              This module uses Google or Yahoo to create a list of
                                              potential usernames for a target company by searching Linkedin for 
                                              names of people who have the company name in their profile.  
                                              
                                              If you want to use the Yahoo! XML web service, you will need to create 
an
                                              APPID key to use this function.  The results seem better than the Google
                                              search because we do not have to screen scrape to get them.  We can 
just 
                                              pull them directly from the XML.  Also, getting your IP banned is not 
an 
                                              issue since Yahoo! throttles by the APPID key.
                                              
                                              WARNING:
                                              CALLING THE GOOGLE SEARCH TOO OFTEN, TOO QUICKLY CAN GET YOUR IP BANNED!
                                              },
                                              'Author' => [ 'Jason Wood <tadaka[at]gmail.com>' ],
                                              'License' => MSF_LICENSE,
                                              'Version' => '$Revision: 1 $'))
                                      register_options(
                                              [
                                                              OptString.new('COMPANY_NAME', [ true, 'The name of the 
target company' ]),
                                                              OptBool.new('USE_GOOGLE', [ false, 'Enable Google as a 
backend search engine', true ]),
                                                              OptBool.new('USE_YAHOO', [ false, 'Enable Yahoo! as a 
backend search engine', true ]),
                                                              OptString.new('YAHOO_APPKEY', [ false, 'A valid Yahoo! 
XML AppKey']),
                                                              OptString.new('OUTDIR', [ false, "A directory path to 
store the username lists"]),
                                              ], self.class)

              end

              def name_buster(raw_names, flast, lastf, firstl, firstlast, fmlast)
                      # Split the names gathered and create usernames
                      
                      raw_names.each do |namebust|
                              # First some housekeeping on variables at the start of each loop
                              fname = ""
                              mname = ""
                              lname = ""
                              name_split = []

                              name_split << namebust[0].split(' ')
                              # puts name_split[0].length()
                              
                              
                              # Haven't figured out why yet, but the split creates an array within
                              # an array on name_split.  So "john doe" splits to an array that 
                              # looks like [["john","doe"]].  So we check for its length, but looking at 
                              # the zero array member, which contains an array with two members.  Kinda weird.
                              if name_split[0].length() == 2 then
                                      fname = name_split[0][0]
                                      lname = name_split[0][1]
                                      
                                      # poor man debugging
                                      # puts "First name:  #{fname}"
                                      # puts "Last name:  #{lname}"
                              end
                              
                              # Just in case they have a middle name listed
                              if name_split[0].length() == 3 then
                                      fname = name_split[0][0]
                                      mname = name_split[0][1]
                                      lname = name_split[0][2]
                                      
                                      
                                      
                                      # poor man debugging
                                      # puts "First name:  #{fname}"
                                      # puts "Middle name: #{mname}"
                                      # puts "Last name:  #{lname}"
                              end
                              
                              # Don't do anything if only a single name is returned
                              if name_split[0].length() != 1 then
                                      # puts "#{fname}"
                                      # puts "#{lname}"
                                      first_initial = fname[0].chr
                                      last_initial = lname[0].chr
                              
                                      # Start making usernames
                                      flast << first_initial + lname
                                      lastf << lname + first_initial
                                      firstl << fname + last_initial
                                      firstlast << fname + lname

                                      if mname != "" then
                                              middle_initial = mname[0].chr
                                              fmlast << first_initial + middle_initial + lname
                                      end
                              end

                      end

              end

              #Search google.com for Linkedin profiles associated with the target company
              def use_google(targetcompany, raw_names)
              
                      print_status("Searching Google for profiles with associated to #{targetcompany}")
                              
                      response = ""
                      header = { 'User-Agent' => "Lynx/2.8.6rel.5 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.8l"}
                      clnt = Net::HTTP.new("www.google.com")
                              

                              searches = ["1"]
                              # searches = ["1", "101", "201", "301", "401", "501"]
                              
                              searches.each { |num|
                                      resp, data = 
clnt.get2("/search?q=site%3Alinkedin.com+#{targetcompany}+&filter=0&start=#{num}&sa=N&num=100",header)
                                      response << data.downcase
                                      # Try to minimize Google bans
                                      sleep 2
                              }
                
                              print_status("Extracting possible usernames from Google search results...")
                              # Take the data in response and send to filter
                              goog_regex = '<h3 class="\w"><a href=".*?"\s.*?>(.*?)\s-.*?<\/a><\/h3>'
                              # print goog_regex
                              
                              # print "#{response}"
                              response.scan(/#{goog_regex}/i) do |t|
                              #       puts "#{t}"
                                      raw_names << t
                              end
                              
                              # Clean out the HTML cruft that sneaks passed the regex
                              raw_names.delete_if {|b| b.to_s.include? "<"}
                              raw_names.delete_if {|b| b.to_s.include? "#"}
                              raw_names.delete_if {|b| b.to_s.include? "+"}
                              
                              # Make sure everthing is unique
                              raw_names.uniq!
                              
                              # Poor man debugging
                              # raw_names.each do |foo|
                              #       puts "#{foo}"
                              # end
              end
        
              def use_yahoo(targetcompany, raw_names, appid)
                      # Search Yahoo's XML service for Linkedin profiles associated with the target company

                      yahoo_regex = '<title>(.*?)\s-.*?<\/title>'
                      
                      print_status("Searching Yahoo! for profiles with associated to #{targetcompany}")
                              
                      response = ""
                      header = { 'User-Agent' => "Lynx/2.8.6rel.5 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.8l"}

                      base_url = "http://boss.yahooapis.com";
                      url = 
"#{base_url}/ysearch/web/v1/site%3Alinkedin.com+#{targetcompany}?appid=#{appid}&format=xml&count=500"
                      
                      # print_status("#{url}")
                      response = Net::HTTP.get_response(URI.parse(url)).body.downcase

                      print_status("Extracting possible usernames from Yahoo search results...")
                      # Take the data in response and send to filter

                      # print "#{response}"
                      response.scan(/#{yahoo_regex}/i) do |t|
                      #       puts "#{t}"
                              raw_names << t
                      end

                      # Clean out the HTML cruft that sneaks passed the regex
                      raw_names.delete_if {|b| b.to_s.include? "<"}
                      raw_names.delete_if {|b| b.to_s.include? "#"}
                      raw_names.delete_if {|b| b.to_s.include? "+"}

                      # Make sure everthing is unique
                      raw_names.uniq!
                      
                      # Poor man debugging
                      # raw_names.each do |foo|
                      #       puts "#{foo}"
                      # end

              end


              #for writing file with all usernames found
              def write_output(data, file_name)
                              usernamefile = datastore['OUTDIR'] + file_name
                
                              ::File.open(usernamefile, "a") do |fd|
                                      fd.write(data)
                              end
              end


              # Finally to the meat of the script.  Start setting up arrays and calling methods
              def run
              
              # Setup our array for all our names
              flast = []
              lastf = []
              firstl = []
              firstlast = []
              fmlast = []
              # Setup our array for temporary storage
              raw_names = []
              
              target = datastore['COMPANY_NAME']
              appid = datastore['YAHOO_APPKEY']
              
              use_google(target, raw_names) if datastore['USE_GOOGLE']
              use_yahoo(target, raw_names, appid) if datastore['USE_YAHOO']
              print_status("Harvesting possible username combinations .....")                                         
                

              name_buster(raw_names, flast, lastf, firstl, firstlast, fmlast)
              
              num_usernames = flast.length() + lastf.length() + firstl.length() + firstlast.length() + fmlast.length()
                              
              print_status("Created #{num_usernames} potential usernames for #{target}")

              if datastore['OUTDIR'] then
                      print_status("Writing username combinations to #{datastore['OUTDIR']}...")
                      file_name = "/flast.lst"
                      write_output(flast.join("\n"), file_name)
                      file_name = "/lastf.lst" 
                      write_output(lastf.join("\n"), file_name)
                      file_name = "/firstl.lst"
                      write_output(firstl.join("\n"), file_name)
                      file_name = "/firstlast.lst"
                      write_output(firstlast.join("\n"), file_name)
                      file_name = "/fmlast.lst"
                      write_output(fmlast.join("\n"), file_name)
              else
                      flast.each do |username|
                              puts "#{username}"
                      end
                      
                      lastf.each do |username|
                              puts "#{username}"
                      end
                      
                      firstl.each do |username|
                              puts "#{username}"
                      end
                      
                      firstlast.each do |username|
                              puts "#{username}"
                      end
                      
                      fmlast.each do |username|
                              puts "#{username}"
                      end
              end

      end

end

_______________________________________________
https://mail.metasploit.com/mailman/listinfo/framework


-- 
Jabra < jabra () spl0it org >
http://www.spl0it.org
_______________________________________________
https://mail.metasploit.com/mailman/listinfo/framework


Current thread: