SQL Injection (SQLi)
SQL Injection occurs when untrusted input is concatenated into SQL queries, allowing attackers to read, modify, or delete database contents. Learn how to detect and prevent SQLi across languages.
What is SQL Injection?
SQL Injection (SQLi) is a code injection vulnerability that occurs when an application incorporates user-supplied data into SQL queries without proper sanitization or parameterization. An attacker can manipulate the SQL query logic to:
- Extract data — Read tables, columns, and records they shouldn’t have access to
- Modify data — Insert, update, or delete records
- Bypass authentication — Log in as any user without knowing passwords
- Execute commands — In some database configurations, run operating system commands on the server
SQLi consistently ranks among the most dangerous web application vulnerabilities. It’s listed in the OWASP Top 10 (A03:2021 Injection) and CWE Top 25 (CWE-89).
Why it matters
SQL Injection is not a theoretical risk. It has been the root cause of some of the largest data breaches in history, including breaches that exposed hundreds of millions of user records. Despite being well-understood for over two decades, SQLi remains prevalent because:
- Legacy code often uses string concatenation for queries
- Developers may not understand the difference between escaping and parameterization
- ORMs can be bypassed with raw query methods
- Second-order injection (stored input used in later queries) is hard to spot manually
How exploitation works
Basic example
Consider this C# code that builds a login query:
// VULNERABLE: User input directly concatenated into SQL
string query = "SELECT * FROM Users WHERE Username = '" + username + "' AND Password = '" + password + "'";
SqlCommand cmd = new SqlCommand(query, connection);
An attacker enters admin' -- as the username. The resulting query becomes:
SELECT * FROM Users WHERE Username = 'admin' --' AND Password = ''
The -- comments out the password check, granting access as admin without knowing the password.
Blind SQL Injection
When the application doesn’t return query results directly, attackers use boolean-based or time-based techniques:
// Boolean-based: different responses reveal data
/user?id=1 AND 1=1 → normal response
/user?id=1 AND 1=2 → different response
// Time-based: response timing reveals data
/user?id=1; WAITFOR DELAY '0:0:5'-- → 5-second delay confirms injection
Vulnerable code examples
C# / ASP.NET
// VULNERABLE
public User GetUser(string id)
{
string query = $"SELECT * FROM Users WHERE Id = {id}";
using var cmd = new SqlCommand(query, connection);
// ...
}
Java / Spring
// VULNERABLE
public User findUser(String username) {
String sql = "SELECT * FROM users WHERE username = '" + username + "'";
return jdbcTemplate.queryForObject(sql, userRowMapper);
}
Python / Django
# VULNERABLE — bypassing Django ORM with raw SQL
def get_user(request):
user_id = request.GET.get('id')
cursor.execute(f"SELECT * FROM users WHERE id = {user_id}")
PHP
// VULNERABLE
$query = "SELECT * FROM users WHERE id = " . $_GET['id'];
$result = mysqli_query($conn, $query);
Secure code examples
C# — Parameterized query
// SECURE: Parameterized query
public User GetUser(string id)
{
string query = "SELECT * FROM Users WHERE Id = @Id";
using var cmd = new SqlCommand(query, connection);
cmd.Parameters.AddWithValue("@Id", id);
// ...
}
Java — PreparedStatement
// SECURE: PreparedStatement with parameter binding
public User findUser(String username) {
String sql = "SELECT * FROM users WHERE username = ?";
return jdbcTemplate.queryForObject(sql, userRowMapper, username);
}
Python — Parameterized query
# SECURE: Parameterized query
def get_user(request):
user_id = request.GET.get('id')
cursor.execute("SELECT * FROM users WHERE id = %s", [user_id])
PHP — Prepared statement
// SECURE: Prepared statement with PDO
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
$stmt->execute(['id' => $_GET['id']]);
What Offensive360 detects
Our SAST engine traces data flow from user input sources (HTTP parameters, form data, headers, cookies) through your application code to SQL query construction. We detect:
- Direct concatenation — String interpolation or concatenation used in SQL queries
- Unsafe ORM usage — Raw query methods in Django, ActiveRecord, Entity Framework with unsanitized input
- Stored procedures — Dynamic SQL within stored procedures that use unsanitized parameters
- Second-order injection — Data stored from one request used unsafely in a later query
- Partial sanitization — Cases where escaping is used instead of parameterization
Each finding includes the complete data-flow trace from source to sink, making it clear exactly how user input reaches the vulnerable query.
Remediation guidance
-
Always use parameterized queries — This is the primary defense. Every major language and framework supports them.
-
Use your ORM correctly — ORMs like Entity Framework, Django ORM, and ActiveRecord protect against SQLi when used properly. Avoid raw query methods with user input.
-
Apply input validation — Validate that input matches expected formats (e.g., numeric IDs should be integers). This is defense-in-depth, not a primary fix.
-
Use least-privilege database accounts — The application’s database user should only have the permissions it needs. Don’t connect as
saorroot. -
Enable WAF rules — Web Application Firewalls can catch common SQLi patterns, but should not be your only defense.
False-positive considerations
Offensive360 may flag SQL query construction that is actually safe in certain cases:
- Constant strings — If the concatenated value is a compile-time constant (not user input), there is no injection risk
- Validated numeric input — If input is parsed to an integer before use, the risk is mitigated
- Allow-listed values — If the application checks input against a fixed set of allowed values
Our engine applies taint analysis to reduce these false positives, but some edge cases may require manual review.
References
Related vulnerabilities
Detect SQL Injection (SQLi) in your code
Run Offensive360 SAST against your codebase to find this and hundreds of other vulnerabilities.