From 38c112e0a4f96f5a0e8957c120110b4881edaeee Mon Sep 17 00:00:00 2001 From: linted Date: Wed, 24 Jan 2018 21:51:30 -0500 Subject: [PATCH 01/30] first itteration of new search server --- privcheckerserver.py | 64 +++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/privcheckerserver.py b/privcheckerserver.py index fd6e004..d960e0f 100755 --- a/privcheckerserver.py +++ b/privcheckerserver.py @@ -2,49 +2,57 @@ # server for hosting exploit search try: - from exploitdb import exploitdb -except: - import os - print("-"*80) - print('Submodule not found. Setting up...') - os.system('cd exploitdb; git submodule init; git submodule update') - print("-"*80) - print("Please run again for full functionality.") - exit() -import socketserver + import socketserver + from shutil import which + import argparse + import re + import subprocess +except Exception as e: + print("Caught exception: {}\nAre you running with python3?".format(e)) + exit(1) + _PORT_ = 4521 _IP_ = '0.0.0.0' +_searchsploit = "" class SearchHandler(socketserver.StreamRequestHandler): def handle(self): print('[+] Connection from '+ self.client_address[0]) - data = self.rfile.readline().decode().strip() - while not data == '': - print('[ ] Searching for: ' + data) - output = [ ] - results = self.server.search(data) - for exploits in results: - output.append(exploits[0]['description'] + ' id: ' + exploits[0]['id']) - if len(output) > 0: - print(''.join(output)) - self.wfile.write('\n'.join(output).encode() + b'\n') - data = self.rfile.readline().decode().strip() + output = [] + for data in iter(self.rfile.readline, ''): + term = data.decode().strip() + if not re.search("^[\w\s]+$", term): + continue + + print('[ ] Searching for: ' + term) + proc = subprocess.Popen([_searchsploit, term.split(" ")], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + self.wfile.write(b'{}\n'.format(proc.stdout.read().decode())) print('[-] Closing connection from ' + self.client_address[0]) -class ExploitServer(exploitdb.ExploitSearch, socketserver.ThreadingMixIn, socketserver.TCPServer): - def __init__(self, connectionInfo, handler): - exploitdb.ExploitSearch.__init__(self) - socketserver.TCPServer.__init__(self, connectionInfo, handler) - socketserver.ThreadingMixIn.__init__(self) +class ExploitServer(socketserver.ThreadingMixIn, socketserver.TCPServer): + pass - +def main(): + #parse the args + parser = argparse.ArgumentParser() + parser.add_argument("-i", "--ip", help="Ip to listen on") + parser.add_argument("-p", "--port", help="Port to listen on") + args = parser.parse_args() + if args.ip: + _IP_ = args.ip + if args.port: + _PORT_ = args.port + #make sure we have searchsploit accessable + _searchsploit = which("searchsploit") + if not _searchsploit: + print("Please install searchsploit.\nFor more details visit: https://github.com/offensive-security/exploit-database") + exit(2) -def main(): exploit = ExploitServer((_IP_, _PORT_), SearchHandler) print('[ ] Starting server on port ' + str(_PORT_)) try: From 970dda910679d776b7a18aeb6027b2b4caa95777 Mon Sep 17 00:00:00 2001 From: linted Date: Thu, 25 Jan 2018 20:43:31 -0500 Subject: [PATCH 02/30] fixed global issue and added more to whitelist --- privcheckerserver.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/privcheckerserver.py b/privcheckerserver.py index d960e0f..c523dce 100755 --- a/privcheckerserver.py +++ b/privcheckerserver.py @@ -37,6 +37,8 @@ class ExploitServer(socketserver.ThreadingMixIn, socketserver.TCPServer): def main(): + global _IP_ + global _PORT_ #parse the args parser = argparse.ArgumentParser() parser.add_argument("-i", "--ip", help="Ip to listen on") @@ -63,4 +65,5 @@ def main(): exploit.server_close() if __name__ == "__main__": + print("[ ] Starting up") main() \ No newline at end of file From b28a607c955165348017bac8d01d916b5483fd23 Mon Sep 17 00:00:00 2001 From: linted Date: Thu, 25 Jan 2018 20:44:10 -0500 Subject: [PATCH 03/30] added things missing from last commit --- privcheckerserver.py | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/privcheckerserver.py b/privcheckerserver.py index c523dce..5c49c5e 100755 --- a/privcheckerserver.py +++ b/privcheckerserver.py @@ -22,7 +22,8 @@ def handle(self): output = [] for data in iter(self.rfile.readline, ''): term = data.decode().strip() - if not re.search("^[\w\s]+$", term): + if re.search("^[\w\s\-\+\._]+$", term): + print("[-] recieved search term with invalid characters: {}".format(term)) continue print('[ ] Searching for: ' + term) @@ -37,18 +38,6 @@ class ExploitServer(socketserver.ThreadingMixIn, socketserver.TCPServer): def main(): - global _IP_ - global _PORT_ - #parse the args - parser = argparse.ArgumentParser() - parser.add_argument("-i", "--ip", help="Ip to listen on") - parser.add_argument("-p", "--port", help="Port to listen on") - args = parser.parse_args() - if args.ip: - _IP_ = args.ip - if args.port: - _PORT_ = args.port - #make sure we have searchsploit accessable _searchsploit = which("searchsploit") if not _searchsploit: @@ -65,5 +54,15 @@ def main(): exploit.server_close() if __name__ == "__main__": + #parse the args + parser = argparse.ArgumentParser() + parser.add_argument("-i", "--ip", help="Ip to listen on") + parser.add_argument("-p", "--port", help="Port to listen on") + args = parser.parse_args() + if args.ip: + _IP_ = args.ip + if args.port: + _PORT_ = args.port + print("[ ] Starting up") main() \ No newline at end of file From a62be290fe2fd088bf574f021aaffc6e5436ecf4 Mon Sep 17 00:00:00 2001 From: linted Date: Thu, 25 Jan 2018 20:46:16 -0500 Subject: [PATCH 04/30] added splat of the list to popen --- privcheckerserver.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/privcheckerserver.py b/privcheckerserver.py index 5c49c5e..d2e7fd5 100755 --- a/privcheckerserver.py +++ b/privcheckerserver.py @@ -22,12 +22,12 @@ def handle(self): output = [] for data in iter(self.rfile.readline, ''): term = data.decode().strip() - if re.search("^[\w\s\-\+\._]+$", term): + if re.search("^[\w\s:\-\+\._]+$", term): print("[-] recieved search term with invalid characters: {}".format(term)) continue print('[ ] Searching for: ' + term) - proc = subprocess.Popen([_searchsploit, term.split(" ")], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + proc = subprocess.Popen([_searchsploit, *term.split(" ")], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) self.wfile.write(b'{}\n'.format(proc.stdout.read().decode())) print('[-] Closing connection from ' + self.client_address[0]) From 683015503d5a2881d468bf336f0ab65fe342cee0 Mon Sep 17 00:00:00 2001 From: linted Date: Thu, 25 Jan 2018 21:04:43 -0500 Subject: [PATCH 05/30] changed to cutting down of the version number to see if we get more results --- privcheckerserver.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/privcheckerserver.py b/privcheckerserver.py index d2e7fd5..2d62010 100755 --- a/privcheckerserver.py +++ b/privcheckerserver.py @@ -27,7 +27,9 @@ def handle(self): continue print('[ ] Searching for: ' + term) - proc = subprocess.Popen([_searchsploit, *term.split(" ")], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + splitTerms = term.split(" ") + splitTerms[-1] = splitTerms[-1][:3] #cut down on the last item which should be the version number + proc = subprocess.Popen([_searchsploit, *splitTerms], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) self.wfile.write(b'{}\n'.format(proc.stdout.read().decode())) print('[-] Closing connection from ' + self.client_address[0]) From c72e529567034adff70203e45d6aafcea9404005 Mon Sep 17 00:00:00 2001 From: linted Date: Thu, 25 Jan 2018 21:08:52 -0500 Subject: [PATCH 06/30] added some error handling so the server doesn't die whenever an exception is hit --- privcheckerserver.py | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/privcheckerserver.py b/privcheckerserver.py index 2d62010..68d70fe 100755 --- a/privcheckerserver.py +++ b/privcheckerserver.py @@ -18,20 +18,24 @@ class SearchHandler(socketserver.StreamRequestHandler): def handle(self): - print('[+] Connection from '+ self.client_address[0]) - output = [] - for data in iter(self.rfile.readline, ''): - term = data.decode().strip() - if re.search("^[\w\s:\-\+\._]+$", term): - print("[-] recieved search term with invalid characters: {}".format(term)) - continue + try: + print('[+] Connection from '+ self.client_address[0]) + output = [] + for data in iter(self.rfile.readline, ''): + term = data.decode().strip() + if re.search("^[\w\s:\-\+\._]+$", term): + print("[-] recieved search term with invalid characters: {}".format(term)) + continue - print('[ ] Searching for: ' + term) - splitTerms = term.split(" ") - splitTerms[-1] = splitTerms[-1][:3] #cut down on the last item which should be the version number - proc = subprocess.Popen([_searchsploit, *splitTerms], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - self.wfile.write(b'{}\n'.format(proc.stdout.read().decode())) - print('[-] Closing connection from ' + self.client_address[0]) + print('[ ] Searching for: ' + term) + splitTerms = term.split(" ") + splitTerms[-1] = splitTerms[-1][:3] #cut down on the last item which should be the version number + proc = subprocess.Popen([_searchsploit, *splitTerms], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + self.wfile.write(b'{}\n'.format(proc.stdout.read().decode())) + print('[-] Closing connection from ' + self.client_address[0]) + except Exception as e: + print("[-] Caught exception {}. Closing this connection.".format(e)) + self.wfile.write("[-] Server caught {}. Closing Connection".format(e).decode()) From ed0709db5986e7b315a216af5c5782b7f3f2fe49 Mon Sep 17 00:00:00 2001 From: linted Date: Thu, 25 Jan 2018 21:12:50 -0500 Subject: [PATCH 07/30] Just realized I'm an idiot of changing a string to byteString and back to string before sending it --- privcheckerserver.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/privcheckerserver.py b/privcheckerserver.py index 68d70fe..2515894 100755 --- a/privcheckerserver.py +++ b/privcheckerserver.py @@ -31,11 +31,11 @@ def handle(self): splitTerms = term.split(" ") splitTerms[-1] = splitTerms[-1][:3] #cut down on the last item which should be the version number proc = subprocess.Popen([_searchsploit, *splitTerms], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - self.wfile.write(b'{}\n'.format(proc.stdout.read().decode())) + self.wfile.write('{}\n'.format(proc.stdout.read()) print('[-] Closing connection from ' + self.client_address[0]) except Exception as e: print("[-] Caught exception {}. Closing this connection.".format(e)) - self.wfile.write("[-] Server caught {}. Closing Connection".format(e).decode()) + self.wfile.write("[-] Server caught {}. Closing Connection".format(e)) From 7129bb08abd81c887d6d5595935e8fad2a18b7e3 Mon Sep 17 00:00:00 2001 From: linted Date: Thu, 25 Jan 2018 21:14:35 -0500 Subject: [PATCH 08/30] fixed miss matches ) and added better formating to a print statement --- privcheckerserver.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/privcheckerserver.py b/privcheckerserver.py index 2515894..bfc3410 100755 --- a/privcheckerserver.py +++ b/privcheckerserver.py @@ -31,8 +31,8 @@ def handle(self): splitTerms = term.split(" ") splitTerms[-1] = splitTerms[-1][:3] #cut down on the last item which should be the version number proc = subprocess.Popen([_searchsploit, *splitTerms], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - self.wfile.write('{}\n'.format(proc.stdout.read()) - print('[-] Closing connection from ' + self.client_address[0]) + self.wfile.write('{}\n'.format(proc.stdout.read())) + print('[$] Closing connection from {}\n'.format(self.client_address[0])) except Exception as e: print("[-] Caught exception {}. Closing this connection.".format(e)) self.wfile.write("[-] Server caught {}. Closing Connection".format(e)) From f1112f5d803a2bb32b9627f07112b1e2f3d59a89 Mon Sep 17 00:00:00 2001 From: linted Date: Thu, 25 Jan 2018 21:16:35 -0500 Subject: [PATCH 09/30] I guess it did actually need byte strings and it just lied to me.. --- privcheckerserver.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/privcheckerserver.py b/privcheckerserver.py index bfc3410..b7d3df3 100755 --- a/privcheckerserver.py +++ b/privcheckerserver.py @@ -31,11 +31,11 @@ def handle(self): splitTerms = term.split(" ") splitTerms[-1] = splitTerms[-1][:3] #cut down on the last item which should be the version number proc = subprocess.Popen([_searchsploit, *splitTerms], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - self.wfile.write('{}\n'.format(proc.stdout.read())) + self.wfile.write('{}\n'.format(proc.stdout.read()).encode()) print('[$] Closing connection from {}\n'.format(self.client_address[0])) except Exception as e: print("[-] Caught exception {}. Closing this connection.".format(e)) - self.wfile.write("[-] Server caught {}. Closing Connection".format(e)) + self.wfile.write("[-] Server caught {}. Closing Connection".format(e).encode()) From f98377ede28f0680f0ab97ced8c800f10d7707f9 Mon Sep 17 00:00:00 2001 From: linted Date: Thu, 25 Jan 2018 21:20:39 -0500 Subject: [PATCH 10/30] forgot to switch the logig from black list to whitelist --- privcheckerserver.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/privcheckerserver.py b/privcheckerserver.py index b7d3df3..fe6384e 100755 --- a/privcheckerserver.py +++ b/privcheckerserver.py @@ -23,19 +23,17 @@ def handle(self): output = [] for data in iter(self.rfile.readline, ''): term = data.decode().strip() - if re.search("^[\w\s:\-\+\._]+$", term): + if not re.search("^[\w\s:\-\+\.~_]+$", term): print("[-] recieved search term with invalid characters: {}".format(term)) continue print('[ ] Searching for: ' + term) - splitTerms = term.split(" ") - splitTerms[-1] = splitTerms[-1][:3] #cut down on the last item which should be the version number proc = subprocess.Popen([_searchsploit, *splitTerms], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) self.wfile.write('{}\n'.format(proc.stdout.read()).encode()) print('[$] Closing connection from {}\n'.format(self.client_address[0])) except Exception as e: print("[-] Caught exception {}. Closing this connection.".format(e)) - self.wfile.write("[-] Server caught {}. Closing Connection".format(e).encode()) + self.wfile.write("[-] Server caught {}. Closing Connection\n".format(e).encode()) From 17d166fcb8e74345651a2a0a13428d5cef0928c9 Mon Sep 17 00:00:00 2001 From: linted Date: Thu, 25 Jan 2018 21:28:31 -0500 Subject: [PATCH 11/30] moved searchsploit check to pre-main() and made the search loop cleaner? --- privcheckerserver.py | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/privcheckerserver.py b/privcheckerserver.py index fe6384e..8da3a37 100755 --- a/privcheckerserver.py +++ b/privcheckerserver.py @@ -22,14 +22,17 @@ def handle(self): print('[+] Connection from '+ self.client_address[0]) output = [] for data in iter(self.rfile.readline, ''): - term = data.decode().strip() - if not re.search("^[\w\s:\-\+\.~_]+$", term): - print("[-] recieved search term with invalid characters: {}".format(term)) - continue + term = data.decode().strip().split(" ") + term[-1] = term[-1][:3] #cut down on the last item which should be the version number + for splitTerms in term: + if not re.search("^[\w\s:\-\+\.~_]+$", term): + print("[-] recieved search term with invalid characters: {}".format(term)) + break #bad term break so we don't search it + else: + print('[ ] Searching for: ' + term) + proc = subprocess.Popen([_searchsploit, *splitTerms], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + self.wfile.write('{}\n'.format(proc.stdout.read()).encode()) - print('[ ] Searching for: ' + term) - proc = subprocess.Popen([_searchsploit, *splitTerms], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - self.wfile.write('{}\n'.format(proc.stdout.read()).encode()) print('[$] Closing connection from {}\n'.format(self.client_address[0])) except Exception as e: print("[-] Caught exception {}. Closing this connection.".format(e)) @@ -42,12 +45,6 @@ class ExploitServer(socketserver.ThreadingMixIn, socketserver.TCPServer): def main(): - #make sure we have searchsploit accessable - _searchsploit = which("searchsploit") - if not _searchsploit: - print("Please install searchsploit.\nFor more details visit: https://github.com/offensive-security/exploit-database") - exit(2) - exploit = ExploitServer((_IP_, _PORT_), SearchHandler) print('[ ] Starting server on port ' + str(_PORT_)) try: @@ -68,5 +65,11 @@ def main(): if args.port: _PORT_ = args.port + #make sure we have searchsploit accessable + _searchsploit = which("searchsploit") + if not _searchsploit: + print("Please install searchsploit.\nFor more details visit: https://github.com/offensive-security/exploit-database") + exit(2) + print("[ ] Starting up") main() \ No newline at end of file From 0b5e0003b46ba839db21574ce0f84c980dded6c2 Mon Sep 17 00:00:00 2001 From: linted Date: Thu, 25 Jan 2018 21:32:57 -0500 Subject: [PATCH 12/30] fixed miss used variables --- privcheckerserver.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/privcheckerserver.py b/privcheckerserver.py index 8da3a37..221107f 100755 --- a/privcheckerserver.py +++ b/privcheckerserver.py @@ -25,8 +25,8 @@ def handle(self): term = data.decode().strip().split(" ") term[-1] = term[-1][:3] #cut down on the last item which should be the version number for splitTerms in term: - if not re.search("^[\w\s:\-\+\.~_]+$", term): - print("[-] recieved search term with invalid characters: {}".format(term)) + if not re.search("^[\w\s:\-\+\.~_]+$", splitTerms): + print("[-] recieved search term with invalid characters: {}".format(splitTerms)) break #bad term break so we don't search it else: print('[ ] Searching for: ' + term) From 731cd51afc44286e0740c729446e3bc50367d8c2 Mon Sep 17 00:00:00 2001 From: linted Date: Thu, 25 Jan 2018 21:35:27 -0500 Subject: [PATCH 13/30] fixed trying to concat a list to a string --- privcheckerserver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/privcheckerserver.py b/privcheckerserver.py index 221107f..c4e3d6e 100755 --- a/privcheckerserver.py +++ b/privcheckerserver.py @@ -29,7 +29,7 @@ def handle(self): print("[-] recieved search term with invalid characters: {}".format(splitTerms)) break #bad term break so we don't search it else: - print('[ ] Searching for: ' + term) + print('[ ] Searching for: {}'.format(' '.join(term) proc = subprocess.Popen([_searchsploit, *splitTerms], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) self.wfile.write('{}\n'.format(proc.stdout.read()).encode()) From 1023a3e8bc9e1868fa3b89eddd15e83cf0488630 Mon Sep 17 00:00:00 2001 From: linted Date: Thu, 25 Jan 2018 21:36:25 -0500 Subject: [PATCH 14/30] stupid )'s will be the end of me --- privcheckerserver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/privcheckerserver.py b/privcheckerserver.py index c4e3d6e..35e314b 100755 --- a/privcheckerserver.py +++ b/privcheckerserver.py @@ -29,7 +29,7 @@ def handle(self): print("[-] recieved search term with invalid characters: {}".format(splitTerms)) break #bad term break so we don't search it else: - print('[ ] Searching for: {}'.format(' '.join(term) + print('[ ] Searching for: {}'.format(' '.join(term)) proc = subprocess.Popen([_searchsploit, *splitTerms], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) self.wfile.write('{}\n'.format(proc.stdout.read()).encode()) From 61b18777041d5eeeb6fd90a3b83825e896f5c608 Mon Sep 17 00:00:00 2001 From: linted Date: Thu, 25 Jan 2018 21:36:57 -0500 Subject: [PATCH 15/30] stupid )'s will be the end of me --- privcheckerserver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/privcheckerserver.py b/privcheckerserver.py index 35e314b..aa2ef29 100755 --- a/privcheckerserver.py +++ b/privcheckerserver.py @@ -29,7 +29,7 @@ def handle(self): print("[-] recieved search term with invalid characters: {}".format(splitTerms)) break #bad term break so we don't search it else: - print('[ ] Searching for: {}'.format(' '.join(term)) + print('[ ] Searching for: {}'.format(' '.join(term))) proc = subprocess.Popen([_searchsploit, *splitTerms], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) self.wfile.write('{}\n'.format(proc.stdout.read()).encode()) From 4e75c0ced70b516a7a724799b479e0e08210835f Mon Sep 17 00:00:00 2001 From: linted Date: Thu, 25 Jan 2018 21:54:28 -0500 Subject: [PATCH 16/30] changed to json output of searchsploit and checking it to make sure we got a result before sending it back --- privcheckerserver.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/privcheckerserver.py b/privcheckerserver.py index aa2ef29..9301207 100755 --- a/privcheckerserver.py +++ b/privcheckerserver.py @@ -7,6 +7,7 @@ import argparse import re import subprocess + import json except Exception as e: print("Caught exception: {}\nAre you running with python3?".format(e)) exit(1) @@ -30,8 +31,10 @@ def handle(self): break #bad term break so we don't search it else: print('[ ] Searching for: {}'.format(' '.join(term))) - proc = subprocess.Popen([_searchsploit, *splitTerms], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - self.wfile.write('{}\n'.format(proc.stdout.read()).encode()) + proc = subprocess.Popen([_searchsploit, '-j', *splitTerms], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + output = proc.stdout.read() + if json.loads(output).get("results", False): + self.wfile.write(output.encode()) print('[$] Closing connection from {}\n'.format(self.client_address[0])) except Exception as e: From 20fff39a9d68c77e63f97e2c022f0c088ddda99b Mon Sep 17 00:00:00 2001 From: linted Date: Thu, 25 Jan 2018 22:44:45 -0500 Subject: [PATCH 17/30] fixed miss used variable --- privcheckerserver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/privcheckerserver.py b/privcheckerserver.py index 9301207..fd5a497 100755 --- a/privcheckerserver.py +++ b/privcheckerserver.py @@ -31,7 +31,7 @@ def handle(self): break #bad term break so we don't search it else: print('[ ] Searching for: {}'.format(' '.join(term))) - proc = subprocess.Popen([_searchsploit, '-j', *splitTerms], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + proc = subprocess.Popen([_searchsploit, '-j', *term], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) output = proc.stdout.read() if json.loads(output).get("results", False): self.wfile.write(output.encode()) From 5368ecaf30adec569633f5f39ca1041487ef7f79 Mon Sep 17 00:00:00 2001 From: linted Date: Thu, 25 Jan 2018 23:22:59 -0500 Subject: [PATCH 18/30] changed to a pool of workers to take care of the searching --- privcheckerserver.py | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/privcheckerserver.py b/privcheckerserver.py index fd5a497..046b9c4 100755 --- a/privcheckerserver.py +++ b/privcheckerserver.py @@ -8,6 +8,7 @@ import re import subprocess import json + import multiprocessing except Exception as e: print("Caught exception: {}\nAre you running with python3?".format(e)) exit(1) @@ -21,26 +22,34 @@ class SearchHandler(socketserver.StreamRequestHandler): def handle(self): try: print('[+] Connection from '+ self.client_address[0]) - output = [] - for data in iter(self.rfile.readline, ''): - term = data.decode().strip().split(" ") - term[-1] = term[-1][:3] #cut down on the last item which should be the version number - for splitTerms in term: - if not re.search("^[\w\s:\-\+\.~_]+$", splitTerms): - print("[-] recieved search term with invalid characters: {}".format(splitTerms)) - break #bad term break so we don't search it + p = multiprocessing.Pool(5) + for output in p.imap_unordered(self.search, iter(self.rfile.readline, b'\n')): + if not output[0]: + #error'd out. print the results, but don't send them on? + print(output[1]) + continue + if json.loads(output[1]).get("results", False): + print('[+] Found results for: {}'.format(' '.join(term))) + self.wfile.write(output.encode()) else: - print('[ ] Searching for: {}'.format(' '.join(term))) - proc = subprocess.Popen([_searchsploit, '-j', *term], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - output = proc.stdout.read() - if json.loads(output).get("results", False): - self.wfile.write(output.encode()) + print('[-] No results for: {}'.format(' '.join(term))) print('[$] Closing connection from {}\n'.format(self.client_address[0])) + + def search(data): + try: + term = data.decode().strip().split(" ") + term[-1] = term[-1][:3] #cut down on the last item which should be the version number + for splitTerms in term: + if not re.search("^[\w:\-\+\.~_]+$", splitTerms): + return [False, "[-] recieved search term with invalid characters: {}".format(data.decode().strip())] #bad term return so we don't search it + else: + proc = subprocess.Popen([_searchsploit, '-j', *term], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + output = proc.stdout.read() + return [True, output] + except Exception as e: - print("[-] Caught exception {}. Closing this connection.".format(e)) - self.wfile.write("[-] Server caught {}. Closing Connection\n".format(e).encode()) - + return [False, "[-] ".format(e)] class ExploitServer(socketserver.ThreadingMixIn, socketserver.TCPServer): From c31064ae7bf047deced8fdde90a2a4c614514b9b Mon Sep 17 00:00:00 2001 From: linted Date: Thu, 25 Jan 2018 23:27:04 -0500 Subject: [PATCH 19/30] fixed missing except --- privcheckerserver.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/privcheckerserver.py b/privcheckerserver.py index 046b9c4..6f9e59c 100755 --- a/privcheckerserver.py +++ b/privcheckerserver.py @@ -35,6 +35,9 @@ def handle(self): print('[-] No results for: {}'.format(' '.join(term))) print('[$] Closing connection from {}\n'.format(self.client_address[0])) + except Exception as e: + self.wfile.write(b'{{"SEARCH":"ERROR", "RESULTS":"{}"}}'.format(e)) + print("[-] Exception Caught: {}".format(e)) def search(data): try: From 30572924a7af6c45a0733f04fa53a097026bfa79 Mon Sep 17 00:00:00 2001 From: linted Date: Thu, 25 Jan 2018 23:30:57 -0500 Subject: [PATCH 20/30] Trying another way to pass this iterable to be pickled --- privcheckerserver.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/privcheckerserver.py b/privcheckerserver.py index 6f9e59c..9a5681d 100755 --- a/privcheckerserver.py +++ b/privcheckerserver.py @@ -23,7 +23,7 @@ def handle(self): try: print('[+] Connection from '+ self.client_address[0]) p = multiprocessing.Pool(5) - for output in p.imap_unordered(self.search, iter(self.rfile.readline, b'\n')): + for output in p.imap_unordered(self.search, iter(str(self.rfile.readline), '\n')): if not output[0]: #error'd out. print the results, but don't send them on? print(output[1]) @@ -36,7 +36,7 @@ def handle(self): print('[$] Closing connection from {}\n'.format(self.client_address[0])) except Exception as e: - self.wfile.write(b'{{"SEARCH":"ERROR", "RESULTS":"{}"}}'.format(e)) + self.wfile.write('{{"SEARCH":"ERROR", "RESULTS":"{}"}}'.format(e).decode()) print("[-] Exception Caught: {}".format(e)) def search(data): From 8fa10a4f0185ded749abcf353f99acc5e502d511 Mon Sep 17 00:00:00 2001 From: linted Date: Thu, 25 Jan 2018 23:33:54 -0500 Subject: [PATCH 21/30] added proper termination of the pool --- privcheckerserver.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/privcheckerserver.py b/privcheckerserver.py index 9a5681d..6d3889e 100755 --- a/privcheckerserver.py +++ b/privcheckerserver.py @@ -22,7 +22,7 @@ class SearchHandler(socketserver.StreamRequestHandler): def handle(self): try: print('[+] Connection from '+ self.client_address[0]) - p = multiprocessing.Pool(5) + self.pool = multiprocessing.Pool(5) for output in p.imap_unordered(self.search, iter(str(self.rfile.readline), '\n')): if not output[0]: #error'd out. print the results, but don't send them on? @@ -34,10 +34,14 @@ def handle(self): else: print('[-] No results for: {}'.format(' '.join(term))) + self.pool.close() + self.pool.join() print('[$] Closing connection from {}\n'.format(self.client_address[0])) except Exception as e: - self.wfile.write('{{"SEARCH":"ERROR", "RESULTS":"{}"}}'.format(e).decode()) + self.pool.terminate() + self.wfile.write('{{"SEARCH":"ERROR", "RESULTS":"{}"}}'.format(e).encode()) print("[-] Exception Caught: {}".format(e)) + self.pool.join() def search(data): try: From 82dc7c770e618e06a7a7e5d4cb8ff6147864e79c Mon Sep 17 00:00:00 2001 From: linted Date: Thu, 25 Jan 2018 23:35:04 -0500 Subject: [PATCH 22/30] fixed miss named var --- privcheckerserver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/privcheckerserver.py b/privcheckerserver.py index 6d3889e..f297f7d 100755 --- a/privcheckerserver.py +++ b/privcheckerserver.py @@ -23,7 +23,7 @@ def handle(self): try: print('[+] Connection from '+ self.client_address[0]) self.pool = multiprocessing.Pool(5) - for output in p.imap_unordered(self.search, iter(str(self.rfile.readline), '\n')): + for output in self.pool.imap_unordered(self.search, iter(str(self.rfile.readline), '\n')): if not output[0]: #error'd out. print the results, but don't send them on? print(output[1]) From cf0aea6c2ce629fb92257bc3e9d8f8c9ff190541 Mon Sep 17 00:00:00 2001 From: linted Date: Fri, 26 Jan 2018 00:53:40 -0500 Subject: [PATCH 23/30] got pools working --- privcheckerserver.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/privcheckerserver.py b/privcheckerserver.py index f297f7d..b567d4c 100755 --- a/privcheckerserver.py +++ b/privcheckerserver.py @@ -22,17 +22,18 @@ class SearchHandler(socketserver.StreamRequestHandler): def handle(self): try: print('[+] Connection from '+ self.client_address[0]) - self.pool = multiprocessing.Pool(5) - for output in self.pool.imap_unordered(self.search, iter(str(self.rfile.readline), '\n')): + self.pool = multiprocessing.Pool(10) + for output in self.pool.imap(SearchHandler.search, iter(self.rfile.readline, b'\n'), 5): if not output[0]: #error'd out. print the results, but don't send them on? print(output[1]) continue - if json.loads(output[1]).get("results", False): - print('[+] Found results for: {}'.format(' '.join(term))) + jsonOutput = json.loads(output[1]) + if jsonOutput.get("results", False): + print('[+] Found results for: {}'.format(jsonOutput.get("SEARCH", output))) self.wfile.write(output.encode()) else: - print('[-] No results for: {}'.format(' '.join(term))) + print('[-] No results for: {}'.format(jsonOutput.get("SEARCH", output))) self.pool.close() self.pool.join() @@ -43,7 +44,8 @@ def handle(self): print("[-] Exception Caught: {}".format(e)) self.pool.join() - def search(data): + @classmethod + def search(cls, data): try: term = data.decode().strip().split(" ") term[-1] = term[-1][:3] #cut down on the last item which should be the version number @@ -54,11 +56,12 @@ def search(data): proc = subprocess.Popen([_searchsploit, '-j', *term], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) output = proc.stdout.read() return [True, output] - + except Exception as e: return [False, "[-] ".format(e)] + class ExploitServer(socketserver.ThreadingMixIn, socketserver.TCPServer): pass From 7203d23dcedfb681c5b9e45db3e0ac9841e57100 Mon Sep 17 00:00:00 2001 From: linted Date: Sat, 27 Jan 2018 21:12:55 -0500 Subject: [PATCH 24/30] moved away from using searchsploit and started parsing the csv on our own --- privcheckerserver.py | 69 ++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/privcheckerserver.py b/privcheckerserver.py index b567d4c..5a43645 100755 --- a/privcheckerserver.py +++ b/privcheckerserver.py @@ -3,12 +3,10 @@ try: import socketserver - from shutil import which + from os.path import isfile import argparse - import re - import subprocess - import json import multiprocessing + from csv import DictReader except Exception as e: print("Caught exception: {}\nAre you running with python3?".format(e)) exit(1) @@ -16,24 +14,18 @@ _PORT_ = 4521 _IP_ = '0.0.0.0' -_searchsploit = "" +_SEARCHSPLOIT_ = "/usr/share/exploitdb/files_exploits.csv" class SearchHandler(socketserver.StreamRequestHandler): def handle(self): try: print('[+] Connection from '+ self.client_address[0]) self.pool = multiprocessing.Pool(10) - for output in self.pool.imap(SearchHandler.search, iter(self.rfile.readline, b'\n'), 5): - if not output[0]: - #error'd out. print the results, but don't send them on? - print(output[1]) - continue - jsonOutput = json.loads(output[1]) - if jsonOutput.get("results", False): - print('[+] Found results for: {}'.format(jsonOutput.get("SEARCH", output))) + for output in self.pool.imap(SearchHandler.search, iter(self.rfile.readline, b'\n')): + if output: + print(output) self.wfile.write(output.encode()) - else: - print('[-] No results for: {}'.format(jsonOutput.get("SEARCH", output))) + self.pool.close() self.pool.join() @@ -46,24 +38,19 @@ def handle(self): @classmethod def search(cls, data): - try: - term = data.decode().strip().split(" ") - term[-1] = term[-1][:3] #cut down on the last item which should be the version number - for splitTerms in term: - if not re.search("^[\w:\-\+\.~_]+$", splitTerms): - return [False, "[-] recieved search term with invalid characters: {}".format(data.decode().strip())] #bad term return so we don't search it - else: - proc = subprocess.Popen([_searchsploit, '-j', *term], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - output = proc.stdout.read() - return [True, output] - - except Exception as e: - return [False, "[-] ".format(e)] + query = data.decode().strip().split(" ") + query[-1] = query[-1][:3] #cut down on the last item which should be the version number + output = ["[ ]" + data] + for rows in ExploitServer.exploitDatabase: + if all([term in rows["description"] for term in query]): + output.append('\t | '.join(rows["description"], rows["file"])) + if output: + return "\n".join(output) class ExploitServer(socketserver.ThreadingMixIn, socketserver.TCPServer): - pass + exploitDatabase = [] def main(): @@ -79,19 +66,31 @@ def main(): if __name__ == "__main__": #parse the args parser = argparse.ArgumentParser() - parser.add_argument("-i", "--ip", help="Ip to listen on") - parser.add_argument("-p", "--port", help="Port to listen on") + parser.add_argument("-i", "--ip", help="Ip to listen on", required=True) + parser.add_argument("-p", "--port", help="Port to listen on", required=True) + parser.add_argument("-f", "--file", help="The exploit csv to use") args = parser.parse_args() if args.ip: _IP_ = args.ip if args.port: _PORT_ = args.port + if args.file: + _SEARCHSPLOIT_ = args.file - #make sure we have searchsploit accessable - _searchsploit = which("searchsploit") - if not _searchsploit: - print("Please install searchsploit.\nFor more details visit: https://github.com/offensive-security/exploit-database") + if not isfile(_SEARCHSPLOIT_): + print("[-] Cannot find csv databse: {}\nFor more details visit: https://github.com/offensive-security/exploit-database".format(_SEARCHSPLOIT_)) exit(2) + #parse the exploit database and collect all the results + try: + with open(_SEARCHSPLOIT_) as Fin: + reader = DictReader(Fin) + for lines in reader: + #add the database to the exploit server for non global persistance... or maybe it is technically still global? + ExploitServer.exploitDatabase.append(lines) + except Exception as e: + print("[-] Exception caught while attempting to parse database file. {}".format(e)) + exit(3) + print("[ ] Starting up") main() \ No newline at end of file From 0c77ce8e2dc0cb64628483dd8685f74a6d6e3fc1 Mon Sep 17 00:00:00 2001 From: linted Date: Sat, 27 Jan 2018 21:14:30 -0500 Subject: [PATCH 25/30] removed the required ip and port, that was a dumb idea and i regreted it instantly --- privcheckerserver.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/privcheckerserver.py b/privcheckerserver.py index 5a43645..e0986f0 100755 --- a/privcheckerserver.py +++ b/privcheckerserver.py @@ -26,10 +26,9 @@ def handle(self): print(output) self.wfile.write(output.encode()) - self.pool.close() - self.pool.join() print('[$] Closing connection from {}\n'.format(self.client_address[0])) + self.pool.join() except Exception as e: self.pool.terminate() self.wfile.write('{{"SEARCH":"ERROR", "RESULTS":"{}"}}'.format(e).encode()) @@ -66,8 +65,8 @@ def main(): if __name__ == "__main__": #parse the args parser = argparse.ArgumentParser() - parser.add_argument("-i", "--ip", help="Ip to listen on", required=True) - parser.add_argument("-p", "--port", help="Port to listen on", required=True) + parser.add_argument("-i", "--ip", help="Ip to listen on") + parser.add_argument("-p", "--port", help="Port to listen on") parser.add_argument("-f", "--file", help="The exploit csv to use") args = parser.parse_args() if args.ip: From c36bfde66b3cb949553e70419a869aca0d543853 Mon Sep 17 00:00:00 2001 From: linted Date: Sat, 27 Jan 2018 21:38:10 -0500 Subject: [PATCH 26/30] added a new line after every output, and moved the section header to after we check if we got results --- privcheckerserver.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/privcheckerserver.py b/privcheckerserver.py index e0986f0..f13193b 100755 --- a/privcheckerserver.py +++ b/privcheckerserver.py @@ -24,7 +24,7 @@ def handle(self): for output in self.pool.imap(SearchHandler.search, iter(self.rfile.readline, b'\n')): if output: print(output) - self.wfile.write(output.encode()) + self.wfile.write(output.encode() + b'\n') self.pool.close() print('[$] Closing connection from {}\n'.format(self.client_address[0])) @@ -39,12 +39,12 @@ def handle(self): def search(cls, data): query = data.decode().strip().split(" ") query[-1] = query[-1][:3] #cut down on the last item which should be the version number - output = ["[ ]" + data] + output = [] for rows in ExploitServer.exploitDatabase: if all([term in rows["description"] for term in query]): - output.append('\t | '.join(rows["description"], rows["file"])) + output.append('\t'.join((rows["description"], rows["file"])) if output: - return "\n".join(output) + return "\n".join(("[ ] " + query, *output) From 1d2c8e93a9d6a0162fc536dae69fedae76f699b6 Mon Sep 17 00:00:00 2001 From: linted Date: Sat, 27 Jan 2018 21:40:00 -0500 Subject: [PATCH 27/30] One day I will eradicate the world of the ). I will destroy them so that no one will ever have to experience the terrible feeling of forgeting one ever again. --- privcheckerserver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/privcheckerserver.py b/privcheckerserver.py index f13193b..4e23aa0 100755 --- a/privcheckerserver.py +++ b/privcheckerserver.py @@ -42,7 +42,7 @@ def search(cls, data): output = [] for rows in ExploitServer.exploitDatabase: if all([term in rows["description"] for term in query]): - output.append('\t'.join((rows["description"], rows["file"])) + output.append('\t'.join((rows["description"], rows["file"]))) if output: return "\n".join(("[ ] " + query, *output) From 4678dd8f1a5000852144ab17370b76b26782bd80 Mon Sep 17 00:00:00 2001 From: linted Date: Sat, 27 Jan 2018 21:40:50 -0500 Subject: [PATCH 28/30] Today is not that day --- privcheckerserver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/privcheckerserver.py b/privcheckerserver.py index 4e23aa0..8274f14 100755 --- a/privcheckerserver.py +++ b/privcheckerserver.py @@ -44,7 +44,7 @@ def search(cls, data): if all([term in rows["description"] for term in query]): output.append('\t'.join((rows["description"], rows["file"]))) if output: - return "\n".join(("[ ] " + query, *output) + return "\n".join(("[ ] " + query, *output)) From 3437cf5c7f0cb8c8f5d0d1cffdb959559211a200 Mon Sep 17 00:00:00 2001 From: linted Date: Sat, 27 Jan 2018 21:45:44 -0500 Subject: [PATCH 29/30] forgot to rejoin the query --- privcheckerserver.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/privcheckerserver.py b/privcheckerserver.py index 8274f14..47f6fc4 100755 --- a/privcheckerserver.py +++ b/privcheckerserver.py @@ -31,7 +31,7 @@ def handle(self): self.pool.join() except Exception as e: self.pool.terminate() - self.wfile.write('{{"SEARCH":"ERROR", "RESULTS":"{}"}}'.format(e).encode()) + self.wfile.write('[-] Exception Caught: {}'.format(e).encode()) print("[-] Exception Caught: {}".format(e)) self.pool.join() @@ -44,7 +44,7 @@ def search(cls, data): if all([term in rows["description"] for term in query]): output.append('\t'.join((rows["description"], rows["file"]))) if output: - return "\n".join(("[ ] " + query, *output)) + return "[ ] " + "\n".join([' '.join(query), *output]) From 9e02bf2d6615548e6d9a02f573fdd6f9085da560 Mon Sep 17 00:00:00 2001 From: linted Date: Sat, 27 Jan 2018 21:54:13 -0500 Subject: [PATCH 30/30] removed submodule dependency --- .gitmodules | 3 --- exploitdb | 1 - 2 files changed, 4 deletions(-) delete mode 160000 exploitdb diff --git a/.gitmodules b/.gitmodules index 8ddf22b..e69de29 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "exploitdb"] - path = exploitdb - url = https://github.com/mattoufoutu/exploitdb.git diff --git a/exploitdb b/exploitdb deleted file mode 160000 index 52f8986..0000000 --- a/exploitdb +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 52f898600a05025f8fd02d28936a5b9c1a5e45a1