Writing Code Isn't Enough; It Must Be Secure

As a web developer, you have a responsibility to protect your users' data and maintain the integrity of your application. A single security vulnerability can have devastating consequences. This lesson covers the most common web vulnerabilities and the essential best practices in PHP to prevent them.

The number one rule of web security is: Never, ever trust user input. Treat all data from users ($_GET, $_POST, $_COOKIE, etc.) as potentially malicious until you have validated and sanitized it.


1. Prevent SQL Injection (Revisited)

We covered this in the CRUD lesson, but it is so important it's worth repeating. SQL Injection occurs when an attacker injects malicious SQL code into your queries, allowing them to read or even delete your entire database.

The Solution: Always use prepared statements with placeholders. This separates the SQL command from the data, making it impossible for an attacker's input to be executed as code.

// GOOD: The user's input is treated as data, not code.
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ?");
$stmt->execute([$_POST['username']]);

2. Prevent Cross-Site Scripting (XSS)

XSS occurs when an attacker injects malicious JavaScript into your webpage, which then runs in the browsers of other users. This can be used to steal session cookies, deface your site, or redirect users to malicious websites.

The Solution: Always escape output. Whenever you display user-generated content (like comments, usernames, or search results) on a page, you must sanitize it to neutralize any HTML or JavaScript code. PHP's htmlspecialchars() function is perfect for this.

<?php
    // Assume $user_comment contains: <script>alert('You have been hacked!');</script>
    
    // BAD: This will execute the malicious script in the browser.
    // echo $user_comment;

    // GOOD: This converts the script into harmless text that can be safely displayed.
    echo htmlspecialchars($user_comment, ENT_QUOTES, 'UTF-8');
?>

3. Prevent Cross-Site Request Forgery (CSRF)

CSRF is a tricky attack where an attacker tricks a logged-in user into unknowingly submitting a request to your web application. For example, a user might click a link on a malicious site that secretly submits a form to your site to change their email address or delete their account.

The Solution: Use Anti-CSRF Tokens. The logic is as follows:

  1. When you display a form, generate a unique, random, single-use token.
  2. Store this token in the user's session and also place it in a hidden input field in the form.
  3. When the form is submitted, check if the token from the form matches the one in the session.
  4. If they match, the request is legitimate. If they don't, reject it.

This process ensures that only forms originating from your own site can be successfully submitted. Modern frameworks like Laravel handle this for you automatically.


4. Hashing Passwords

This is a critical rule: NEVER store passwords in plain text in your database. If your database is ever compromised, all of your users' passwords will be stolen. The correct way to store passwords is by hashing them.

Hashing is a one-way process. You cannot "un-hash" a password. You can only compare a submitted password to a stored hash. PHP has simple, secure, built-in functions for this.

<?php
    $submitted_password = "my_secret_password";

    // --- When a user registers ---
    // password_hash() creates a secure hash with a random salt.
    $hashed_password = password_hash($submitted_password, PASSWORD_DEFAULT);
    // You would store $hashed_password in your database.

    // --- When a user logs in ---
    // Retrieve the hash from the database for that user.
    // password_verify() securely compares the submitted password to the stored hash.
    if (password_verify($submitted_password, $hashed_password)) {
        echo "Password is correct!";
    } else {
        echo "Invalid password.";
    }
?>

By following these fundamental security practices, you can protect your application and your users from the most common attacks on the web. A well-maintained framework like Laravel can make security even easier by providing many of these protections out of the box.