mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2026-06-20 22:49:59 +00:00
110 lines
4.2 KiB
Python
110 lines
4.2 KiB
Python
#!/usr/bin/env python
|
|
|
|
"""
|
|
Copyright (c) 2006-2026 sqlmap developers (https://sqlmap.org)
|
|
See the file 'LICENSE' for copying permission
|
|
|
|
Structural invariants of the injection payload/boundary definitions
|
|
(data/xml/payloads/*.xml -> conf.tests, data/xml/boundaries.xml -> conf.boundaries).
|
|
|
|
These XML files ARE the detection engine: every test/boundary loaded here is
|
|
something sqlmap will fire at a target. The fields are pure data, so the right
|
|
tests are shape/range invariants - a malformed level, an unknown technique, a
|
|
duplicate title, or a test missing its request payload would silently break or
|
|
skew detection.
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import unittest
|
|
|
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
from _testutils import bootstrap
|
|
bootstrap()
|
|
|
|
from lib.parse.payloads import loadBoundaries, loadPayloads
|
|
from lib.core.data import conf
|
|
from lib.core.enums import PAYLOAD
|
|
from lib.core.common import getPublicTypeMembers
|
|
|
|
# load once for the module
|
|
loadBoundaries()
|
|
loadPayloads()
|
|
|
|
TECHNIQUES = set(v for _, v in getPublicTypeMembers(PAYLOAD.TECHNIQUE)) # {1..6}
|
|
WHERES = set(v for _, v in getPublicTypeMembers(PAYLOAD.WHERE)) # {1,2,3}
|
|
|
|
|
|
class TestLoaded(unittest.TestCase):
|
|
# floors well below the current counts (~340 tests, ~54 boundaries) - high enough to catch a
|
|
# truncated/partially-loaded XML set (not just "> 0"), low enough to survive normal additions
|
|
def test_payloads_loaded(self):
|
|
self.assertGreaterEqual(len(conf.tests), 200, msg="only %d tests loaded" % len(conf.tests))
|
|
|
|
def test_boundaries_loaded(self):
|
|
self.assertGreaterEqual(len(conf.boundaries), 30, msg="only %d boundaries loaded" % len(conf.boundaries))
|
|
|
|
|
|
class TestTestEntries(unittest.TestCase):
|
|
def setUp(self):
|
|
# guard against vacuous passes: if payloads failed to load, every loop below
|
|
# would iterate zero times and pass silently
|
|
self.assertTrue(conf.tests, "conf.tests is empty - payloads failed to load")
|
|
|
|
def test_required_fields_present(self):
|
|
for t in conf.tests:
|
|
for field in ("title", "stype", "clause", "where", "level", "risk", "request", "response"):
|
|
self.assertIn(field, t, msg="test %r missing field %r" % (t.get("title"), field))
|
|
|
|
def test_title_non_empty(self):
|
|
for t in conf.tests:
|
|
self.assertTrue(t.title and t.title.strip(), msg="empty test title")
|
|
|
|
def test_titles_unique(self):
|
|
titles = [t.title for t in conf.tests]
|
|
self.assertEqual(len(titles), len(set(titles)), msg="duplicate test titles exist")
|
|
|
|
def test_stype_is_known_technique(self):
|
|
for t in conf.tests:
|
|
self.assertIn(t.stype, TECHNIQUES, msg="test %r has unknown stype %r" % (t.title, t.stype))
|
|
|
|
def test_level_and_risk_in_range(self):
|
|
for t in conf.tests:
|
|
self.assertIn(t.level, (1, 2, 3, 4, 5), msg="test %r bad level %r" % (t.title, t.level))
|
|
self.assertIn(t.risk, (1, 2, 3), msg="test %r bad risk %r" % (t.title, t.risk))
|
|
|
|
def test_request_has_payload(self):
|
|
for t in conf.tests:
|
|
self.assertIn("payload", t.request, msg="test %r request has no payload" % t.title)
|
|
|
|
def test_where_values_valid(self):
|
|
for t in conf.tests:
|
|
for w in t.where:
|
|
self.assertIn(w, WHERES, msg="test %r has bad where %r" % (t.title, w))
|
|
|
|
|
|
class TestBoundaryEntries(unittest.TestCase):
|
|
def setUp(self):
|
|
self.assertTrue(conf.boundaries, "conf.boundaries is empty - boundaries failed to load")
|
|
|
|
def test_required_fields_present(self):
|
|
for b in conf.boundaries:
|
|
for field in ("level", "clause", "where", "ptype"):
|
|
self.assertIn(field, b, msg="boundary missing field %r" % field)
|
|
|
|
def test_level_in_range(self):
|
|
for b in conf.boundaries:
|
|
self.assertIn(b.level, (1, 2, 3, 4, 5), msg="boundary bad level %r" % b.level)
|
|
|
|
def test_where_values_valid(self):
|
|
for b in conf.boundaries:
|
|
for w in b.where:
|
|
self.assertIn(w, WHERES, msg="boundary bad where %r" % w)
|
|
|
|
def test_clause_is_list_like(self):
|
|
for b in conf.boundaries:
|
|
self.assertTrue(isinstance(b.clause, (list, tuple)), msg="boundary clause not list-like")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main(verbosity=2)
|