From ec87d8ebda8a93b20a5de4ff0282d3d5b8252876 Mon Sep 17 00:00:00 2001 From: Miroslav Stampar Date: Mon, 1 Jun 2015 10:45:16 +0200 Subject: [PATCH] Adding a support for SNI (Issue #1256) --- lib/core/option.py | 1 + lib/request/httpshandler.py | 55 ++++++++++++++++++++++++++----------- 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/lib/core/option.py b/lib/core/option.py index 34391841d..df20fdcc8 100644 --- a/lib/core/option.py +++ b/lib/core/option.py @@ -1836,6 +1836,7 @@ def _setKnowledgeBaseAttributes(flushAll=True): kb.safeReq = AttribDict() kb.singleLogFlags = set() kb.reduceTests = None + kb.tlsSNI = None kb.stickyDBMS = False kb.stickyLevel = None kb.storeCrawlingChoice = None diff --git a/lib/request/httpshandler.py b/lib/request/httpshandler.py index 7ea178160..bbd291e15 100644 --- a/lib/request/httpshandler.py +++ b/lib/request/httpshandler.py @@ -7,8 +7,10 @@ See the file 'doc/COPYING' for copying permission import httplib import socket +import sys import urllib2 +from lib.core.data import kb from lib.core.data import logger from lib.core.exception import SqlmapConnectionException @@ -19,7 +21,7 @@ try: except ImportError: pass -_protocols = filter(None, (getattr(ssl, _, None) for _ in ("PROTOCOL_SSLv3", "PROTOCOL_TLSv1", "PROTOCOL_SSLv23", "PROTOCOL_SSLv2"))) +_protocols = filter(None, (getattr(ssl, _, None) for _ in ("PROTOCOL_TLSv1_2", "PROTOCOL_TLSv1_1", "PROTOCOL_TLSv1", "PROTOCOL_SSLv3", "PROTOCOL_SSLv23", "PROTOCOL_SSLv2"))) class HTTPSConnection(httplib.HTTPSConnection): """ @@ -41,21 +43,42 @@ class HTTPSConnection(httplib.HTTPSConnection): success = False - for protocol in _protocols: - try: - sock = create_sock() - _ = ssl.wrap_socket(sock, self.key_file, self.cert_file, ssl_version=protocol) - if _: - success = True - self.sock = _ - _protocols.remove(protocol) - _protocols.insert(0, protocol) - break - else: - sock.close() - except (ssl.SSLError, socket.error, httplib.BadStatusLine), errMsg: - self._tunnel_host = None - logger.debug("SSL connection error occurred ('%s')" % errMsg) + if not kb.tlsSNI: + for protocol in _protocols: + try: + sock = create_sock() + _ = ssl.wrap_socket(sock, self.key_file, self.cert_file, ssl_version=protocol) + if _: + success = True + self.sock = _ + _protocols.remove(protocol) + _protocols.insert(0, protocol) + break + else: + sock.close() + except (ssl.SSLError, socket.error, httplib.BadStatusLine), errMsg: + self._tunnel_host = None + logger.debug("SSL connection error occurred ('%s')" % errMsg) + + # Reference(s): https://docs.python.org/2/library/ssl.html#ssl.SSLContext + # https://www.mnot.net/blog/2014/12/27/python_2_and_tls_sni + if not success and hasattr(ssl, "SSLContext"): + for protocol in filter(lambda _: _ >= ssl.PROTOCOL_TLSv1, _protocols): + try: + sock = create_sock() + context = ssl.SSLContext(protocol) + _ = context.wrap_socket(sock, do_handshake_on_connect=False, server_hostname=self.host) + if _: + kb.tlsSNI = success = True + self.sock = _ + _protocols.remove(protocol) + _protocols.insert(0, protocol) + break + else: + sock.close() + except (ssl.SSLError, socket.error, httplib.BadStatusLine), errMsg: + self._tunnel_host = None + logger.debug("SSL connection error occurred ('%s')" % errMsg) if not success: raise SqlmapConnectionException("can't establish SSL connection")