What is SQL Injection (SQLi)? Ways to Exploit, Examples and Impact

Master the fundamentals of SQL Injection (SQLi). This guide covers exploitation methods, real-world examples, and critical prevention strategies for developers.

What is SQL Injection (SQLi)? Ways to Exploit, Examples and Impact

SQL Injection (SQLi) remains one of the most prevalent and damaging web application vulnerabilities in the modern cybersecurity landscape. Despite being a well-understood threat for over two decades, it consistently ranks near the top of the OWASP Top 10 list of web security risks. At its core, SQLi allows an attacker to interfere with the queries that an application makes to its database, potentially granting unauthorized access to sensitive data, administrative control, or the ability to modify and delete critical information.

Understanding the Fundamentals of SQL Injection

To understand SQL Injection, one must first understand how web applications interact with databases. Most modern websites use a database (like MySQL, PostgreSQL, or SQL Server) to store user information, product catalogs, and configuration settings. When a user interacts with a site—such as logging in or searching for a product—the application generates a Structured Query Language (SQL) command to retrieve or update the relevant data.

A SQL Injection vulnerability occurs when an application takes user-supplied input and includes it directly in a SQL query in an unsafe manner. Instead of treating the input as literal data, the database engine interprets part of the input as a command. This happens because the application fails to properly sanitize the input or use secure coding patterns like parameterized queries.

The Anatomy of a Vulnerable SQL Query

Consider a simple PHP-based login script that checks a username and password. The code might look like this:

$username = $_POST['username'];
$password = $_POST['password'];

$query = "SELECT * FROM users WHERE username = '" . $username . "' AND password = '" . $password . "'";

If a legitimate user enters the username admin and the password password123, the resulting SQL query is:

SELECT * FROM users WHERE username = 'admin' AND password = 'password123'

However, if an attacker enters ' OR '1'='1 in the username field and leaves the password blank, the query becomes:

SELECT * FROM users WHERE username = '' OR '1'='1' AND password = ''

Because '1'='1' is always true, the database returns the first record in the users table, which is often the administrator account. The attacker has successfully bypassed authentication without knowing a valid password.

Common Types of SQL Injection Attacks

SQL Injection is not a monolithic threat; it manifests in several forms depending on how the application handles data and how the database responds to the injected commands. We generally categorize SQLi into three main types: In-band (Classic), Inferential (Blind), and Out-of-band.

In-band SQLi (Classic SQLi)

In-band SQLi is the most straightforward and common type of attack. In this scenario, the attacker uses the same communication channel to both launch the attack and gather the results. There are two primary sub-types:

  1. Error-based SQLi: The attacker intentionally submits malformed SQL fragments to trigger database error messages. If the application is configured to display these errors, the attacker can extract information about the database's structure, version, and table names. For example, injecting a single quote ' might reveal that the backend is running Microsoft SQL Server.
  2. Union-based SQLi: This technique leverages the UNION SQL operator to combine the results of the original query with a secondary query injected by the attacker. This allows the attacker to steal data from other tables in the database. To succeed, the attacker must first determine the number of columns returned by the original query and their data types.

Inferential SQLi (Blind SQLi)

Inferential or "Blind" SQLi occurs when the application does not return any data or error messages directly in the HTTP response. The attacker cannot see the results of their query, but they can still reconstruct information by observing the application's behavior. This is often slower but equally dangerous.

  1. Boolean-based Blind SQLi: The attacker sends queries that ask the database true/false questions. For example, they might inject a condition like AND (SELECT SUBSTRING(password,1,1) FROM users WHERE username='admin')='a'. If the page loads normally, the first letter of the password is 'a'. If the page displays a "not found" message, the letter is something else.
  2. Time-based Blind SQLi: If the application's response doesn't change based on true/false conditions, the attacker can use time delays. They inject commands like SLEEP(10) or pg_sleep(10). If the server takes 10 seconds to respond, the attacker knows the injected condition was true.

Out-of-band SQLi

Out-of-band SQLi is rare and only possible when the database server has certain features enabled, such as the ability to make DNS or HTTP requests. The attacker triggers the database to send data to an external server they control. This is often used when the application is too slow or unstable for blind techniques.

Practical SQL Injection Payload Examples

To better understand the mechanics of exploitation, let's look at some common payloads used by security researchers and attackers.

Bypassing Login Forms

As seen earlier, the most basic payload involves using a tautology (a statement that is always true) to bypass authentication logic.

