mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2024-11-27 12:03:49 +03:00
139 lines
5.7 KiB
Python
139 lines
5.7 KiB
Python
#!/usr/bin/env python
|
|
|
|
"""
|
|
Copyright (c) 2006-2024 sqlmap developers (https://sqlmap.org/)
|
|
See the file 'LICENSE' for copying permission
|
|
"""
|
|
|
|
import re
|
|
import socket
|
|
|
|
from lib.core.common import filterNone
|
|
from lib.core.common import getSafeExString
|
|
from lib.core.compat import LooseVersion
|
|
from lib.core.compat import xrange
|
|
from lib.core.data import conf
|
|
from lib.core.data import kb
|
|
from lib.core.data import logger
|
|
from lib.core.exception import SqlmapConnectionException
|
|
from lib.core.settings import PYVERSION
|
|
from thirdparty.six.moves import http_client as _http_client
|
|
from thirdparty.six.moves import urllib as _urllib
|
|
|
|
ssl = None
|
|
try:
|
|
import ssl as _ssl
|
|
ssl = _ssl
|
|
except ImportError:
|
|
pass
|
|
|
|
_protocols = filterNone(getattr(ssl, _, None) for _ in ("PROTOCOL_TLS_CLIENT", "PROTOCOL_TLSv1_2", "PROTOCOL_TLSv1_1", "PROTOCOL_TLSv1", "PROTOCOL_SSLv3", "PROTOCOL_SSLv23", "PROTOCOL_SSLv2"))
|
|
_lut = dict((getattr(ssl, _), _) for _ in dir(ssl) if _.startswith("PROTOCOL_"))
|
|
_contexts = {}
|
|
|
|
class HTTPSConnection(_http_client.HTTPSConnection):
|
|
"""
|
|
Connection class that enables usage of newer SSL protocols.
|
|
|
|
Reference: http://bugs.python.org/msg128686
|
|
|
|
NOTE: use https://check-tls.akamaized.net/ to check if (e.g.) TLS/SNI is working properly
|
|
"""
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
# NOTE: Dirty patch for https://bugs.python.org/issue38251 / https://github.com/sqlmapproject/sqlmap/issues/4158
|
|
if hasattr(ssl, "_create_default_https_context"):
|
|
if None not in _contexts:
|
|
_contexts[None] = ssl._create_default_https_context()
|
|
kwargs["context"] = _contexts[None]
|
|
|
|
self.retrying = False
|
|
|
|
_http_client.HTTPSConnection.__init__(self, *args, **kwargs)
|
|
|
|
def connect(self):
|
|
def create_sock():
|
|
sock = socket.create_connection((self.host, self.port), self.timeout)
|
|
if getattr(self, "_tunnel_host", None):
|
|
self.sock = sock
|
|
self._tunnel()
|
|
return sock
|
|
|
|
success = False
|
|
|
|
# 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 hasattr(ssl, "SSLContext"):
|
|
for protocol in (_ for _ in _protocols if _ >= ssl.PROTOCOL_TLSv1):
|
|
try:
|
|
sock = create_sock()
|
|
if protocol not in _contexts:
|
|
_contexts[protocol] = ssl.SSLContext(protocol)
|
|
|
|
# Disable certificate and hostname validation enabled by default with PROTOCOL_TLS_CLIENT
|
|
_contexts[protocol].check_hostname = False
|
|
_contexts[protocol].verify_mode = ssl.CERT_NONE
|
|
|
|
if getattr(self, "cert_file", None) and getattr(self, "key_file", None):
|
|
_contexts[protocol].load_cert_chain(certfile=self.cert_file, keyfile=self.key_file)
|
|
try:
|
|
# Reference(s): https://askubuntu.com/a/1263098
|
|
# https://askubuntu.com/a/1250807
|
|
_contexts[protocol].set_ciphers("DEFAULT@SECLEVEL=1")
|
|
except (ssl.SSLError, AttributeError):
|
|
pass
|
|
result = _contexts[protocol].wrap_socket(sock, do_handshake_on_connect=True, server_hostname=self.host if re.search(r"\A[\d.]+\Z", self.host or "") is None else None)
|
|
if result:
|
|
success = True
|
|
self.sock = result
|
|
_protocols.remove(protocol)
|
|
_protocols.insert(0, protocol)
|
|
break
|
|
else:
|
|
sock.close()
|
|
except (ssl.SSLError, socket.error, _http_client.BadStatusLine) as ex:
|
|
self._tunnel_host = None
|
|
logger.debug("SSL connection error occurred for '%s' ('%s')" % (_lut[protocol], getSafeExString(ex)))
|
|
|
|
elif hasattr(ssl, "wrap_socket"):
|
|
for protocol in _protocols:
|
|
try:
|
|
sock = create_sock()
|
|
_ = ssl.wrap_socket(sock, keyfile=getattr(self, "key_file"), certfile=getattr(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, _http_client.BadStatusLine) as ex:
|
|
self._tunnel_host = None
|
|
logger.debug("SSL connection error occurred for '%s' ('%s')" % (_lut[protocol], getSafeExString(ex)))
|
|
|
|
if not success:
|
|
errMsg = "can't establish SSL connection"
|
|
# Reference: https://docs.python.org/2/library/ssl.html
|
|
if LooseVersion(PYVERSION) < LooseVersion("2.7.9"):
|
|
errMsg += " (please retry with Python >= 2.7.9)"
|
|
|
|
if kb.sslSuccess and not self.retrying:
|
|
self.retrying = True
|
|
|
|
for _ in xrange(conf.retries):
|
|
try:
|
|
self.connect()
|
|
except SqlmapConnectionException:
|
|
pass
|
|
else:
|
|
return
|
|
|
|
raise SqlmapConnectionException(errMsg)
|
|
else:
|
|
kb.sslSuccess = True
|
|
|
|
class HTTPSHandler(_urllib.request.HTTPSHandler):
|
|
def https_open(self, req):
|
|
return self.do_open(HTTPSConnection if ssl else _http_client.HTTPSConnection, req)
|