Earn More by Sharing What You Love
Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!

Tim Corey
34m 33s
SQL injection is a code injection technique that lets attackers send malicious SQL code to your database server through user input. In his video "What Is SQL Injection And How Do I Prevent It in C#?", Tim Corey demonstrates exactly how SQL injection vulnerabilities appear in real code, shows several successful SQL injection attack examples (including union-based and destructive attacks), and walks through practical SQL injection prevention techniques you can apply in C#. This article follows Tim's walkthrough so you can see the exact problems and fixes he shows.
Tim starts with a small WPF demo app tied to a local InjectableDB (People and Secrets tables). The app's web form-like search box takes user input (a last name) and builds a SQL query to return ID, first name and last name. It "works" - type Corey and you get Tim Corey - but Tim emphasizes the core point: "Just because an application works doesn't mean it's safe." A working web application can still have SQL injection vulnerabilities when user-supplied input is inserted directly into SQL statements via string concatenation or dynamic SQL.
Tim shows the exact unsafe pattern many devs use:
var sql = $"SELECT * FROM People WHERE LastName = '{searchText}'";
var results = connection.Query<Person>(sql);Dim sql = $"SELECT * FROM People WHERE LastName = '{searchText}'"
Dim results = connection.Query(Of Person)(sql)This original query uses string concatenation to create a SQL statement. Tim warns: if you see code that injects user inputs directly into SQL queries, stop - this is a SQL injection vulnerability. Attackers can craft malicious input that changes the structure of your SQL commands or even runs additional malicious SQL statements.
To show how a SQL injection attack works, Tim reproduces queries in SQL Server and then crafts injections using UNION ALL and SQL comments (--) to hide trailing characters. Example malicious payloads Tim demonstrates:
Union-based SQL injection to read other tables:
UNION ALL SELECT ID, Username AS FirstName, Password AS LastName FROM Secrets;
This mixes results from Secrets into the original SELECT result set, exposing sensitive data like usernames and passwords.
Destructive injection to drop tables:
DROP TABLE DemoTable;
This runs a second SQL statement (DROP TABLE) by terminating the first statement with a semicolon and then adding the destructive command. Tim shows the table disappears - the database has been modified by malicious SQL.
Tim's point: attackers don't need to know table or column names ahead of time - they can enumerate table or column names from database servers, or simply try blind or timing-based techniques to discover behavior.
Tim's first and primary defense is to stop building SQL strings with user data. Replace dynamic SQL with parameterized queries:
string sql = "SELECT * FROM People WHERE LastName = @LastName";
var results = connection.Query<Person>(sql, new { LastName = searchText });Dim sql As String = "SELECT * FROM People WHERE LastName = @LastName"
Dim results = connection.Query(Of Person)(sql, New With {.LastName = searchText})Tim explains that parameterization (prepared statement style usage) means the database treats the user-supplied input strictly as data - malicious SQL becomes just a string value and cannot change the SQL structure. This prevents many common SQL injection attacks including union-based payloads and appended ; DROP TABLE commands.
He also recommends pairing parameterization with minimal input validation: sanitize or block characters unlikely in a last name (e.g., semicolons or -- comment markers) while allowing legitimate characters like apostrophes (O'Reilly). Parameterized queries + input cleansing give substantial protection against SQL injection attacks.
Tim next shows two stored procedures: an unsafe stored procedure that concatenates SQL inside the proc and then executes it, and a safe stored procedure that uses parameters directly.
Tim clarifies: stored procedures are not an automatic cure if you still build dynamic SQL inside them. But when used properly (no dynamic SQL), stored procedures help centralize SQL statements, making it easier to parameterize and audit queries. Stored procedures can also help simplify SQL injection prevention in your app.
An important, often-missed point Tim raises: you mustn't blindly trust data retrieved from your own SQL database. Attackers sometimes plant malicious payloads in columns (a "ticking time bomb") that will later be concatenated into dynamic SQL by another process. Tim insists: always use parameters and sanitize data at every step - whether it comes from a web form, a file upload, or your own database - so malicious input cannot later become an avenue for injection.
Beyond code fixes, Tim recommends defensive configuration: limit database privileges for your application accounts. In his demo the connection uses an admin account via integrated security - dangerous. Instead, use the principle of least privilege:
This reduces the impact of a successful SQL injection attack - even if injection is possible, the attacker can't do more than the account is allowed.
Tim also notes Entity Framework complicates this: EF often requires elevated permissions (migrations, schema changes). If you use EF in production, plan its permissions and deployment carefully.
Tim wraps up his video with a clear checklist to prevent SQL injection in C# applications:
Tim's final warning: sloppy handling of user inputs, dynamic SQL, and excessive database privileges can lead to serious breaches - leaked sensitive data, destroyed tables, or long-running undetected exfiltration. Treat SQL injection prevention as a core security requirement, not an optional polish.
Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!
Join our newsletter, you’ll get exclusive access on article updates. We value your privacy