ADO - Parameterization & SQL Injection Prevention
Parameterization means sending SQL code and data separately to the database.
This is the only correct and reliable way to prevent SQL Injection in ADO.NET.
1. What is SQL Injection (fact)
SQL Injection happens when user input is treated as SQL code.
Vulnerable example ❌
string sql = "SELECT * FROM Users WHERE Username = '" + user + "'";
SqlCommand cmd = new SqlCommand(sql, conn);
Input:
' OR 1=1 --
Result:
SELECT * FROM Users WHERE Username = '' OR 1=1 --'
✔ Attacker bypasses authentication
2. How parameterization stops injection
With parameters:
-
SQL structure is fixed
-
User input is data only
-
Database never executes input as code
3. Correct parameterized query (ADO.NET)
SqlCommand cmd = new SqlCommand(
"SELECT * FROM Users WHERE Username = @username",
conn);
cmd.Parameters.AddWithValue("@username", userInput);
✔ Injection impossible
✔ Query plan reuse
✔ Cleaner code
4. Best practice: define parameter types (important)
Avoid AddWithValue for non-trivial queries.
Correct way
cmd.Parameters.Add("@username", SqlDbType.NVarChar, 50)
.Value = userInput;
Why
-
Prevents implicit type conversion
-
Avoids index scans
-
Improves performance
5. Parameterization for INSERT / UPDATE
SqlCommand cmd = new SqlCommand(
"INSERT INTO Users (Name, Age) VALUES (@name, @age)", conn);
cmd.Parameters.Add("@name", SqlDbType.NVarChar, 100).Value = name;
cmd.Parameters.Add("@age", SqlDbType.Int).Value = age;
6. Stored procedures + parameters (safe)
SqlCommand cmd = new SqlCommand("CreateUser", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@name", SqlDbType.NVarChar, 100).Value = name;
✔ Safe
✔ Reusable
✔ Centralized validation
7. What does NOT prevent SQL Injection ❌
| Method | Why unsafe |
|---|---|
| String concatenation | Input becomes SQL |
| Escaping quotes | Bypassable |
| Regex validation | Not sufficient |
| Client-side validation | Easily skipped |
Only parameters truly prevent injection.
8. Dynamic SQL (safe pattern)
If SQL must be dynamic:
string sql = "SELECT * FROM Orders WHERE Status = @status";
if (isPaid)
sql += " AND PaidDate IS NOT NULL";
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.Parameters.Add("@status", SqlDbType.VarChar, 20).Value = status;
✔ SQL structure dynamic
✔ Data still parameterized
9. Edge cases to watch
-
Table/column names cannot be parameterized
→ Must be whitelisted -
INclauses need multiple parameters -
LIKE queries still safe with parameters
cmd.Parameters.Add("@name", SqlDbType.NVarChar)
.Value = "%" + search + "%";
10. Security checklist (real-world)
✔ Always use parameters
✔ Use least-privilege DB accounts
✔ Validate input (for logic, not security)
✔ Avoid dynamic SQL when possible
✔ Log and monitor failed attempts