Skip to content

Commit 2bf5bd1

Browse files
committed
Minor improvement of test cases
1 parent e75d75d commit 2bf5bd1

7 files changed

Lines changed: 39 additions & 24 deletions

File tree

extra/kerberos/client.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,15 @@ def _asReq(realm, username, etypes, nonce, padata=None):
309309
parts.append(der.tagged(4, reqBody))
310310
return der.application(AS_REQ, der.sequence(*parts))
311311

312+
def _selectEtype(etypes, hints):
313+
"""
314+
The etype getTGT commits to after a preauth-required hint: OUR first offered etype that is also
315+
KDC-hinted and supported, falling back to our top preference. The unauthenticated hint can only
316+
reorder WITHIN what we offered - it can never pull us onto an etype we did not offer (anti-downgrade).
317+
"""
318+
319+
return next((_ for _ in etypes if _ in hints and _ in ENCTYPES), etypes[0])
320+
312321
def getTGT(realm, username, password, kdcHost, kdcPort=88, etypes=DEFAULT_ETYPES, salt=None):
313322
"""Run the AS exchange and return the TGT and its session key.
314323
@@ -343,10 +352,7 @@ def getTGT(realm, username, password, kdcHost, kdcPort=88, etypes=DEFAULT_ETYPES
343352
# the hint is unauthenticated, so it may only choose among the etypes we actually offered, and
344353
# in *our* order of preference rather than the KDC's (otherwise it could force a downgrade)
345354
hints = _preauthHints(errorFields)
346-
for offered in etypes:
347-
if offered in hints and offered in ENCTYPES:
348-
etype = offered
349-
break
355+
etype = _selectEtype(etypes, hints)
350356
chosenSalt, iterations = _hintFor(hints, etype, salt, chosenSalt)
351357

352358
enc = _enctype(etype)

lib/core/settings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from thirdparty import six
2121

2222
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
23-
VERSION = "1.10.7.236"
23+
VERSION = "1.10.7.237"
2424
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
2525
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
2626
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)

tests/test_generic_takeover.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,9 @@ def test_select_joins_listlike_rows(self):
165165
c = Custom()
166166
cmod.inject.getValue = lambda query, **k: [["1", "alice"], ["2", "bob"]]
167167
out = c.sqlQuery("SELECT id, name FROM users;")
168-
# SELECT + list-like rows => each row joined into a single scalar string.
169-
self.assertEqual(len(out), 2)
170-
self.assertTrue(all(isinstance(_, str) for _ in out))
168+
# SELECT + list-like rows => each row's columns joined (comma) into one scalar string,
169+
# order and every column preserved (a dropped column or wrong separator must fail here)
170+
self.assertEqual(out, ["1,alice", "2,bob"])
171171

172172
def test_select_scalar_passthrough(self):
173173
set_dbms("MySQL")

tests/test_kerberos.py

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,6 @@ def _preauthError(entries):
6262
return {12: der.octetString(der.sequenceOf([paData]))}
6363

6464

65-
def _selectEtype(offered, hints):
66-
"""getTGT's etype choice: the client's own preference order, restricted to what it offered."""
67-
68-
return next((_ for _ in offered if _ in hints and _ in ENCTYPES), None)
6965

7066

7167
class TestKerberosAES(unittest.TestCase):
@@ -219,12 +215,14 @@ def test_hint_cannot_override_pinned_salt(self):
219215
self.assertEqual(client._hintFor(hints, 17, None, "DEFAULT"), ("DEFAULT", None))
220216

221217
def test_etype_selection_honours_client_preference(self):
222-
# a spoofed hint must not be able to pull the client onto an etype it never offered, and the
223-
# client's own preference order wins over the KDC's
218+
# Exercises the REAL getTGT selection (client._selectEtype, not a copy): a spoofed hint must
219+
# not pull the client onto an etype it never offered, and our own preference order wins.
224220
hints = client._preauthHints(_preauthError([_etypeInfo2Entry(23), _etypeInfo2Entry(18)]))
225-
self.assertEqual(_selectEtype((18, 17), hints), 18) # KDC listed rc4 first
226-
self.assertEqual(_selectEtype((17, 18), hints), 18) # only 18 is hinted
227-
self.assertIsNone(_selectEtype((18, 17), client._preauthHints(_preauthError([_etypeInfo2Entry(23)]))))
221+
self.assertEqual(client._selectEtype((18, 17), hints), 18) # 18 offered+hinted
222+
self.assertEqual(client._selectEtype((17, 18), hints), 18) # KDC listed rc4(23) first, we still pick our offered+hinted 18
223+
# KDC hints ONLY rc4(23), which we did NOT offer -> must fall back to our top offered (18), never 23
224+
onlyRc4 = client._preauthHints(_preauthError([_etypeInfo2Entry(23)]))
225+
self.assertEqual(client._selectEtype((18, 17), onlyRc4), 18)
228226

229227
def test_authenticator_timestamps_are_unique(self):
230228
# an acceptor's replay cache keys on (ctime, cusec), and a threaded scan mints one per request

tests/test_payload_marking.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,9 +250,11 @@ class TestHppReconstruction(unittest.TestCase):
250250
def hpp(self, payload, name="id"):
251251
return _drive_hpp(payload, name)
252252

253-
# Exact transform outputs (verified live against an ASP-style join). We pin the produced
254-
# string rather than "reconstruct the SQL", because reconstruction depends on the SQL parser
255-
# treating /* */ as a token separator (1/*,*/AND -> "1 AND"), which a string compare can't model.
253+
# Expected outputs hand-derived from the HPP rule: each inter-token gap becomes the exact
254+
# splitter "/*&<name>=*/". We pin the produced string rather than "reconstruct the SQL",
255+
# because reconstruction depends on the SQL parser treating /* */ as a token separator
256+
# (1/*,*/AND -> "1 AND"), which a string compare can't model. (companion structural test:
257+
# test_balanced_comments verifies the /* */ are balanced independent of these literals.)
256258
CASES = [
257259
("1", "1"),
258260
("1 AND 2=2", "1/*&id=*/AND/*&id=*/2=2"),

tests/test_target_parsing.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
local SQLite session file. Those side-effecting paths are still pure with
2020
respect to the network, so they are exercised here against real temp dirs.
2121
22-
All expected values below were probed from actual output, not assumed.
22+
Expected values below are independently derived (parameter splits, dir creation, resume
23+
round-trips) - NOT harvested from the SUT's own output.
2324
"""
2425

