mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2026-06-29 04:50:58 +00:00
Update of unit tests
This commit is contained in:
parent
b933ff3f63
commit
cb20a446ae
48 changed files with 15116 additions and 190 deletions
175
tests/test_parse_modules.py
Normal file
175
tests/test_parse_modules.py
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2026 sqlmap developers (https://sqlmap.org)
|
||||
See the file 'LICENSE' for copying permission
|
||||
|
||||
Parsers under lib/parse/: DBMS banner fingerprinting (banner.py + the shared
|
||||
FingerprintHandler in handler.py) and the .ini configuration-file reader
|
||||
(configfile.py). These are pure: given a banner string (and the shipped XML
|
||||
signature files) or a config file on disk, they populate kb/conf with no
|
||||
network or DBMS. We drive each over realistic inputs and assert the extracted
|
||||
fingerprint / parsed options.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
from _testutils import bootstrap, set_dbms
|
||||
bootstrap()
|
||||
|
||||
from lib.core.data import kb, conf
|
||||
from lib.core.enums import DBMS
|
||||
from lib.parse.banner import bannerParser, MSSQLBannerHandler
|
||||
from lib.parse.handler import FingerprintHandler
|
||||
|
||||
|
||||
class TestFingerprintHandler(unittest.TestCase):
|
||||
def test_feedinfo_dbms_version_scalar(self):
|
||||
info = {}
|
||||
h = FingerprintHandler("some banner", info)
|
||||
h._feedInfo("dbmsVersion", "5.7.1")
|
||||
self.assertEqual(info["dbmsVersion"], "5.7.1")
|
||||
|
||||
def test_feedinfo_set_valued_keys_split_on_pipe(self):
|
||||
info = {}
|
||||
h = FingerprintHandler("some banner", info)
|
||||
h._feedInfo("type", "Linux|Debian")
|
||||
self.assertIsInstance(info["type"], set)
|
||||
self.assertEqual(info["type"], set(["Linux", "Debian"]))
|
||||
|
||||
def test_feedinfo_ignores_empty_and_none(self):
|
||||
info = {}
|
||||
h = FingerprintHandler("b", info)
|
||||
h._feedInfo("type", "")
|
||||
h._feedInfo("type", "None")
|
||||
h._feedInfo("type", None)
|
||||
self.assertNotIn("type", info)
|
||||
|
||||
|
||||
class TestBannerParser(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self._saved = kb.bannerFp
|
||||
kb.bannerFp = {}
|
||||
|
||||
def tearDown(self):
|
||||
kb.bannerFp = self._saved
|
||||
|
||||
def test_no_dbms_is_noop(self):
|
||||
# without an identified DBMS bannerParser must bail out before touching kb.bannerFp
|
||||
from lib.core.common import Backend
|
||||
Backend.flushForcedDbms(force=True)
|
||||
saved = (conf.get("forceDbms"), kb.get("dbms"))
|
||||
conf.forceDbms = None
|
||||
kb.dbms = None
|
||||
try:
|
||||
kb.bannerFp = {}
|
||||
self.assertIsNone(bannerParser("PostgreSQL 9.5.3 on x86_64-pc-linux-gnu"))
|
||||
# no back-end identified -> the early return leaves the fingerprint untouched
|
||||
self.assertEqual(kb.bannerFp, {})
|
||||
finally:
|
||||
conf.forceDbms, kb.dbms = saved
|
||||
|
||||
def test_mysql_banner_populates_version(self):
|
||||
set_dbms(DBMS.MYSQL)
|
||||
kb.bannerFp = {}
|
||||
bannerParser("5.0.51a-3ubuntu5.4")
|
||||
# the generic signatures classify the OS/distrib from the banner tail
|
||||
self.assertTrue(kb.bannerFp, msg="no fingerprint extracted")
|
||||
self.assertIn("Ubuntu", kb.bannerFp.get("distrib", set()))
|
||||
|
||||
def test_oracle_banner_populates_version(self):
|
||||
set_dbms(DBMS.ORACLE)
|
||||
kb.bannerFp = {}
|
||||
bannerParser("Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production")
|
||||
self.assertIn("dbmsVersion", kb.bannerFp)
|
||||
self.assertTrue(kb.bannerFp["dbmsVersion"].startswith("11.2.0"))
|
||||
|
||||
def test_pgsql_banner_populates_version(self):
|
||||
set_dbms(DBMS.PGSQL)
|
||||
kb.bannerFp = {}
|
||||
# the shipped PostgreSQL signature 'PostgreSQL\s+([\w\.]+)' captures the version
|
||||
bannerParser("PostgreSQL 9.5.3 on x86_64-pc-linux-gnu")
|
||||
self.assertIn("dbmsVersion", kb.bannerFp)
|
||||
self.assertEqual(kb.bannerFp["dbmsVersion"], "9.5.3")
|
||||
|
||||
def test_mssql_banner_populates_release_and_version(self):
|
||||
set_dbms(DBMS.MSSQL)
|
||||
kb.bannerFp = {}
|
||||
# a real SQL Server 2008 RTM build present in data/xml/banner/mssql.xml,
|
||||
# so the MSSQLBannerHandler resolves both the release year and the version
|
||||
bannerParser("Microsoft SQL Server 2008 - 10.00.4311.00")
|
||||
self.assertEqual(kb.bannerFp.get("dbmsRelease"), "2008")
|
||||
self.assertEqual(kb.bannerFp.get("dbmsVersion"), "10.00.4311")
|
||||
|
||||
|
||||
class TestMSSQLBannerHandler(unittest.TestCase):
|
||||
def test_version_alt_built_for_dotzero_form(self):
|
||||
info = {}
|
||||
h = MSSQLBannerHandler("Microsoft SQL Server 10.00.1600.22", info)
|
||||
h.startElement("version", {})
|
||||
h.characters("10.00.1600")
|
||||
h.endElement("version")
|
||||
# endElement('version') derives the "<major>.0.<build>.0" alternate form
|
||||
self.assertEqual(h._versionAlt, "10.0.1600.0")
|
||||
|
||||
|
||||
class _Attrs(dict):
|
||||
"""Minimal SAX-attrs stand-in (supports .get)."""
|
||||
|
||||
|
||||
class TestMSSQLBannerHandlerServicePack(unittest.TestCase):
|
||||
def test_servicepack_strips_spaces(self):
|
||||
info = {}
|
||||
h = MSSQLBannerHandler("banner", info)
|
||||
h.startElement("servicepack", {})
|
||||
h.characters(" 2 ")
|
||||
h.endElement("servicepack")
|
||||
self.assertEqual(h._servicePack, "2")
|
||||
|
||||
|
||||
class TestConfigFileParser(unittest.TestCase):
|
||||
def _write_cfg(self, body):
|
||||
fd, path = tempfile.mkstemp(suffix=".ini", prefix="sqlmapcfg_")
|
||||
os.close(fd)
|
||||
with open(path, "w") as f:
|
||||
f.write(body)
|
||||
return path
|
||||
|
||||
def test_parses_target_and_typed_options(self):
|
||||
from lib.parse.configfile import configFileParser
|
||||
path = self._write_cfg(
|
||||
"[Target]\n"
|
||||
"url = http://config.invalid/?id=1\n"
|
||||
"[Optimization]\n"
|
||||
"threads = 4\n"
|
||||
"[Injection]\n"
|
||||
"tamper = space2comment\n"
|
||||
)
|
||||
saved = {k: conf.get(k) for k in ("url", "threads", "tamper")}
|
||||
try:
|
||||
configFileParser(path)
|
||||
self.assertEqual(conf.url, "http://config.invalid/?id=1")
|
||||
self.assertEqual(conf.threads, 4) # INTEGER datatype coerced
|
||||
self.assertEqual(conf.tamper, "space2comment")
|
||||
finally:
|
||||
for k, v in saved.items():
|
||||
conf[k] = v
|
||||
os.remove(path)
|
||||
|
||||
def test_missing_target_section_raises(self):
|
||||
from lib.parse.configfile import configFileParser
|
||||
from lib.core.exception import SqlmapMissingMandatoryOptionException
|
||||
path = self._write_cfg("[Request]\nthreads = 1\n")
|
||||
try:
|
||||
self.assertRaises(SqlmapMissingMandatoryOptionException,
|
||||
configFileParser, path)
|
||||
finally:
|
||||
os.remove(path)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue