diff --git a/lib/core/option.py b/lib/core/option.py index 04fe07a78..590303f4b 100644 --- a/lib/core/option.py +++ b/lib/core/option.py @@ -67,6 +67,7 @@ from lib.core.update import update from lib.parse.configfile import configFileParser from lib.parse.queriesfile import queriesParser from lib.request.proxy import ProxyHTTPSHandler +from lib.request.certhandler import HTTPSCertAuthHandler from lib.utils.google import Google authHandler = urllib2.BaseHandler() @@ -518,13 +519,14 @@ def __setHTTPProxy(): def __setHTTPAuthentication(): """ - Check and set the HTTP authentication method (Basic, Digest or NTLM), - username and password to perform HTTP requests with. + Check and set the HTTP(s) authentication method (Basic, Digest, NTLM or Certificate), + username and password for first three methods, or key file and certification file for + certificate authentication """ global authHandler - if not conf.aType and not conf.aCred: + if not conf.aType and not conf.aCred and not conf.aCert: return elif conf.aType and not conf.aCred: @@ -537,45 +539,67 @@ def __setHTTPAuthentication(): errMsg += "but did not provide the type" raise sqlmapSyntaxException, errMsg - debugMsg = "setting the HTTP authentication type and credentials" - logger.debug(debugMsg) - - aTypeLower = conf.aType.lower() - - if aTypeLower not in ( "basic", "digest", "ntlm" ): - errMsg = "HTTP authentication type value must be " - errMsg += "Basic, Digest or NTLM" - raise sqlmapSyntaxException, errMsg - - aCredRegExp = re.search("^(.*?)\:(.*?)$", conf.aCred) - - if not aCredRegExp: - errMsg = "HTTP authentication credentials value must be " - errMsg += "in format username:password" - raise sqlmapSyntaxException, errMsg - - authUsername = aCredRegExp.group(1) - authPassword = aCredRegExp.group(2) - - passwordMgr = urllib2.HTTPPasswordMgrWithDefaultRealm() - passwordMgr.add_password(None, "%s://%s" % (conf.scheme, conf.hostname), authUsername, authPassword) - - if aTypeLower == "basic": - authHandler = urllib2.HTTPBasicAuthHandler(passwordMgr) - - elif aTypeLower == "digest": - authHandler = urllib2.HTTPDigestAuthHandler(passwordMgr) - - elif aTypeLower == "ntlm": - try: - from ntlm import HTTPNtlmAuthHandler - except ImportError, _: - errMsg = "sqlmap requires Python NTLM third-party library " - errMsg += "in order to authenticate via NTLM, " - errMsg += "http://code.google.com/p/python-ntlm/" - raise sqlmapMissingDependence, errMsg - - authHandler = HTTPNtlmAuthHandler.HTTPNtlmAuthHandler(passwordMgr) + if not conf.aCert: + debugMsg = "setting the HTTP authentication type and credentials" + logger.debug(debugMsg) + + aTypeLower = conf.aType.lower() + + if aTypeLower not in ( "basic", "digest", "ntlm" ): + errMsg = "HTTP authentication type value must be " + errMsg += "Basic, Digest or NTLM" + raise sqlmapSyntaxException, errMsg + + aCredRegExp = re.search("^(.*?)\:(.*?)$", conf.aCred) + + if not aCredRegExp: + errMsg = "HTTP authentication credentials value must be " + errMsg += "in format username:password" + raise sqlmapSyntaxException, errMsg + + authUsername = aCredRegExp.group(1) + authPassword = aCredRegExp.group(2) + + passwordMgr = urllib2.HTTPPasswordMgrWithDefaultRealm() + passwordMgr.add_password(None, "%s://%s" % (conf.scheme, conf.hostname), authUsername, authPassword) + + if aTypeLower == "basic": + authHandler = urllib2.HTTPBasicAuthHandler(passwordMgr) + + elif aTypeLower == "digest": + authHandler = urllib2.HTTPDigestAuthHandler(passwordMgr) + + elif aTypeLower == "ntlm": + try: + from ntlm import HTTPNtlmAuthHandler + except ImportError, _: + errMsg = "sqlmap requires Python NTLM third-party library " + errMsg += "in order to authenticate via NTLM, " + errMsg += "http://code.google.com/p/python-ntlm/" + raise sqlmapMissingDependence, errMsg + + authHandler = HTTPNtlmAuthHandler.HTTPNtlmAuthHandler(passwordMgr) + else: + debugMsg = "setting the HTTP(s) authentication certificate" + logger.debug(debugMsg) + + aCertRegExp = re.search("^(.+?),\s*(.+?)$", conf.aCert) + + if not aCertRegExp: + errMsg = "HTTP authentication certificate option " + errMsg += "must be in format key_file,cert_file" + raise sqlmapSyntaxException, errMsg + + #os.path.expanduser for support of paths with ~ + key_file = os.path.expanduser(aCertRegExp.group(1)) + cert_file = os.path.expanduser(aCertRegExp.group(2)) + + for file in (key_file, cert_file): + if not os.path.exists(file): + errMsg = "File '%s' doesn't exist" % file + raise sqlmapSyntaxException, errMsg + + authHandler = HTTPSCertAuthHandler(key_file, cert_file) def __setHTTPMethod(): """ diff --git a/lib/core/optiondict.py b/lib/core/optiondict.py index 51286ca1f..c5c4eb0fe 100644 --- a/lib/core/optiondict.py +++ b/lib/core/optiondict.py @@ -41,6 +41,7 @@ optDict = { "headers": "string", "aType": "string", "aCred": "string", + "aCert": "string", "proxy": "string", "threads": "integer", "delay": "float", diff --git a/lib/parse/cmdline.py b/lib/parse/cmdline.py index 75345a05f..ce0fb5115 100644 --- a/lib/parse/cmdline.py +++ b/lib/parse/cmdline.py @@ -95,6 +95,10 @@ def cmdLineParser(): request.add_option("--auth-cred", dest="aCred", help="HTTP Authentication credentials (value " "name:password)") + + request.add_option("--auth-cert", dest="aCert", + help="HTTP(s) Authentication certificate (value " + "key_file,cert_file)") request.add_option("--proxy", dest="proxy", help="Use a HTTP proxy to connect to the target url") diff --git a/lib/request/certhandler.py b/lib/request/certhandler.py index e646e129b..c2c4cf98c 100644 --- a/lib/request/certhandler.py +++ b/lib/request/certhandler.py @@ -22,9 +22,12 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ +import sys import httplib import urllib2 +from lib.core.data import conf + class HTTPSCertAuthHandler(urllib2.HTTPSHandler): def __init__(self, key_file, cert_file): urllib2.HTTPSHandler.__init__(self) @@ -35,4 +38,8 @@ class HTTPSCertAuthHandler(urllib2.HTTPSHandler): return self.do_open(self.getConnection, req) def getConnection(self, host): - return httplib.HTTPSConnection(host, key_file=self.key_file, cert_file=self.cert_file) + if sys.version_info >= (2,6): + retVal = httplib.HTTPSConnection(host, key_file=self.key_file, cert_file=self.cert_file, timeout=conf.timeout) + else: + retVal = httplib.HTTPSConnection(host, key_file=self.key_file, cert_file=self.cert_file) + return retVal diff --git a/sqlmap.conf b/sqlmap.conf index a54abfc11..61ba2dbac 100644 --- a/sqlmap.conf +++ b/sqlmap.conf @@ -65,6 +65,11 @@ aType = # Syntax: username:password aCred = +# HTTP Authentication certificate. Useful only if the target url requires +# logon certificate and you have such data. +# Syntax: key_file,cert_file +aCert = + # Use a HTTP proxy to connect to the target url. # Syntax: http://address:port proxy =