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)
