SQL injection is a code injection attack where an attacker inserts malicious SQL statements into input fields or API parameters that get executed by your application's database. A successful SQL injection can allow attackers to read, modify, or delete data, bypass authentication, and in some cases execute commands on the underlying server.
SQL injection (SQLi) is an attack where someone manipulates the database queries your application sends by inserting malicious SQL code through user input. It works because the application treats untrusted user input as part of a database command instead of as data.
Here's the classic example. Your login form takes a username and password and builds a query like this:
SELECT * FROM users WHERE username = 'INPUT' AND password = 'INPUT'
If an attacker enters ' OR '1'='1 as the username, the query becomes:
SELECT * FROM users WHERE username = '' OR '1'='1' AND password = ''
Since '1'='1' is always true, the database returns all users and the attacker is logged in without knowing any credentials. That's SQL injection in its simplest form.
The attack isn't limited to login forms. Any place your application passes user input to a database query is a potential injection point: search bars, URL parameters, API endpoints, form fields, HTTP headers, and even cookies.
SQL injection was first documented in 1998. Twenty-seven years later, it remains one of the most dangerous and frequently exploited vulnerability classes in web applications.
SQL injection has been behind some of the most damaging data breaches in history:
The good news: SQL injection is almost entirely preventable with known techniques.
Fencer's SAST scanning detects SQL injection patterns in your source code on every pull request, catching unsafe query construction before it merges. Fencer's DAST scanning tests your running application for SQL injection vulnerabilities by sending crafted requests to your endpoints, the same way an attacker would probe them. Together, these catch SQL injection at both the code level and the runtime level.
ORMs prevent SQL injection by default when you use their query-building methods, because they generate parameterized queries automatically. However, most ORMs also provide a way to execute raw SQL, and those raw queries are just as vulnerable to injection as hand-written SQL. The risk shifts from the query language to the developer bypassing the ORM's protections. If your team uses an ORM, establish a policy that raw SQL queries require security review before merging.
The same injection principle applies to NoSQL databases (MongoDB, DynamoDB, Couchbase), LDAP directories, XML parsers, and operating system commands. NoSQL injection, LDAP injection, and command injection all follow the same pattern: untrusted input is treated as executable instructions rather than data. SQL injection is the most common and well-known variant, but the defense (parameterized queries or equivalent input separation) applies across all injection types. OWASP groups them all under the "Injection" category for this reason.
There are three complementary approaches. First, run a SAST scanner against your codebase to find code patterns that are vulnerable to injection (like string concatenation in SQL queries). Second, run a DAST scanner against your running application to test whether injection payloads actually work against your endpoints. Third, include SQL injection testing in your penetration tests. Each method catches different things: SAST finds the vulnerability in code, DAST confirms it's exploitable at runtime, and a pen tester can find logic-level injection paths that automated tools miss.