This commit is contained in:
Miroslav Štampar
2026-10-21 13:51:35 +02:00
parent 5b8a2faab1
commit 11afdcb026
3 changed files with 113 additions and 2 deletions
+1 -1
View File
@@ -19,7 +19,7 @@ from lib.core.enums import OS
from thirdparty import six
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
VERSION = "1.10.10.17"
VERSION = "1.10.10.18"
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)
+3 -1
View File
@@ -28,6 +28,8 @@ 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"))
# Note: SNI (i.e. server_hostname) is a TLS extension, hence only those are used in here (Note: PROTOCOL_TLSv1 is not compiled in on OpenSSL builds without TLS 1.0 support)
_tlsProtocols = filterNone(getattr(ssl, _, None) for _ in ("PROTOCOL_TLS_CLIENT", "PROTOCOL_TLSv1_2", "PROTOCOL_TLSv1_1", "PROTOCOL_TLSv1"))
_lut = dict((getattr(ssl, _), _) for _ in dir(ssl) if _.startswith("PROTOCOL_"))
_contexts = {}
@@ -64,7 +66,7 @@ class HTTPSConnection(_http_client.HTTPSConnection):
# 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):
for protocol in (_ for _ in _protocols if _ in _tlsProtocols):
sock = None
try:
sock = create_sock()
+109
View File
@@ -0,0 +1,109 @@
#!/usr/bin/env python
"""
Copyright (c) 2006-2026 sqlmap developers (https://sqlmap.org)
See the file 'LICENSE' for copying permission
Unit tests for lib/request/httpshandler.py, exercising the SSL protocol
candidate selection.
No network is involved: the module is reimported with chosen ssl.PROTOCOL_*
constants removed, mimicking OpenSSL builds that have those protocol versions
compiled out (e.g. OPENSSL_NO_TLS1), as the constants are conditional there.
"""
import os
import ssl
import sys
import unittest
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from _testutils import bootstrap
bootstrap()
from lib.core.data import conf
import lib.request.httpshandler as hmod
from thirdparty.six.moves import reload_module as _reload_module
class TestProtocolSelection(unittest.TestCase):
def tearDown(self):
hmod.socket.create_connection = self._createConnection
hmod.ssl.SSLContext = self._sslContext
hmod._contexts.clear()
for name, value in self._removed.items():
setattr(ssl, name, value)
_reload_module(hmod)
def _reload_without(self, *names):
"""Reloads the module with `names` missing from ssl (as on builds lacking those protocols)"""
self._removed = {}
self._createConnection = hmod.socket.create_connection
self._sslContext = hmod.ssl.SSLContext
for name in names:
if hasattr(ssl, name):
self._removed[name] = getattr(ssl, name)
delattr(ssl, name)
_reload_module(hmod)
return [hmod._lut.get(_, _) for _ in hmod._protocols if _ in hmod._tlsProtocols]
def test_only_tls_protocols_are_used_with_sni(self):
# Note: SSL era protocols stay in _protocols for the non-SNI fallback, but carry no server_hostname
selected = self._reload_without()
self.assertTrue(selected)
for name in ("PROTOCOL_SSLv3", "PROTOCOL_SSLv23", "PROTOCOL_SSLv2"):
if hasattr(ssl, name):
self.assertIn(getattr(ssl, name), hmod._protocols)
self.assertNotIn(getattr(ssl, name), hmod._tlsProtocols)
def test_missing_tlsv1_does_not_raise(self):
# Note: ssl.PROTOCOL_TLSv1 is compiled in only '#ifndef OPENSSL_NO_TLS1' (used to raise an AttributeError here)
selected = self._reload_without("PROTOCOL_TLSv1")
self.assertTrue(selected)
self.assertNotIn("PROTOCOL_TLSv1", selected)
def test_missing_all_legacy_tls_does_not_raise(self):
selected = self._reload_without("PROTOCOL_TLSv1", "PROTOCOL_TLSv1_1")
self.assertTrue(selected)
self.assertNotIn("PROTOCOL_TLSv1_1", selected)
def test_connect_without_tlsv1(self):
"""Drives the real connect() loop, which used to reference ssl.PROTOCOL_TLSv1 directly"""
selected = self._reload_without("PROTOCOL_TLSv1")
conf.host = None
conf.httpHeaders = []
class _Context(object):
def __init__(self, protocol):
self.protocol = protocol
def set_ciphers(self, _):
pass
def wrap_socket(self, sock, **kwargs):
return "wrapped:%s" % hmod._lut.get(self.protocol, self.protocol)
connection = hmod.HTTPSConnection("example.com", 443)
# Note: stubbed only after the instantiation, as that one resolves the default context through ssl itself
hmod.socket.create_connection = lambda *args, **kwargs: _Socket()
hmod.ssl.SSLContext = _Context
hmod._contexts.clear()
connection.connect()
self.assertEqual(connection.sock, "wrapped:%s" % selected[0])
class _Socket(object):
def close(self):
pass
if __name__ == "__main__":
unittest.main()