Preventing SQL Injection in PHP
Understanding SQL Injection
Here’s an example of how a SQL injection attack works. Say there is a simple login form on a page like this.
The PHP to process this form looks like this.
Note: This is only a simplified example, real passwords should not be stored in plain text.
This script works great if all users have good intentions, but unfortunately that’s not always the case. Here’s how an attacker can exploit this simple login form to takeover the database.
Appending SQL to the Query
Using SQL injection an attacker can add additional harmful queries. If an attacker uses the following password they could drop the user table entirely.
As you can see, the SQL statement in the $sql variable is closed out with a closing apostrophe and semicolon. A second statement is added after that drops the users table.
1=1 Always Evaluates True
Using SQL injection an attacker can modify the query to always evaluate true. An attacker could also use SQL injection to gain access to any user’s account with the following password
The OR clause has been added here which will always evaluate to true and allow an attacker to successfully login. This is the completed SQL statement after the injection attack.
Prevent and Secure Against SQL Injection
Fortunately, SQL injection is very easy to prevent once you understand the vulnerability. There are two steps to preventing an injection attack. The first step is proper user input validation and sanitization. The second step is to update the database technology to use prepared statements or to properly escape the input added to the query.
Validation and Sanitization
The first step to preventing SQL injection is to properly validate and sanitize user input. In the login form example, there are likely some characters that can be treated as illegal, depending on your application. For instance, usernames could be limited to letters and numbers only, limiting the attack surface. Passwords on the site should be hashed which would address the threat of special characters posing an injection risk.
The key takeaway is to always know what data you are expecting the user to enter, if it’s a number then validate that it’s a number and maybe even cast it to a float or integer to be safe. If characters are not allowed, then remove them before adding the user input to a query. This will also help maintain data integrity.
Using Prepared Statements or an Escaping Strategy
The second step to preventing SQL injection is to use prepared statements or to use an escaping strategy appropriate for your database.
If your application is a new application then consider using the PHP mysqli or PDO libraries. These both allow the use of prepared statements. Prepared statements are like a template for the SQL statement with placeholders for any variables or parameters. The database will handle adding the parameters safely back into the query. Prepared statements are not vulnerable to SQL injection IF all user input is added using parameters in the query.
In many applications prepared statements are not an easy option, as is the case with many legacy applications. An alternative to prepared statements is to properly escape all user input prior to adding to the query. This should be specific to the database and library used. If your application uses the PHP mysql extension, then there is a function to properly escape user input: mysql_escape_string().
2 comments on “Preventing SQL Injection in PHP”