What's in That Input Field?
Maya's first security code review. Her task: audit the customer lookup page. She opens the source and finds the search function: the application takes whatever the user types into the name field, drops it directly into a SQL query, and sends it to the database. SELECT * FROM customers WHERE name = '[user input]'. "That's fine," she thinks β until her senior developer Raj stops by her desk and asks: "What stops someone from typing SQL instead of a name?"
She stares at the code. Nothing. There are no checks, no filters, no validation. The application trusts everything the user types and passes it straight to the database engine. "The browser is just the front end," Raj explains. "Behind it is a database that speaks SQL. If your app doesn't filter the input, the user can speak directly to the database β and the database will listen."
How the Injection Works
Raj pulls up the database query on the whiteboard. Normal usage: a user types "Professor" and the app sends SELECT * FROM users WHERE name = 'Professor' β the database returns that user's record. Fine. Expected. Now Raj writes a different input: Professor' OR '1'='1. "Watch what the query becomes," he says.
The app constructs: SELECT * FROM users WHERE name = 'Professor' OR '1'='1'. Maya's eyes widen. 1 does equal 1 β always. The condition is always true. The database returns every row in the users table. Every account. Every record. "You didn't write any extra software," Raj says. "You didn't exploit a network protocol. You just typed something into an input field. That's all SQL injection is β adding your own SQL into the query the application was already going to run."
He writes more examples on the board. With a carefully crafted input, an attacker can add a semicolon and chain additional SQL commands. They can call DROP TABLE customers and delete the entire table. They can call INSERT to add fake records. They can call stored procedures that run administrative commands. "Once the injection works," Raj says, "you effectively have complete control of the data in that database."
More Than Just Viewing Data
Maya asks: "So the worst case is someone reads customer names?" Raj shakes his head. "The database doesn't just hold names. It holds everything." He lists what the retail company's database contains: full customer profiles, email addresses, shipping addresses, order histories, payment method references, internal employee records, product pricing, vendor contracts, promotional codes. "SQL injection doesn't give read-only access. Depending on what commands the attacker injects and what permissions the database account is running under, they can read it, change it, or delete it."
He describes four outcomes. View: the attacker reads data they were never supposed to see β customer PII, credentials, financial records. Modify: the attacker changes records β prices, account balances, access levels. Delete: the attacker destroys data β a full DROP TABLE wipes the database permanently. Deny: the attacker causes the database to crash or become unresponsive, taking the application down. "One unguarded input field," Raj says. "Four catastrophic outcomes."
Every Input Is a Potential Door
Raj and Maya walk through the application together. He points out every place where user input touches the database: the login form (username and password fields), the product search bar, the customer registration form (name, address, email), the account lookup field in the admin panel, the URL parameters in product detail pages. "Every one of these is a potential injection point," he says. "An attacker tests them all. They look for the one that isn't sanitized."
Maya is alarmed. "Doesn't this require special software? Do they need to be on the network?" Raj shakes his head. "No. All of this runs through a web browser. The attacker opens the site in their browser, finds an input field, and types SQL. That's the entire attack. No special tool required. No network access required. No user needs to click anything. The only thing standing between the attacker and the database is whether your code checks the input β and right now, ours doesn't."
Parameterized Queries β The Right Way to Build SQL
Maya asks the question that matters: "How do we fix it?" Raj sits down and shows her. The core problem is string concatenation β building SQL by pasting user input directly into the query string. The fix is parameterized queries, also called prepared statements. Instead of building the SQL string with user input embedded in it, the developer writes the query with a placeholder β a parameter β and then passes the user's input separately. The database engine receives the structure and the data as two separate things. It cannot confuse one for the other.
He writes both versions. Vulnerable: query = "SELECT * FROM users WHERE name = '" + userInput + "'". Safe: the query is defined first as a template β SELECT * FROM users WHERE name = ? β and then the value of userInput is bound to that placeholder as pure data. The database engine sees the structure defined by the developer and the data provided by the user as completely separate entities. No matter what the user types β even Professor' OR '1'='1 β it is treated as a literal string being searched for, not as SQL code to execute.
"This is the most important fix," Raj says, "but not the only layer." He walks Maya through the full defense stack: input validation (only accept the character types the field should receive β a name field should reject apostrophes and semicolons); stored procedures that limit what SQL operations can be performed; principle of least privilege (the database account the app uses should only have SELECT permission where SELECT is all it needs β it should never need DROP TABLE from a customer search); and a web application firewall that can detect and block common injection patterns at the network layer.