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:
- Auxiliary Module - Generation of usernames for target company Jason Wood (Jun 16)
- Re: Auxiliary Module - Generation of usernames for target company Jabra (Jun 16)
- Re: Auxiliary Module - Generation of usernames for target company Giorgio Casali (Jun 18)
- Re: Auxiliary Module - Generation of usernames for target company Jabra (Jun 16)