Payload: ' OR 1=1 --
Explanation: The -- (or # in MySQL) comments out the rest of the original SQL query, ignoring the password check entirely.

Data Exfiltration using UNION

Suppose an application displays product details via a URL like product.php?id=123. An attacker can check for a UNION vulnerability by trying to determine the column count:

Payload: 123 ORDER BY 1--, 123 ORDER BY 2--, 123 ORDER BY 3--
If ORDER BY 4 triggers an error, the attacker knows there are 3 columns. They can then extract the database name:

Payload: -1 UNION SELECT 1,2,database()--
By using -1, the attacker ensures the first part of the query returns nothing, so only the result of the UNION (the database name) is displayed on the page.

Database Fingerprinting

Identifying the database management system (DBMS) is crucial for tailoring an attack. Different databases have different functions for retrieving the version:

  • MySQL/MariaDB: SELECT @@version
  • PostgreSQL: SELECT version()
  • Microsoft SQL Server: SELECT @@version
  • Oracle: SELECT banner FROM v$version

The Impact of SQL Injection on Business Security

The consequences of a successful SQL Injection attack can be catastrophic for an organization. Because the database is often the "crown jewel" of an application, gaining control over it leads to several high-impact risks:

  • Data Breaches: Attackers can steal sensitive customer data, including PII (Personally Identifiable Information), credit card numbers, and passwords. This leads to massive fines under regulations like GDPR or CCPA.
  • Loss of Integrity: SQLi allows attackers to modify data. They could change their own account balance, alter prices in an e-commerce store, or delete entire tables to disrupt business operations.
  • Administrative Takeover: In some configurations, if the database user has high privileges (like db_owner or root), an attacker can use SQLi to execute operating system commands, potentially leading to a full server compromise.
  • Reputational Damage: News of a data breach caused by a preventable vulnerability like SQLi erodes customer trust and can lead to a long-term decline in brand value.

How to Detect SQL Injection Vulnerabilities

Detecting SQLi requires a combination of automated scanning and manual testing. Security professionals often use tools like sqlmap to automate the process of detecting and exploiting SQLi vulnerabilities, but manual verification is essential to reduce false positives.

  1. Dynamic Analysis (DAST): Tools crawl the application and submit common SQLi payloads into every input field, header, and cookie to see how the application reacts.
  2. Static Analysis (SAST): Reviewing the source code of the application to find instances where variables are concatenated into SQL strings instead of being handled securely.
  3. Manual Fuzzing: Inserting special characters like ', ", \, ;, and -- into input fields to see if the application generates database errors or changes behavior.

How to Prevent SQL Injection: Best Practices

Preventing SQL Injection is a matter of adopting secure coding standards. The primary goal is to ensure that user input is never interpreted as code by the database engine.

Using Prepared Statements (Parameterized Queries)

This is the most effective defense against SQLi. Instead of building a query string with user input, you define the SQL code first and then pass the user input as parameters. The database treats these parameters strictly as data, never as executable code.

Example in Java (JDBC):

String query = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement pstmt = connection.prepareStatement(query);
pstmt.setString(1, username);
pstmt.setString(2, password);
ResultSet results = pstmt.executeQuery();

Implementing Input Validation and Filtering

Always validate input against a strict allowlist. For example, if an input is supposed to be a numeric ID, ensure it only contains digits. While validation is not a complete replacement for parameterized queries, it adds a crucial layer of defense-in-depth.

Principle of Least Privilege

Configure the database user that the application uses to have the minimum permissions necessary. For instance, a web application's database user should rarely have permissions to drop tables, access system-level configurations, or execute shell commands (xp_cmdshell in MSSQL).

Using an ORM

Modern Object-Relational Mapping (ORM) frameworks like Hibernate (Java), Entity Framework (.NET), or Eloquent (PHP/Laravel) often handle SQL generation securely by default, using parameterized queries under the hood. However, developers must still be careful when using "raw query" features within these frameworks.

Conclusion

SQL Injection is a classic vulnerability that continues to plague modern web applications. By understanding the different types of SQLi—from simple Union-based attacks to complex time-based blind techniques—developers and security professionals can better defend their infrastructure. The key to prevention lies in moving away from string concatenation and embracing parameterized queries, robust input validation, and the principle of least privilege.

To proactively monitor your organization's external attack surface and catch database exposures before attackers do, try Jsmon.