From ab1efed0d5eebd9c3e539c043afc21ebaf10a9e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0tampar?= Date: Wed, 10 Jun 2026 18:37:46 +0200 Subject: [PATCH] Harden REST API option handling and require authentication credentials (#6073) --- data/txt/sha256sums.txt | 6 +++--- lib/core/settings.py | 2 +- lib/utils/api.py | 8 ++++++++ sqlmapapi.py | 7 +++++-- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/data/txt/sha256sums.txt b/data/txt/sha256sums.txt index 779f5301f..a448c1730 100644 --- a/data/txt/sha256sums.txt +++ b/data/txt/sha256sums.txt @@ -188,7 +188,7 @@ c03dc585f89642cfd81b087ac2723e3e1bb3bfa8c60e6f5fe58ef3b0113ebfe6 lib/core/data. 48797d6c34dd9bb8a53f7f3794c85f4288d82a9a1d6be7fcf317d388cb20d4b3 lib/core/replication.py 0b8c38a01bb01f843d94a6c5f2075ee47520d0c4aa799cecea9c3e2c5a4a23a6 lib/core/revision.py 888daba83fd4a34e9503fe21f01fef4cc730e5cde871b1d40e15d4cbc847d56c lib/core/session.py -b0b0b170613ed0ff8235adebbc342cf2bfb69ad054a5fd48971eb851dcfd3b8f lib/core/settings.py +341a90f1ac0b438d3b5f4f3532e70e4cf50385340c9ca2027a122cbcf0dc5683 lib/core/settings.py cd5a66deee8963ba8e7e9af3dd36eb5e8127d4d68698811c29e789655f507f82 lib/core/shell.py bcb5d8090d5e3e0ef2a586ba09ba80eef0c6d51feb0f611ed25299fbb254f725 lib/core/subprocessng.py 70ea3768f1b3062b22d20644df41c86238157ec80dd43da40545c620714273c6 lib/core/target.py @@ -241,7 +241,7 @@ f552b6140d4069be6a44792a08f295da8adabc1c4bb6a5e100f222f87144ca9d lib/techniques 1966ca704961fb987ab757f0a4afddbf841d1a880631b701487c75cef63d60c3 lib/techniques/union/__init__.py 30cae858e2a5a75b40854399f65ad074e6bb808d56d5ee66b94d4002dc6e101b lib/techniques/union/test.py a8a795f29ec6fd66482926f04b054ed492a033982c3b7837c5d2ea32368acec0 lib/techniques/union/use.py -3a418628622cf1f09346ecea12ae13a22341c8211815e01c839c9c1ab01fb12a lib/utils/api.py +c8f1037cacae1068bdc050d44dfa29132051006d4ad022299509234427ca6a41 lib/utils/api.py 442555ab85277aff7c9e0cf465ea5b0d28395c326f68363449b2d3941f4b6de2 lib/utils/brute.py da5bcbcda3f667582adf5db8c1b5d511b469ac61b55d387cec66de35720ed718 lib/utils/crawler.py a94958be0ec3e9d28d8171813a6a90655a9ad7e6aa33c661e8d8ebbfcf208dbb lib/utils/deps.py @@ -489,7 +489,7 @@ cedf45d33461bd7e5400d06611a63c8a4ffae1a4510030c5696b9d46ed6a9883 plugins/generi 45bfd00f09557e20115e6ce7fb52ff507930d705db215e535f991e5fbf7464de plugins/generic/users.py 1966ca704961fb987ab757f0a4afddbf841d1a880631b701487c75cef63d60c3 plugins/__init__.py 5d72f0af46ff3c9e3fe80300e83cb78749132278e8db88915764a94d7130a04c README.md -c6ad39bfd1810413402dedfc275fc805fa13f85fc490e236c1e725bde4e5100b sqlmapapi.py +7ef0d0ea10d4b19283b1e380d521abb0fdd4c6bf1443b88f7b00af7947fc5e27 sqlmapapi.py 4e993cfe2889bf0f86ad0abafd9a6a25849580284ea279b2115e99707e14bb97 sqlmapapi.yaml 627d90f1194335b800cbc9cc78db6697cf9e02e193a83598e0d4d0abb55b63b8 sqlmap.conf 65159b82795604069a2d14ccbd1f66e888a26b05db0401a1ddadb40c665c93dc sqlmap.py diff --git a/lib/core/settings.py b/lib/core/settings.py index 12679fdf9..c9d0825e2 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -20,7 +20,7 @@ from lib.core.enums import OS from thirdparty import six # sqlmap version (...) -VERSION = "1.10.6.51" +VERSION = "1.10.6.52" 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) diff --git a/lib/utils/api.py b/lib/utils/api.py index 5dbf3a0e3..c0704a6ad 100644 --- a/lib/utils/api.py +++ b/lib/utils/api.py @@ -490,6 +490,11 @@ def option_set(taskid): logger.warning("[%s] Invalid JSON options provided to option_set()" % taskid) return jsonize({"success": False, "message": "Invalid JSON options"}) + for key in request.json: + if key in RESTAPI_UNSUPPORTED_OPTIONS: + logger.warning("[%s] Unsupported option '%s' provided to option_set()" % (taskid, key)) + return jsonize({"success": False, "message": "Unsupported option '%s'" % key}) + for option, value in request.json.items(): DataStore.tasks[taskid].set_option(option, value) @@ -687,6 +692,9 @@ def server(host=RESTAPI_DEFAULT_ADDRESS, port=RESTAPI_DEFAULT_PORT, adapter=REST REST-JSON API server """ + if not all((username, password)): + logger.critical("REST-JSON API server requires both username and password") + DataStore.admin_token = encodeHex(os.urandom(16), binary=False) DataStore.username = username DataStore.password = password diff --git a/sqlmapapi.py b/sqlmapapi.py index 99862b65b..198e43c60 100755 --- a/sqlmapapi.py +++ b/sqlmapapi.py @@ -101,10 +101,13 @@ def main(): apiparser.add_argument("-p", "--port", help="Port of the REST-JSON API server (default %d)" % RESTAPI_DEFAULT_PORT, default=RESTAPI_DEFAULT_PORT, type=int) apiparser.add_argument("--adapter", help="Server (bottle) adapter to use (default \"%s\")" % RESTAPI_DEFAULT_ADAPTER, default=RESTAPI_DEFAULT_ADAPTER) apiparser.add_argument("--database", help="Set IPC database filepath (optional)") - apiparser.add_argument("--username", help="Basic authentication username (optional)") - apiparser.add_argument("--password", help="Basic authentication password (optional)") + apiparser.add_argument("--username", help="Basic authentication username") + apiparser.add_argument("--password", help="Basic authentication password") (args, _) = apiparser.parse_known_args() if hasattr(apiparser, "parse_known_args") else apiparser.parse_args() + if (args.server or args.client) and not all((args.username, args.password)): + apiparser.error("--username and --password are mandatory for REST-JSON API server/client usage") + # Start the client or the server if args.server: server(args.host, args.port, adapter=args.adapter, username=args.username, password=args.password, database=args.database)