From d80ee0f427ea64239d85552bd68b8e6b87920f9d Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 22 Jun 2020 10:01:58 -0400 Subject: [PATCH 1/3] WIP: More robust IPV4 validation. --- nosqlmap.py | 45 ++++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/nosqlmap.py b/nosqlmap.py index 1aac75d..585e73b 100755 --- a/nosqlmap.py +++ b/nosqlmap.py @@ -4,6 +4,7 @@ # See the file 'doc/COPYING' for copying permission from exception import NoSQLMapException +from ipaddress import IPv4Address, AddressValueError import sys import nsmcouch import nsmmongo @@ -265,29 +266,39 @@ def options(): notDNS = True victim = raw_input("Enter the host IP/DNS name: ") # make sure we got a valid IP - octets = victim.split(".") + # octets = victim.split(".") - if len(octets) != 4: - # Treat this as a DNS name - optionSet[0] = True + try: + victim = IPv4Address(unicode(victim)) + except AddressValueError as err: notDNS = False - else: - # If len(octets) != 4 is executed the block of code below is also run, but it is not necessary - # If the format of the IP is good, check and make sure the octets are all within acceptable ranges. - for item in octets: - try: - if int(item) < 0 or int(item) > 255: - print "Bad octet in IP address." - goodDigits = False + goodDigits = False + print("[!]", err) - except NoSQLMapException("[!] Must be a DNS name."): - #Must be a DNS name (for now) + # else: + # octets = str(victim.exploded).split(".") - notDNS = False + # if len(octets) != 4: + # # Treat this as a DNS name + # optionSet[0] = True + # notDNS = False + # else: + # If len(octets) != 4 is executed the block of code below is also run, but it is not necessary + # If the format of the IP is good, check and make sure the octets are all within acceptable ranges. + # for item in octets: + # try: + # if int(item) < 0 or int(item) > 255: + # print "Bad octet in IP address." + # goodDigits = False + # + # except NoSQLMapException("[!] Must be a DNS name."): + # #Must be a DNS name (for now) + # + # notDNS = False #If everything checks out set the IP and break the loop - if goodDigits == True or notDNS == False: - print "\nTarget set to " + victim + "\n" + if goodDigits or notDNS is False: + print "\nTarget set to " + victim.exploded + "\n" optionSet[0] = True elif select == "2": From a836a8ace3ea646ce535d5d5f27c641338a87539 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 22 Jun 2020 10:59:26 -0400 Subject: [PATCH 2/3] Using ipaddress from the standard library to validate IPV4 addresses input by the user. --- nosqlmap.py | 75 ++++++++++++++++------------------------------------- 1 file changed, 22 insertions(+), 53 deletions(-) diff --git a/nosqlmap.py b/nosqlmap.py index 585e73b..ade7ab4 100755 --- a/nosqlmap.py +++ b/nosqlmap.py @@ -245,7 +245,7 @@ def options(): print "4-Toggle HTTPS (Current: " + str(https) + ")" print "5-Set " + platform + " Port (Current : " + str(dbPort) + ")" print "6-Set HTTP Request Method (GET/POST) (Current: " + httpMethod + ")" - print "7-Set my local " + platform + "/Shell IP (Current: " + str(myIP) + ")" + print "7-Set my local " + platform + "/Shell IP (Current: " + str(myIP) + ")" print "8-Set shell listener port (Current: " + str(myPort) + ")" print "9-Toggle Verbose Mode: (Current: " + str(verb) + ")" print "0-Load options file" @@ -265,40 +265,21 @@ def options(): goodDigits = True notDNS = True victim = raw_input("Enter the host IP/DNS name: ") - # make sure we got a valid IP - # octets = victim.split(".") + octets = None + # make sure we got a valid IP try: - victim = IPv4Address(unicode(victim)) + octets = IPv4Address(unicode(victim)).exploded except AddressValueError as err: + print("\n[!] Not a valid IP address. Please make another selection or try again.\n{}".format(err.message)) notDNS = False goodDigits = False - print("[!]", err) - - # else: - # octets = str(victim.exploded).split(".") - - # if len(octets) != 4: - # # Treat this as a DNS name - # optionSet[0] = True - # notDNS = False - # else: - # If len(octets) != 4 is executed the block of code below is also run, but it is not necessary - # If the format of the IP is good, check and make sure the octets are all within acceptable ranges. - # for item in octets: - # try: - # if int(item) < 0 or int(item) > 255: - # print "Bad octet in IP address." - # goodDigits = False - # - # except NoSQLMapException("[!] Must be a DNS name."): - # #Must be a DNS name (for now) - # - # notDNS = False + # take the user back to the options dialog + options() #If everything checks out set the IP and break the loop if goodDigits or notDNS is False: - print "\nTarget set to " + victim.exploded + "\n" + print "\nTarget set to " + octets + "\n" optionSet[0] = True elif select == "2": @@ -330,7 +311,6 @@ def options(): https = "OFF" optionSet[8] = True - elif select == "5": dbPort = int(raw_input("Enter target MongoDB port: ")) print "\nTarget Mongo Port set to " + str(dbPort) + "\n" @@ -365,38 +345,26 @@ def options(): optionSet[4] = False while optionSet[4] == False: - goodLen = False + goodLen = True goodDigits = True # Every time when user input Invalid IP, goodLen and goodDigits should be reset. If this is not done, there will be a bug # For example enter 10.0.0.1234 first and the goodLen will be set to True and goodDigits will be set to False # Second step enter 10.0.123, because goodLen has already been set to True, this invalid IP will be put in myIP variables - myIP = raw_input("Enter the host IP for my " + platform +"/Shells: ") - # make sure we got a valid IP - octets = myIP.split(".") - # If there aren't 4 octets, toss an error. - if len(octets) != 4: - print "Invalid IP length." - - else: - goodLen = True - - if goodLen == True: - # If the format of the IP is good, check and make sure the octets are all within acceptable ranges. - for item in octets: - if int(item) < 0 or int(item) > 255: - print "Bad octet in IP address." - goodDigits = False - - # else: - # goodDigits = True - - # Default value of goodDigits should be set to True - # for example 12.12345.12.12 + myIP = raw_input("Enter the host IP for my {}/Shells: ".format(platform)) + octets = None + try: + octets = IPv4Address(unicode(myIP)).exploded + except AddressValueError as err: + print("\n[!] Not a valid IP address. Please make another selection or try again.\n{}".format(err.message)) + goodLen = False + goodDigits = False + # take the user back to the options dialog + options() # If everything checks out set the IP and break the loop - if goodLen == True and goodDigits == True: - print "\nShell/DB listener set to " + myIP + "\n" + if goodLen and goodDigits: + print "\nShell/DB listener set to " + octets + "\n" optionSet[4] = True elif select == "8": @@ -549,6 +517,7 @@ def signal_handler(signal, frame): print "CTRL+C detected. Exiting." sys.exit() + if __name__ == '__main__': parser = build_parser() args = parser.parse_args() From cfcaaeb83fe2c121ab67295b1f9950384f5a7319 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 22 Jun 2020 17:22:30 -0400 Subject: [PATCH 3/3] Attempted fix for issue #105. --- nosqlmap.py | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/nosqlmap.py b/nosqlmap.py index ade7ab4..a7057d0 100755 --- a/nosqlmap.py +++ b/nosqlmap.py @@ -5,6 +5,8 @@ from exception import NoSQLMapException from ipaddress import IPv4Address, AddressValueError +from socket import getfqdn, error as SockError +import re import sys import nsmcouch import nsmmongo @@ -259,27 +261,38 @@ def options(): if select == "1": # Unset the boolean if it's set since we're setting it again. optionSet[0] = False - ipLen = False while optionSet[0] == False: goodDigits = True notDNS = True victim = raw_input("Enter the host IP/DNS name: ") - octets = None - - # make sure we got a valid IP - try: - octets = IPv4Address(unicode(victim)).exploded - except AddressValueError as err: - print("\n[!] Not a valid IP address. Please make another selection or try again.\n{}".format(err.message)) + pattern = re.compile('^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])') + target = None + if re.match(string=victim, pattern=pattern) is None: + print("\n[!] Not a valid hostname or IP address. Please make another selection or try again.\n{}") notDNS = False goodDigits = False # take the user back to the options dialog options() + else: + # make sure we got a valid IP + try: + target = IPv4Address(unicode(victim)).exploded + except AddressValueError: + print("\n[+] Not a valid IP address. Attempting to grab fully qualified domain name...") + try: + target = getfqdn(victim) + print("[+] Target: {}\n".format(target)) + except SockError: + print("[+] Failed to grab FQDN. Please make another selection or try again.\n") + notDNS = False + goodDigits = False + options() + #If everything checks out set the IP and break the loop if goodDigits or notDNS is False: - print "\nTarget set to " + octets + "\n" + print "\nTarget set to " + target + "\n" optionSet[0] = True elif select == "2":