77 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			77 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| 
								 | 
							
								---
							 | 
						||
| 
								 | 
							
								title: Query Parameterization
							 | 
						||
| 
								 | 
							
								---
							 | 
						||
| 
								 | 
							
								## Query Parameterization
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								A common mistake when connecting your program to a database is to accept a user's input and apply it directly to the database without checking it first. This is a dangerous habit to get into, and you may hear more experienced developers warning others to "sanitize input" or "parameterize queries".
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Let's start with a short example demonstrating the problem:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								_(the following snippets are written in C# for MySQL, but the concept applies to any language and database)_
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### The Problem
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```csharp
							 | 
						||
| 
								 | 
							
								public void RetrieveEmployeeInfo(string username)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    using (var connection = new MySqlConnection("valid_connection_string"))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        var query = "SELECT * FROM EMPLOYEES WHERE USERNAME = '" + username + "'";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        using (var command = new MySqlCommand(query, connection))
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            var reader = command.ExecuteReader();
							 | 
						||
| 
								 | 
							
								            while (reader.Read())
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                // do something with the results of your query, like display the employee
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								At first glance, that might seem fairly harmless. If the user types "JDOE" into your program, and it's passed to this function, you'll end up executing a query like this:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```sql
							 | 
						||
| 
								 | 
							
								SELECT * FROM EMPLOYEES WHERE USERNAME = 'JDOE';
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The problem becomes more apparent when you consider what happens if the user _doesn't_ type what you expect. What if they type something like `JDOE'; DROP TABLE EMPLOYEES; --`? Your "query" string now looks like this, which will select the employee info, then delete the entire EMPLOYEES table!
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```sql
							 | 
						||
| 
								 | 
							
								SELECT * FROM EMPLOYEES WHERE USERNAME = 'JDOE'; DROP TABLE EMPLOYEES; --'
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### The Solution
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								To prevent issues like this, we can parameterize our queries. Let's look at another example:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```csharp
							 | 
						||
| 
								 | 
							
								public void RetrieveEmployeeInfo(string username)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    using (var connection = new MySqlConnection("valid_connection_string"))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        var query = "SELECT * FROM EMPLOYEES WHERE USERNAME = @username";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        using (var command = new MySqlCommand(query, connection))
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            command.Parameters.AddWithValue("username", username);
							 | 
						||
| 
								 | 
							
								                    
							 | 
						||
| 
								 | 
							
								            var reader = command.ExecuteReader();
							 | 
						||
| 
								 | 
							
								            while (reader.Read())
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                // do something with the results of your query, like display the employee
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Now what happens if the user types in `JDOE'; DROP TABLE EMPLOYEES; --`? Our program ends up executing a query like this one and, finding no employee whose username actually matches that input, simply returns no records.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```sql
							 | 
						||
| 
								 | 
							
								SELECT * FROM EMPLOYEES WHERE USERNAME = 'JDOE\'; DROP TABLE EMPLOYEES; --'
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								No matter which language or database you're using, if you consider querying the database using user input, check the documentation for the proper way to parameterize queries.
							 |