SQL Injection (SQLi) is one of the oldest—and still most dangerous—web vulnerabilities. It allows attackers to manipulate backend SQL queries by injecting arbitrary code through unsanitized inputs. If successful, attackers can:
- Bypass authentication
- Extract sensitive records
- Modify or delete data
- In extreme cases, achieve remote code execution (RCE)
SQLi remains a top entry in the OWASP Top 10 because many legacy systems and poorly implemented apps are still vulnerable today.
How SQL Injection Works
SQLi exploits occur when an application directly includes user-supplied input in a SQL query string without proper sanitization or parameterization.
Conceptual Flow:
User input → Embedded in SQL query → Malicious SQL code executes
Instead of treating input as data, the application mistakenly treats it as SQL logic.
Vulnerable Code Example (PHP)
Here’s a common pattern that leads to SQLi in a PHP/MySQL app:
$user = $_GET['username'];
$pass = $_GET['password'];
$query = "SELECT * FROM users WHERE username = '$user' AND password = '$pass'";
$result = mysqli_query($conn, $query);
Now imagine an attacker sends:
username = ' OR '1'='1
password = anything
The resulting SQL query becomes:
SELECT * FROM users WHERE username = '' OR '1'='1' AND password = ''
This condition always evaluates to true—bypassing login checks.
Attack Vectors and Payload Examples
- Authentication bypass:
' OR 1=1 --
- Data extraction:
' UNION SELECT credit_card_number FROM payments --
- Blind SQLi: Time-based or Boolean inference via crafted payloads (e.g.,
' AND SLEEP(5) --
) - Stacked queries (in some DBs):
'; DROP TABLE users; --
Client-Side Entry Points
Although SQLi happens server-side, the entry point is user input—commonly via:
- URL query parameters
- Form fields (login, search)
- API requests (JSON bodies)
- Cookies or HTTP headers
Modern attackers often automate this scanning using tools like sqlmap or Burp Suite extensions.
Mitigation Best Practices
Protecting against SQLi comes down to not trusting user input—ever. Here’s how to stay safe:
Use Prepared Statements (Parameterized Queries)
Let the database handle input escaping:
In PHP (MySQLi):
$stmt = $conn->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
$stmt->bind_param("ss", $user, $pass);
$stmt->execute();
In Python (SQLite):
cursor.execute("SELECT * FROM users WHERE username=? AND password=?", (user, pass))
Additional Safeguards
- Input validation: Reject suspicious patterns early (e.g., SQL meta-characters)
- Escape output, not input—but never rely solely on escaping
- Principle of least privilege: DB users should only access what's necessary
- WAFs and logging: Use web application firewalls and monitor abnormal query patterns
Real-World Consequences
SQLi has enabled some of the largest breaches in history—such as:
- Heartland Payment Systems (2008): 130M card numbers stolen
- Sony Pictures (2011): User databases dumped via blind SQLi
- British Airways (2018): Injection vulnerability enabled payment skimming
Even today, insecure legacy systems, CMS plugins, and small business platforms remain prime targets.
TL;DR
SQL Injection is simple to exploit but devastating in impact.
Mitigate it by design—not after a breach. Use prepared statements, validate inputs, and audit your codebase regularly.
If your app constructs SQL queries with untrusted input, you are vulnerable. Fix it now—before someone else finds it.