Lab 10: Security Hardening

Time: 40 minutes | Level: Advanced | Docker: docker run -it --rm php:8.3-cli bash

Security is not a feature — it's a discipline. This lab covers PHP's security APIs: password hashing, CSRF protection, session hardening, Content Security Policy, SQL injection prevention, and runtime hardening directives.


Step 1: Secure Password Hashing — Argon2id

<?php
// Argon2id is the recommended algorithm (PHP 7.3+)
$hash = password_hash('MySecretPass123!', PASSWORD_ARGON2ID, [
    'memory_cost' => 65536,   // 64MB RAM
    'time_cost'   => 4,        // 4 iterations
    'threads'     => 1,        // Parallelism
]);

echo "Hash: " . substr($hash, 0, 30) . "...\n";
echo "Algorithm: " . password_get_info($hash)['algoName'] . "\n";

// Verify
echo "Correct password: " . (password_verify('MySecretPass123!', $hash) ? 'valid' : 'invalid') . "\n";
echo "Wrong password:   " . (password_verify('wrong', $hash) ? 'valid' : 'invalid') . "\n";

// Check if rehash needed (after cost increase)
$needsRehash = password_needs_rehash($hash, PASSWORD_ARGON2ID, ['memory_cost' => 131072]);
echo "Needs rehash (higher cost): " . ($needsRehash ? 'yes' : 'no') . "\n";

// Compare bcrypt vs argon2id
echo "\nBcrypt hash:   " . substr(password_hash('pass', PASSWORD_BCRYPT), 0, 30) . "...\n";
echo "Argon2id hash: " . substr(password_hash('pass', PASSWORD_ARGON2ID), 0, 30) . "...\n";

📸 Verified Output:

💡 Never use md5() or sha1() for passwords. Always use password_hash() — it handles salting automatically.


Step 2: CSRF Token Protection

📸 Verified Output:


Step 3: Secure Random & Cryptographic Functions

📸 Verified Output:


Step 4: Session Security

📸 Verified Output:


Step 5: SQL Injection Prevention with PDO

📸 Verified Output:


Step 6: Content Security Policy & Security Headers

📸 Verified Output:


Step 7: Input Validation & Output Escaping

📸 Verified Output:


Step 8: Capstone — Secure Authentication Flow

📸 Verified Output:


Summary

Threat
Defense
PHP Function/Feature

Weak passwords

Argon2id hashing

password_hash(PASSWORD_ARGON2ID)

CSRF

HMAC token + timing-safe compare

hash_hmac(), hash_equals()

Session fixation

Regenerate on login

session_regenerate_id(true)

XSS

Output encoding

htmlspecialchars(ENT_QUOTES)

SQL injection

Prepared statements

PDO::prepare()->execute([...])

Timing attacks

Constant-time compare

hash_equals()

Insecure random

CSPRNG

random_bytes(), random_int()

Path traversal

realpath() + prefix check

str_starts_with(realpath($p), $base)

Header injection

header() with validation

Never pass user input directly

Information leakage

Error reporting off

display_errors=Off in production

Last updated