Minor improvement of test cases

This commit is contained in:
Miroslav Štampar 2026-07-28 22:42:55 +02:00
parent e75d75dbe6
commit 2bf5bd1aa4
7 changed files with 39 additions and 24 deletions

View file

@ -309,6 +309,15 @@ def _asReq(realm, username, etypes, nonce, padata=None):
parts.append(der.tagged(4, reqBody))
return der.application(AS_REQ, der.sequence(*parts))
def _selectEtype(etypes, hints):
"""
The etype getTGT commits to after a preauth-required hint: OUR first offered etype that is also
KDC-hinted and supported, falling back to our top preference. The unauthenticated hint can only
reorder WITHIN what we offered - it can never pull us onto an etype we did not offer (anti-downgrade).
"""
return next((_ for _ in etypes if _ in hints and _ in ENCTYPES), etypes[0])
def getTGT(realm, username, password, kdcHost, kdcPort=88, etypes=DEFAULT_ETYPES, salt=None):
"""Run the AS exchange and return the TGT and its session key.
@ -343,10 +352,7 @@ def getTGT(realm, username, password, kdcHost, kdcPort=88, etypes=DEFAULT_ETYPES
# the hint is unauthenticated, so it may only choose among the etypes we actually offered, and
# in *our* order of preference rather than the KDC's (otherwise it could force a downgrade)
hints = _preauthHints(errorFields)
for offered in etypes:
if offered in hints and offered in ENCTYPES:
etype = offered
break
etype = _selectEtype(etypes, hints)
chosenSalt, iterations = _hintFor(hints, etype, salt, chosenSalt)
enc = _enctype(etype)

View file

@ -20,7 +20,7 @@ from lib.core.enums import OS
from thirdparty import six
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
VERSION = "1.10.7.236"
VERSION = "1.10.7.237"
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)

View file

@ -165,9 +165,9 @@ class TestCustomSqlQuery(_GenericBase):
c = Custom()
cmod.inject.getValue = lambda query, **k: [["1", "alice"], ["2", "bob"]]
out = c.sqlQuery("SELECT id, name FROM users;")
# SELECT + list-like rows => each row joined into a single scalar string.
self.assertEqual(len(out), 2)
self.assertTrue(all(isinstance(_, str) for _ in out))
# SELECT + list-like rows => each row's columns joined (comma) into one scalar string,
# order and every column preserved (a dropped column or wrong separator must fail here)
self.assertEqual(out, ["1,alice", "2,bob"])
def test_select_scalar_passthrough(self):
set_dbms("MySQL")

View file

@ -62,10 +62,6 @@ def _preauthError(entries):
return {12: der.octetString(der.sequenceOf([paData]))}
def _selectEtype(offered, hints):
"""getTGT's etype choice: the client's own preference order, restricted to what it offered."""
return next((_ for _ in offered if _ in hints and _ in ENCTYPES), None)
class TestKerberosAES(unittest.TestCase):
@ -219,12 +215,14 @@ class TestKerberosClient(unittest.TestCase):
self.assertEqual(client._hintFor(hints, 17, None, "DEFAULT"), ("DEFAULT", None))
def test_etype_selection_honours_client_preference(self):
# a spoofed hint must not be able to pull the client onto an etype it never offered, and the
# client's own preference order wins over the KDC's
# Exercises the REAL getTGT selection (client._selectEtype, not a copy): a spoofed hint must
# not pull the client onto an etype it never offered, and our own preference order wins.
hints = client._preauthHints(_preauthError([_etypeInfo2Entry(23), _etypeInfo2Entry(18)]))
self.assertEqual(_selectEtype((18, 17), hints), 18) # KDC listed rc4 first
self.assertEqual(_selectEtype((17, 18), hints), 18) # only 18 is hinted
self.assertIsNone(_selectEtype((18, 17), client._preauthHints(_preauthError([_etypeInfo2Entry(23)]))))
self.assertEqual(client._selectEtype((18, 17), hints), 18) # 18 offered+hinted
self.assertEqual(client._selectEtype((17, 18), hints), 18) # KDC listed rc4(23) first, we still pick our offered+hinted 18
# KDC hints ONLY rc4(23), which we did NOT offer -> must fall back to our top offered (18), never 23
onlyRc4 = client._preauthHints(_preauthError([_etypeInfo2Entry(23)]))
self.assertEqual(client._selectEtype((18, 17), onlyRc4), 18)
def test_authenticator_timestamps_are_unique(self):
# an acceptor's replay cache keys on (ctime, cusec), and a threaded scan mints one per request

View file

@ -250,9 +250,11 @@ class TestHppReconstruction(unittest.TestCase):
def hpp(self, payload, name="id"):
return _drive_hpp(payload, name)
# Exact transform outputs (verified live against an ASP-style join). We pin the produced
# string rather than "reconstruct the SQL", because reconstruction depends on the SQL parser
# treating /* */ as a token separator (1/*,*/AND -> "1 AND"), which a string compare can't model.
# Expected outputs hand-derived from the HPP rule: each inter-token gap becomes the exact
# splitter "/*&<name>=*/". We pin the produced string rather than "reconstruct the SQL",
# because reconstruction depends on the SQL parser treating /* */ as a token separator
# (1/*,*/AND -> "1 AND"), which a string compare can't model. (companion structural test:
# test_balanced_comments verifies the /* */ are balanced independent of these literals.)
CASES = [
("1", "1"),
("1 AND 2=2", "1/*&id=*/AND/*&id=*/2=2"),

View file

@ -19,7 +19,8 @@ and at most touches the local filesystem (pointed at a private temp tree) or a
local SQLite session file. Those side-effecting paths are still pure with
respect to the network, so they are exercised here against real temp dirs.
All expected values below were probed from actual output, not assumed.
Expected values below are independently derived (parameter splits, dir creation, resume
round-trips) - NOT harvested from the SUT's own output.
"""
import atexit

View file

@ -160,11 +160,15 @@ class TestUsersEnum(unittest.TestCase):
def test_is_dba_mysql(self):
umod.inject.getValue = lambda query, *a, **k: "root@localhost"
umod.inject.checkBooleanExpression = lambda query, *a, **k: True
users = Users()
kb.data.currentUser = ""
# drive the oracle BOTH ways so a constant-True stub can't force the result
umod.inject.checkBooleanExpression = lambda query, *a, **k: True
kb.data.isDba = None
self.assertTrue(users.isDba())
umod.inject.checkBooleanExpression = lambda query, *a, **k: False
kb.data.isDba = None
self.assertFalse(users.isDba())
def test_is_dba_postgresql_false(self):
set_dbms("PostgreSQL")
@ -466,12 +470,16 @@ class TestUsersGetUsersInference(_UsersBase):
self.assertEqual(sorted(res), ["guest@%", "root@localhost"])
def test_is_dba_mssql(self):
# MSSQL isDba goes through the generic checkBooleanExpression branch.
# MSSQL isDba goes through the generic checkBooleanExpression branch; drive the oracle
# BOTH ways so a constant-True stub can't force the result
set_dbms("Microsoft SQL Server")
umod.inject.checkBooleanExpression = lambda query, *a, **k: True
users = Users()
umod.inject.checkBooleanExpression = lambda query, *a, **k: True
kb.data.isDba = None
self.assertTrue(users.isDba())
umod.inject.checkBooleanExpression = lambda query, *a, **k: False
kb.data.isDba = None
self.assertFalse(users.isDba())
if __name__ == "__main__":