In this blog post I will show you how to use Pythonect to easily generate potential passwords from LinkedIn public profiles. If you haven't heard about Python:
(1) Find all the employees public LinkedIn profiles → (2) Scrap all the employees public LinkedIn profiles → (3) Crunch all the data into potential passwords
Now that we have the general concept and high-level overview out of the way, let's dive in to the details.
Finding all the employees public LinkedIn profiles will be done via Google Custom Search Engine,: linkedin.com. It's also possible to fine-tune the search results even further, e.g. uk.linkedin.com to find only employees from United Kingdom.
The access to the newly created Google Custom Search Engine will be made using a free API key obtained from Google API Console..
Scraping the profiles is a matter of iterating all over the hCards in all the search-result pages, and extracting the employee name from each hCard. Whats is a hCard? hCard.
Let's see the implementation of the above:
#!/usr/bin/python # # Copyright (C) 2012 Itzik Kotler # # scraper.py is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # scraper scraper.py. If not, see <>. """Simple LinkedIn public profiles scraper that uses Google Custom Search""" import urllib import simplejson BASE_URL = "<YOUR GOOGLE API KEY>&cx=<YOUR GOOGLE SEARCH ENGINE CX>" def __get_all_hcards_from_query(query, index=0, hcards={}): url = query if index != 0: url = url + '&start=%d' % (index) json = simplejson.loads(urllib.urlopen(url).read()) if json.has_key('error'): print "Stopping at %s due to Error!" % (url) print json else: for item in json['items']: try: hcards[item['pagemap']['hcard'][0]['fn']] = item['pagemap']['hcard'][0]['title'] except KeyError as e: pass if json['queries'].has_key('nextPage'): return __get_all_hcards_from_query(query, json['queries']['nextPage'][0]['startIndex'], hcards) return hcards def get_all_employees_by_company_via_linkedin(company): queries = ['"at %s" inurl:"in"', '"at %s" inurl:"pub"'] result = {} for query in queries: _query = query % company result.update(__get_all_hcards_from_query(BASE_URL + '&q=' + _query)) return list(result)Replace <YOUR GOOGLE API KEY> and <YOUR GOOGLE SEARCH ENGINE CX> in the code above with your Google API Key and Google Search Engine CX respectively, save it to a file called scraper.py, and you're ready!
To kick-start, here is a simple program in Pythonect (that utilizes the scraper module) that searchs and prints all the Pythonect company employees full names:
"Pythonect" -> scraper.get_all_employees_by_company_via_linkedin -> printThe output should be:
Itzik KotlerIn my LinkedIn Profile, I have listed Pythonect as a company that I work for, and since no one else is working there, when searching for all the employees of Pythonect company - only my LinkedIn profile comes up.
For demonstration purposes I will keep using this example (i.e. "Pythonect" company, and "Itzik Kotler" employee), but go ahead and replace Pythonect with other, more popular, companies names and see the results.:
"Pythonect" -> scraper.get_all_employees_by_company_via_linkedin -> string.lower(''.join(_.split()))The normalization procedure is short and simple: convert the string to lowercase and remove any spaces, and so the output should be now:
itzikkotlerAs for data manipulation, out of the box (Thanks to The Python Standard Library) we've got itertools and it's combinatoric generators. Let's start by applying itertools.product:
"Pythonect" -> scraper.get_all_employees_by_company_via_linkedin -> string.lower(''.join(_.split())) -> itertools.product(_, repeat=4) -> printThe code above will generate and print every 4 characters password from the letters: i, t, z, k, o, t, l , e, r. However, it won't cover passwords with uppercase letters in it. And so, here's a simple and straightforward implementation of a cycle_uppercase function that cycles the input letters yields a copy of the input with letter in uppercase:
def cycle_uppercase(i): s = ''.join(i) for idx in xrange(0, len(s)): yield s[:idx] + s[idx].upper() + s[idx+1:]To use it, save it to a file called itertools2.py, and then simply add it to the Pythonect program after the itertools.product(_, repeat=4) block, as follows:
"Pythonect" -> scraper.get_all_employees_by_company_via_linkedin \ -> string.lower(''.join(_.split())) \ -> itertools.product(_, repeat=4) \ -> itertools2.cycle_uppercase \ -> printNow,:
[_ + postfix for postfix in ['123','!','$']]To use it, simply add it to the Pythonect program after the itertools2.cycle_uppercase block, as follows:
"Pythonect" -> scraper.get_all_employees_by_company_via_linkedin \ -> string.lower(''.join(_.split())) \ -> itertools.product(_, repeat=4) \ -> itertools2.cycle_uppercase \ -> [_ + postfix for postfix in ['123','!','$']] \ -> printThe result is that now the program adds the strings: '123', '!', and '$' to every generated password, which increases the chances of guessing the user's right password, or not, depends on the password :).