Lesson 20: Writing Secure PHP Code

Web applications are often targets for malicious attacks. This lesson focuses on writing secure PHP code to mitigate common vulnerabilities, including SQL Injection, Cross-Site Scripting (XSS), and Cross-Site Request Forgery (CSRF).


Lesson Outline

  1. Introduction to Secure PHP Development
  2. Preventing SQL Injection
  3. Mitigating Cross-Site Scripting (XSS)
  4. Safeguarding Against Cross-Site Request Forgery (CSRF)
  5. Best Practices for Secure PHP Development

20.1 Introduction to Secure PHP Development

Why Security Matters?

  • Applications handle sensitive data like user credentials, financial details, and personal information.
  • Common vulnerabilities can compromise data integrity, confidentiality, and availability.

Common Web Vulnerabilities

  1. SQL Injection: Exploiting vulnerabilities in database queries to execute malicious SQL code.
  2. XSS: Injecting malicious scripts into web pages to affect other users.
  3. CSRF: Tricking users into performing actions without their knowledge.

20.2 Preventing SQL Injection

What is SQL Injection?

  • SQL Injection occurs when user input is directly embedded into SQL queries without proper sanitization.
  • Example:
    php
    $username = $_GET['username'];
    $query = "SELECT * FROM users WHERE username = '$username'";
    • An attacker could input: ' OR '1'='1 to bypass authentication.

Mitigation Techniques

1. Use Prepared Statements

Prepared statements separate SQL code from user input, preventing malicious input from altering the query.

Example with PDO:

php
<?php
require 'db.php'; // Include database connection
$username = $_POST[‘username’];
$password = $_POST[‘password’];

$stmt = $conn->prepare(“SELECT * FROM users WHERE username = :username AND password = :password”);
$stmt->bindParam(‘:username’, $username);
$stmt->bindParam(‘:password’, $password);
$stmt->execute();

$user = $stmt->fetch(PDO::FETCH_ASSOC);

if ($user) {
echo “Login successful.”;
} else {
echo “Invalid credentials.”;
}
?>

Example with MySQLi:

php
$stmt = $conn->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
$stmt->bind_param("ss", $username, $password);
$stmt->execute();

2. Validate and Sanitize Input

Always validate and sanitize user input before using it in your application.

Sanitization Example:

php
$username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING);
$password = filter_input(INPUT_POST, 'password', FILTER_SANITIZE_STRING);

3. Use ORM (Object-Relational Mapping) Tools

Tools like Eloquent in Laravel automatically handle SQL queries securely.


20.3 Mitigating Cross-Site Scripting (XSS)

What is XSS?

  • XSS occurs when attackers inject malicious scripts into web pages viewed by other users.
  • Example:
    php
    echo "<p>Welcome, " . $_GET['name'] . "</p>";
    • Input: <script>alert('Hacked!')</script> executes JavaScript.

Mitigation Techniques

1. Escape Output

Use built-in functions to escape output before rendering it on a page.

PHP Built-In Functions:

php
echo htmlspecialchars($name, ENT_QUOTES, 'UTF-8');
  • Converts < to &lt; and > to &gt;.

2. Validate Input

Ensure user input is as expected using validation rules.

Example:

php
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);

3. Use a Templating Engine

Engines like Blade (Laravel) or Twig (Symfony) automatically escape output.


4. Content Security Policy (CSP)

CSP restricts the sources from which scripts can be loaded.

Example: Add the following HTTP header:

php
Content-Security-Policy: script-src 'self';

20.4 Safeguarding Against Cross-Site Request Forgery (CSRF)

What is CSRF?

  • CSRF exploits the trust a web application has in the user’s browser by tricking the user into executing unwanted actions.

Example: A malicious link:

html
<a href="http://example.com/delete_account?id=1">Delete Account</a>

If the user is logged in, clicking the link deletes their account.


Mitigation Techniques

1. Use CSRF Tokens

Generate and validate CSRF tokens for every form submission.

Generating a CSRF Token:

php
<?php
session_start();
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
?>

Embedding in a Form:

html
<form action="submit.php" method="POST">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
<button type="submit">Submit</button>
</form>

Validating the CSRF Token:

php
<?php
session_start();
if ($_POST['csrf_token'] !== $_SESSION['csrf_token']) {
die("CSRF validation failed.");
}
?>

2. Use Framework Features

Frameworks like Laravel handle CSRF protection automatically. Include @csrf in Blade templates.

Example:

html
<form action="/submit" method="POST">
@csrf
<button type="submit">Submit</button>
</form>

3. Use Same-Site Cookies

Set cookies to SameSite mode to prevent them from being sent with cross-origin requests.

Example:

php
setcookie('key', 'value', ['samesite' => 'Strict']);

20.5 Best Practices for Secure PHP Development

  1. Keep Software Updated
    • Regularly update PHP, libraries, and frameworks to patch security vulnerabilities.
  2. Error Handling
    • Display generic error messages to users and log detailed errors for developers.

Example:

php
ini_set('display_errors', 0);
error_log('Error occurred: ' . $exception->getMessage());
  1. Use HTTPS
    • Ensure all communications are encrypted using HTTPS.
  2. Set Proper File Permissions
    • Restrict permissions to sensitive files (.env, configuration files).
  3. Secure Session Management
    • Use secure and httpOnly flags for cookies.

Example:

php
session_set_cookie_params([
'secure' => true,
'httponly' => true,
]);
session_start();
  1. Avoid Storing Sensitive Data in the Codebase
    • Store API keys and passwords in environment variables.
  2. Use Secure Hashing for Passwords
    • Use password_hash() and password_verify() for managing passwords.

Example:

php
$hashedPassword = password_hash($password, PASSWORD_BCRYPT);
if (password_verify($password, $hashedPassword)) {
echo "Password is valid.";
}

Activities and Exercises

  1. Prevent SQL Injection:
    • Create a login form and secure it using prepared statements.
  2. Mitigate XSS:
    • Build a comment system and ensure all inputs are sanitized and escaped.
  3. Implement CSRF Protection:
    • Add CSRF tokens to a form submission and validate them server-side.

Assignment

  1. Secure an existing PHP project by:
    • Replacing raw SQL queries with prepared statements.
    • Escaping all user-generated output.
    • Adding CSRF protection to forms.
  2. Implement a secure user authentication system:
    • Use secure password hashing.
    • Add rate-limiting to prevent brute-force attacks.

Summary

In this lesson, you learned:

  1. How to prevent SQL Injection using prepared statements and input validation.
  2. How to mitigate XSS using output escaping and CSP.
  3. How to protect against CSRF using tokens and same-site cookies.

Following these best practices ensures your PHP applications remain secure against common vulnerabilities. Let me know if you need more guidance or examples!


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *