From 4806751470cb186f646335a0c44b4ffdcee1d513 Mon Sep 17 00:00:00 2001 From: csparks Date: Fri, 6 Sep 2019 02:57:53 +0000 Subject: [PATCH 01/10] added option to return linkedin links --- theHarvester/__main__.py | 20 ++++++++++++++++++-- theHarvester/discovery/constants.py | 22 ++++++++++++++++++++++ theHarvester/discovery/linkedinsearch.py | 12 +++++++++++- theHarvester/lib/core.py | 1 + theHarvester/parsers/myparser.py | 13 ++++++++++++- 5 files changed, 64 insertions(+), 4 deletions(-) diff --git a/theHarvester/__main__.py b/theHarvester/__main__.py index 8d87cf47..ebbcdbb5 100644 --- a/theHarvester/__main__.py +++ b/theHarvester/__main__.py @@ -53,9 +53,9 @@ def start(): parser.add_argument('-c', '--dns-brute', help='perform a DNS brute force on the domain', default=False, action='store_true') parser.add_argument('-f', '--filename', help='save the results to an HTML and/or XML file', default='', type=str) parser.add_argument('-b', '--source', help='''baidu, bing, bingapi, censys, crtsh, dnsdumpster, - dogpile, duckduckgo, github-code, google, + dogpile, duckduckgo, github-code, google, hunter, intelx, - linkedin, netcraft, securityTrails, threatcrowd, + linkedin,linkedin_links, netcraft, securityTrails, threatcrowd, trello, twitter, vhost, virustotal, yahoo, all''') parser.add_argument('-x', '--exclude', help='exclude options when using all sources', type=str) args = parser.parse_args() @@ -279,6 +279,22 @@ def start(): for user in sorted(list(set(people))): print(user) + elif engineitem == 'linkedin_links': + print('\033[94m[*] Searching Linkedin. \033[0m') + search = linkedinsearch.SearchLinkedin(word, limit) + search.process() + people = search.get_links() + db = stash.stash_manager() + db.store_all(word, people, 'name', 'linkedin') + + if len(people) == 0: + print('\n[*] No links found Linkedin.\n\n') + else: + print(f'\n[*] Links found: {len(people)}') + print('---------------------') + for user in sorted(list(set(people))): + print(user) + elif engineitem == 'netcraft': print('\033[94m[*] Searching Netcraft. \033[0m') search = netcraft.SearchNetcraft(word) diff --git a/theHarvester/discovery/constants.py b/theHarvester/discovery/constants.py index eeb8dcaf..2be35d84 100644 --- a/theHarvester/discovery/constants.py +++ b/theHarvester/discovery/constants.py @@ -4,6 +4,28 @@ import random googleUA = 'Mozilla/5.0 (Windows NT 6.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1464.0 Safari/537.36' +def splitter(links): + """ + Method that tries to remove duplicates + :param links: list of links to remove duplicates from + :return: unique-ish list + """ + unique_list = [] + name_check = [] + for url in links: + tail = url.split("/")[-1] + if len(tail) == 2 or tail == "zh-cn": + tail = url.split("/")[-2] + name = tail.split("-") + if len(name) > 1: + joined_name = name[0] + name[1] + else: + joined_name = name[0] + if joined_name not in name_check: + unique_list.append(url) + name_check.append(joined_name) + return unique_list + def filter(lst): """ Method that filters list diff --git a/theHarvester/discovery/linkedinsearch.py b/theHarvester/discovery/linkedinsearch.py index d59d14fd..7992200d 100644 --- a/theHarvester/discovery/linkedinsearch.py +++ b/theHarvester/discovery/linkedinsearch.py @@ -4,7 +4,6 @@ from theHarvester.parsers import myparser import requests import time - class SearchLinkedin: def __init__(self, word, limit): @@ -34,9 +33,20 @@ class SearchLinkedin: rawres = myparser.Parser(self.totalresults, self.word) return rawres.people_linkedin() + def get_links(self): + links = myparser.Parser(self.totalresults, self.word) + return splitter(links.links_linkedin()) + + def process(self): while self.counter < self.limit: self.do_search() time.sleep(getDelay()) self.counter += 100 print(f'\tSearching {self.counter} results.') + + + + + + diff --git a/theHarvester/lib/core.py b/theHarvester/lib/core.py index 66a9ef27..40042bbf 100644 --- a/theHarvester/lib/core.py +++ b/theHarvester/lib/core.py @@ -77,6 +77,7 @@ class Core: 'hunter', 'intelx', 'linkedin', + 'linkedin_links', 'netcraft', 'securityTrails', 'threatcrowd', diff --git a/theHarvester/parsers/myparser.py b/theHarvester/parsers/myparser.py index a63b0612..5958c8d9 100644 --- a/theHarvester/parsers/myparser.py +++ b/theHarvester/parsers/myparser.py @@ -92,11 +92,22 @@ class Parser: hostnames = self.unique() return hostnames + def links_linkedin(self): + reg_links = re.compile("url=https:\/\/www.linkedin.com(.*?)&") + self.temp = reg_links.findall(self.results) + resul = [] + for x in self.temp: + y = x.replace("url=", "") + resul.append("https://www.linkedin.com" + y) + return set(resul) + def people_linkedin(self): reg_people = re.compile(r'">[a-zA-Z0-9._ -]* \| LinkedIn') self.temp = reg_people.findall(self.results) resul = [] - for x in self.temp: + + + for x in (self.temp): y = x.replace(' | LinkedIn', '') y = y.replace(' profiles ', '') y = y.replace('LinkedIn', '') From 0e975961f1c01767f6f5fdbb0879ea2756509d4b Mon Sep 17 00:00:00 2001 From: csparks Date: Fri, 6 Sep 2019 03:36:22 +0000 Subject: [PATCH 02/10] fixing unintended code overwrite --- theHarvester/__main__.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/theHarvester/__main__.py b/theHarvester/__main__.py index 3fc442ac..3093c822 100644 --- a/theHarvester/__main__.py +++ b/theHarvester/__main__.py @@ -41,10 +41,6 @@ def start(): trello, twitter, vhost, virustotal, yahoo, all''') parser.add_argument('-x', '--exclude', help='exclude options when using all sources', type=str) - dogpile, duckduckgo, exalead, github-code, google, - hunter, intelx, - linkedin, netcraft, securityTrails, threatcrowd, - trello, twitter, vhost, virustotal, yahoo''') args = parser.parse_args() From 6740f051fc3db8c34786aaf609a2fb0b5c1cd15a Mon Sep 17 00:00:00 2001 From: csparks Date: Fri, 6 Sep 2019 03:46:14 +0000 Subject: [PATCH 03/10] have to remember to fetch, even if its just a week --- theHarvester/__main__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/theHarvester/__main__.py b/theHarvester/__main__.py index 3093c822..af6df831 100644 --- a/theHarvester/__main__.py +++ b/theHarvester/__main__.py @@ -288,6 +288,7 @@ def start(): elif engineitem == 'linkedin_links': print('\033[94m[*] Searching Linkedin. \033[0m') + from theHarvester.discovery import linkedinsearch search = linkedinsearch.SearchLinkedin(word, limit) search.process() people = search.get_links() From 06dbea58d021aa804bc613ef5bdd0c7fa82cf248 Mon Sep 17 00:00:00 2001 From: csparks Date: Fri, 6 Sep 2019 04:00:05 +0000 Subject: [PATCH 04/10] flake8 --- theHarvester/__main__.py | 3 --- theHarvester/discovery/constants.py | 1 + theHarvester/discovery/linkedinsearch.py | 8 +------- theHarvester/parsers/myparser.py | 2 -- 4 files changed, 2 insertions(+), 12 deletions(-) diff --git a/theHarvester/__main__.py b/theHarvester/__main__.py index af6df831..a34e5674 100644 --- a/theHarvester/__main__.py +++ b/theHarvester/__main__.py @@ -34,16 +34,13 @@ def start(): parser.add_argument('-c', '--dns-brute', help='perform a DNS brute force on the domain', default=False, action='store_true') parser.add_argument('-f', '--filename', help='save the results to an HTML and/or XML file', default='', type=str) parser.add_argument('-b', '--source', help='''baidu, bing, bingapi, censys, crtsh, dnsdumpster, - dogpile, duckduckgo, github-code, google, hunter, intelx, linkedin,linkedin_links, netcraft, securityTrails, threatcrowd, trello, twitter, vhost, virustotal, yahoo, all''') parser.add_argument('-x', '--exclude', help='exclude options when using all sources', type=str) - args = parser.parse_args() - try: db = stash.stash_manager() db.do_init() diff --git a/theHarvester/discovery/constants.py b/theHarvester/discovery/constants.py index 69510ad2..5f4c55dd 100644 --- a/theHarvester/discovery/constants.py +++ b/theHarvester/discovery/constants.py @@ -26,6 +26,7 @@ def splitter(links): name_check.append(joined_name) return unique_list + def filter(lst): """ Method that filters list diff --git a/theHarvester/discovery/linkedinsearch.py b/theHarvester/discovery/linkedinsearch.py index 7992200d..ef774df3 100644 --- a/theHarvester/discovery/linkedinsearch.py +++ b/theHarvester/discovery/linkedinsearch.py @@ -4,6 +4,7 @@ from theHarvester.parsers import myparser import requests import time + class SearchLinkedin: def __init__(self, word, limit): @@ -37,16 +38,9 @@ class SearchLinkedin: links = myparser.Parser(self.totalresults, self.word) return splitter(links.links_linkedin()) - def process(self): while self.counter < self.limit: self.do_search() time.sleep(getDelay()) self.counter += 100 print(f'\tSearching {self.counter} results.') - - - - - - diff --git a/theHarvester/parsers/myparser.py b/theHarvester/parsers/myparser.py index b7dd7a46..95b3607b 100644 --- a/theHarvester/parsers/myparser.py +++ b/theHarvester/parsers/myparser.py @@ -90,8 +90,6 @@ class Parser: reg_people = re.compile(r'">[a-zA-Z0-9._ -]* \| LinkedIn') self.temp = reg_people.findall(self.results) resul = [] - - for x in (self.temp): y = x.replace(' | LinkedIn', '') y = y.replace(' profiles ', '') From ef7b2fd1d11d0ab04e18cc19fe63f8b3d784cf18 Mon Sep 17 00:00:00 2001 From: csparks Date: Fri, 6 Sep 2019 04:11:55 +0000 Subject: [PATCH 05/10] invalid escape sequence --- theHarvester/parsers/myparser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/theHarvester/parsers/myparser.py b/theHarvester/parsers/myparser.py index 95b3607b..2fd6f050 100644 --- a/theHarvester/parsers/myparser.py +++ b/theHarvester/parsers/myparser.py @@ -78,7 +78,7 @@ class Parser: return hostnames def links_linkedin(self): - reg_links = re.compile("url=https:\/\/www.linkedin.com(.*?)&") + reg_links = re.compile(r"url=https:\/\/www.linkedin.com(.*?)&") self.temp = reg_links.findall(self.results) resul = [] for x in self.temp: From efa7bf8dab141f28b80cc548f18cde643f6c7bdf Mon Sep 17 00:00:00 2001 From: csparks Date: Sat, 7 Sep 2019 00:32:48 +0000 Subject: [PATCH 06/10] fixed unescaped regex, formatted -b options --- theHarvester/__main__.py | 2 +- theHarvester/parsers/myparser.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/theHarvester/__main__.py b/theHarvester/__main__.py index a34e5674..eefeed22 100644 --- a/theHarvester/__main__.py +++ b/theHarvester/__main__.py @@ -36,7 +36,7 @@ def start(): parser.add_argument('-b', '--source', help='''baidu, bing, bingapi, censys, crtsh, dnsdumpster, dogpile, duckduckgo, github-code, google, hunter, intelx, - linkedin,linkedin_links, netcraft, securityTrails, threatcrowd, + linkedin, linkedin_links, netcraft, securityTrails, threatcrowd, trello, twitter, vhost, virustotal, yahoo, all''') parser.add_argument('-x', '--exclude', help='exclude options when using all sources', type=str) diff --git a/theHarvester/parsers/myparser.py b/theHarvester/parsers/myparser.py index 2fd6f050..09c8f825 100644 --- a/theHarvester/parsers/myparser.py +++ b/theHarvester/parsers/myparser.py @@ -78,7 +78,7 @@ class Parser: return hostnames def links_linkedin(self): - reg_links = re.compile(r"url=https:\/\/www.linkedin.com(.*?)&") + reg_links = re.compile(r"url=https:\/\/www\.linkedin.com(.*?)&") self.temp = reg_links.findall(self.results) resul = [] for x in self.temp: From 88e8e88874b91da229bbde3ab76ff9816a2ac3d1 Mon Sep 17 00:00:00 2001 From: csparks Date: Sat, 7 Sep 2019 02:58:57 +0000 Subject: [PATCH 07/10] added unit test; removed splitter function since regex now handles dupes --- tests/discovery/test_linkedin_links.py | 21 +++++++++++++++++++++ theHarvester/discovery/constants.py | 23 ----------------------- theHarvester/discovery/linkedinsearch.py | 2 +- 3 files changed, 22 insertions(+), 24 deletions(-) create mode 100644 tests/discovery/test_linkedin_links.py diff --git a/tests/discovery/test_linkedin_links.py b/tests/discovery/test_linkedin_links.py new file mode 100644 index 00000000..e03f8860 --- /dev/null +++ b/tests/discovery/test_linkedin_links.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 +# coding=utf-8 +import sys +sys.path.append("../../") +from theHarvester.parsers import myparser +from theHarvester.discovery import linkedinsearch +import pytest +from theHarvester.lib import stash + + +class TestGetLinks(object): + + def test_get_links(self): + search = linkedinsearch.SearchLinkedin("facebook.com", '100') + search.process() + links = search.get_links() + for link in links: + print(link) + +if __name__ == '__main__': + pytest.main() diff --git a/theHarvester/discovery/constants.py b/theHarvester/discovery/constants.py index 5f4c55dd..7549c4c6 100644 --- a/theHarvester/discovery/constants.py +++ b/theHarvester/discovery/constants.py @@ -4,29 +4,6 @@ import random googleUA = 'Mozilla/5.0 (Windows NT 6.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1464.0 Safari/537.36' -def splitter(links): - """ - Method that tries to remove duplicates - :param links: list of links to remove duplicates from - :return: unique-ish list - """ - unique_list = [] - name_check = [] - for url in links: - tail = url.split("/")[-1] - if len(tail) == 2 or tail == "zh-cn": - tail = url.split("/")[-2] - name = tail.split("-") - if len(name) > 1: - joined_name = name[0] + name[1] - else: - joined_name = name[0] - if joined_name not in name_check: - unique_list.append(url) - name_check.append(joined_name) - return unique_list - - def filter(lst): """ Method that filters list diff --git a/theHarvester/discovery/linkedinsearch.py b/theHarvester/discovery/linkedinsearch.py index ef774df3..22a58699 100644 --- a/theHarvester/discovery/linkedinsearch.py +++ b/theHarvester/discovery/linkedinsearch.py @@ -36,7 +36,7 @@ class SearchLinkedin: def get_links(self): links = myparser.Parser(self.totalresults, self.word) - return splitter(links.links_linkedin()) + return links.links_linkedin() def process(self): while self.counter < self.limit: From 7ded50fd95d6cfef2ab4da066cb8eb917ac57041 Mon Sep 17 00:00:00 2001 From: csparks Date: Sat, 7 Sep 2019 03:00:22 +0000 Subject: [PATCH 08/10] removed testing imports --- tests/discovery/test_linkedin_links.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/discovery/test_linkedin_links.py b/tests/discovery/test_linkedin_links.py index e03f8860..b748e77b 100644 --- a/tests/discovery/test_linkedin_links.py +++ b/tests/discovery/test_linkedin_links.py @@ -1,11 +1,9 @@ #!/usr/bin/env python3 # coding=utf-8 -import sys -sys.path.append("../../") from theHarvester.parsers import myparser from theHarvester.discovery import linkedinsearch -import pytest from theHarvester.lib import stash +import pytest class TestGetLinks(object): From b18983fecb8ade833a714788407d1ace1b3e50cb Mon Sep 17 00:00:00 2001 From: csparks Date: Sat, 7 Sep 2019 03:16:56 +0000 Subject: [PATCH 09/10] pylint --- tests/discovery/test_linkedin_links.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/discovery/test_linkedin_links.py b/tests/discovery/test_linkedin_links.py index b748e77b..c1965221 100644 --- a/tests/discovery/test_linkedin_links.py +++ b/tests/discovery/test_linkedin_links.py @@ -1,6 +1,5 @@ #!/usr/bin/env python3 # coding=utf-8 -from theHarvester.parsers import myparser from theHarvester.discovery import linkedinsearch from theHarvester.lib import stash import pytest @@ -8,6 +7,7 @@ import pytest class TestGetLinks(object): + def test_get_links(self): search = linkedinsearch.SearchLinkedin("facebook.com", '100') search.process() From a2a2e197ecab7f3d1829db1cdbc72801e96d39b7 Mon Sep 17 00:00:00 2001 From: csparks Date: Sat, 7 Sep 2019 03:35:59 +0000 Subject: [PATCH 10/10] too many blank lines in test --- tests/discovery/test_linkedin_links.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/discovery/test_linkedin_links.py b/tests/discovery/test_linkedin_links.py index c1965221..2dc6f3dc 100644 --- a/tests/discovery/test_linkedin_links.py +++ b/tests/discovery/test_linkedin_links.py @@ -1,13 +1,11 @@ #!/usr/bin/env python3 # coding=utf-8 from theHarvester.discovery import linkedinsearch -from theHarvester.lib import stash import pytest class TestGetLinks(object): - def test_get_links(self): search = linkedinsearch.SearchLinkedin("facebook.com", '100') search.process() @@ -15,5 +13,6 @@ class TestGetLinks(object): for link in links: print(link) + if __name__ == '__main__': pytest.main()