Chapter 14: PHP Security Best Practices
Learn best practices for PHP security, including protecting against SQL injection, XSS, and securely handling user input.
In this chapter, we’ll discuss security best practices in PHP to help you protect your applications against common vulnerabilities. Ensuring data security and preventing attacks like SQL injection and cross-site scripting (XSS) is essential in web development. Following these practices will help you create secure and resilient PHP applications.
Protecting Against SQL Injection
SQL injection is a common vulnerability that occurs when user input is embedded directly into SQL queries. Use prepared statements and parameterized queries with mysqli
or PDO
to prevent SQL injection:
<?php
$stmt = $conn->prepare("SELECT * FROM users WHERE username = ?");
$stmt->bind_param("s", $username);
$username = $_POST['username'];
$stmt->execute();
$result = $stmt->get_result();
?>
In this example, bind_param
safely binds user input to the query, preventing malicious SQL injection attacks.
Preventing Cross-Site Scripting (XSS)
Cross-site scripting (XSS) occurs when attackers inject malicious scripts into your website. Use htmlspecialchars
to escape output and prevent XSS:
<?php
$user_input = "<script>alert('XSS');</script>";
echo htmlspecialchars($user_input, ENT_QUOTES, 'UTF-8');
?>
In this example, htmlspecialchars
converts special characters to HTML entities, preventing scripts from executing.
Validating and Sanitizing User Input
Always validate and sanitize user input to ensure it conforms to expected formats. PHP provides filter_var
for common validation tasks:
<?php
$email = filter_var($_POST['email'], FILTER_VALIDATE_EMAIL);
if ($email === false) {
echo "Invalid email address.";
}
?>
Here, filter_var
checks if the input is a valid email address.
Using Password Hashing
Use PHP’s password_hash
function to securely hash passwords before storing them in a database:
<?php
$password = "user_password";
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
// Verifying a password
if (password_verify($password, $hashed_password)) {
echo "Password is valid.";
}
?>
In this example, password_hash
securely hashes the password, and password_verify
checks if the input matches the stored hash.
Preventing Cross-Site Request Forgery (CSRF)
CSRF attacks trick authenticated users into performing unintended actions. Use CSRF tokens to protect forms:
<?php
session_start();
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
?>
<form method="post" action="submit.php">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
<input type="submit" value="Submit">
</form>
In this example, a CSRF token is generated and stored in the session, then included in the form as a hidden input.
Error Handling and Logging
Handle errors gracefully without exposing sensitive information. Log errors for debugging purposes and display user-friendly error messages:
<?php
ini_set("log_errors", 1);
ini_set("error_log", "errors.log");
try {
// Code that may cause an exception
} catch (Exception $e) {
error_log($e->getMessage());
echo "An error occurred. Please try again later.";
}
?>
In this example, errors are logged to errors.log
, and a generic message is displayed to the user.
Summary and Next Steps
In this chapter, we covered PHP security best practices, including protecting against SQL injection, XSS, CSRF, and securely handling user input. Applying these practices will help you build secure and resilient PHP applications. In the next chapter, we’ll work on a final project that integrates the skills and knowledge you've gained throughout this book.