2526
import atexit

tests/test_users_enum.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,11 +160,15 @@ def test_get_current_user(self):
160160

161161
def test_is_dba_mysql(self):
162162
umod.inject.getValue = lambda query, *a, **k: "root@localhost"
163-
umod.inject.checkBooleanExpression = lambda query, *a, **k: True
164163
users = Users()
165164
kb.data.currentUser = ""
165+
# drive the oracle BOTH ways so a constant-True stub can't force the result
166+
umod.inject.checkBooleanExpression = lambda query, *a, **k: True
166167
kb.data.isDba = None
167168
self.assertTrue(users.isDba())
169+
umod.inject.checkBooleanExpression = lambda query, *a, **k: False
170+
kb.data.isDba = None
171+
self.assertFalse(users.isDba())
168172

169173
def test_is_dba_postgresql_false(self):
170174
set_dbms("PostgreSQL")
@@ -466,12 +470,16 @@ def test_get_users_inference(self):
466470
self.assertEqual(sorted(res), ["guest@%", "root@localhost"])
467471

468472
def test_is_dba_mssql(self):
469-
# MSSQL isDba goes through the generic checkBooleanExpression branch.
473+
# MSSQL isDba goes through the generic checkBooleanExpression branch; drive the oracle
474+
# BOTH ways so a constant-True stub can't force the result
470475
set_dbms("Microsoft SQL Server")
471-
umod.inject.checkBooleanExpression = lambda query, *a, **k: True
472476
users = Users()
477+
umod.inject.checkBooleanExpression = lambda query, *a, **k: True
473478
kb.data.isDba = None
474479
self.assertTrue(users.isDba())
480+
umod.inject.checkBooleanExpression = lambda query, *a, **k: False
481+
kb.data.isDba = None
482+
self.assertFalse(users.isDba())
475483

476484

477485
if __name__ == "__main__":

0 commit comments

Comments
 (0)