How To Prevent SQL Injection To Secure your PHP Application?

PHP, as a popular server-side scripting language, is often used in web development projects. It is crucial to ensure that your PHP applications are fortified against SQL injection attacks.

In this tutorial you will learn how to effectively prevent SQL injection in PHP with best practices and techniques.

Understanding SQL Injection:

SQL injection is a type of security vulnerability that occurs when an attacker is able to manipulate SQL queries sent to a database by injecting malicious SQL code.

It typically happens when user input is concatenated directly into SQL statements without proper sanitization or validation.

For example, consider the following PHP code snippet:

$username = $_POST['username'];
$password = $_POST['password'];

$query = "SELECT * FROM users WHERE username='$username' AND password='$password'";
$result = mysqli_query($conn, $query);

In this code, if an attacker enters a malicious input like ' OR '1'='1, the resulting query becomes:

$username = $_POST['username']; // Contain -> ' OR '1'='1
$password = $_POST['password']; // Contain -> ' OR '1'='1

$query = "SELECT * FROM users WHERE username='$username' AND password='$password'";
// This query always returns true
$query_becomes = "SELECT * FROM users WHERE username='' OR '1'='1' AND password='' OR '1'='1'";

This query always returns true, effectively bypassing the authentication system and granting unauthorized access.

SQL injection poses various security risks:

SQL injection is a severe threat because it can lead to various security risks:

Ways to Prevent SQL Injection in PHP:

Preventing SQL injection requires a combination of best practices and techniques to ensure that user input is properly sanitized and validated before being included in SQL queries.

Now that we understand the risks associated with SQL injection, let’s explore effective prevention techniques for PHP applications:

1. Use Prepared Statements and Parameterized Queries:

Prepared statements separate SQL code from user input, making it extremely difficult for attackers to inject malicious code.

# Prepared Statement
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ?");
$stmt->execute([$input_username]);
# With Parameterized Queries
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username");
$stmt->bindParam(':username', $input_username);
$stmt->execute();

2. MySQLi execute_query():

PHP introduced the MySQLi execute_query() method in version 8.2 which is a shortcut for mysqli::prepare(), mysqli_stmt::bind_param(), mysqli_stmt::execute(), and mysqli_stmt::get_result().

Here is an example of using it:

// Create a MySQLi connection
$mysqli = new mysqli("localhost", "username", "password", "mydatabase");

// Prepare a SQL statement with placeholders
$sql = "SELECT * FROM users WHERE username = ?";

$result = $mysqli->execute_query($sql, [$input_username]);

With prepared statements, user input is treated as data, not as part of the SQL query, making it impossible for attackers to inject malicious code.

3. Input Validation and Sanitization:

In addition to prepared statements, input validation and sanitization are essential. Validate and sanitize user inputs to ensure they meet expected criteria before using them in SQL queries.

Use PHP’s built-in functions like filter_var and htmlspecialchars for this purpose.

// Validate and sanitize user input
$email = "[email protected]";

if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
  echo("$email is a valid email address");
} else {
  echo("$email is not a valid email address");How to Implement MySQL Prepared Statement in PHP
}

# htmlspecialchars Example
$new = htmlspecialchars("<a href='test'>Test</a>", ENT_QUOTES);
echo $new; //Output: &lt;a href=&#039;test&#039;&gt;Test&lt;/a&gt;

4. Escaping User Input:

If you are using PHP MySQLi Extension, consider escaping user input using functions like mysqli_real_escape_string. However, this method is not as secure as prepared statements.

// Escape user input (using MySQLi Extension)
$escaped_username = mysqli_real_escape_string($mysqli, $input_username);

5. Least Privilege Principle:

Ensure that the database user account used by your PHP application has the least privilege necessary.

Limit the account’s access rights to only the specific tables and operations required by the application. This minimizes the potential impact of an SQL injection attack.

6. Error Handling:

Avoid displaying detailed error messages to users (When your application is in production), as they can provide valuable information to attackers.

7. Regular Updates and Security Patches:

Keep your PHP version, database software, and related libraries up to date.

Note: Check if your application is running on the newer version of a software before updating to the production version.

Suggestion: Do not update immediately after a new version of a software is released. May be, there will be some flaws in the newer version. Wait for some time until people start using it normally.