PHP powers over three-quarters of all dynamic web applications worldwide. Because of its ubiquity, PHP applications are frequent targets of automated vulnerability scanners, brute-force bots, and malicious exploit scripts. Securing a modern PHP application requires defense-in-depth across database access, user input sanitization, authentication tokens, and HTTP headers.

1. Defeating SQL Injection with Prepared Statements

SQL Injection (SQLi) remains one of the most critical web vulnerabilities. It occurs when untrusted user inputs are concatenated directly into SQL queries. The defensive rule is absolute: Never concatenate raw input into database queries. Always use parameterized prepared statements.

// INSECURE VULNERABILITY (Vulnerable to bypass and data exfiltration):
// $query = "SELECT * FROM users WHERE email = '" . $_POST['email'] . "'";

// SECURE: Using PDO Prepared Statements with Parameter Binding
$stmt = $pdo->prepare('SELECT id, password_hash, role FROM users WHERE email = :email AND status = :status LIMIT 1');
$stmt->execute([
    'email'  => $inputEmail,
    'status' => 'active'
]);
$user = $stmt->fetch();

Prepared statements separate the query structure from the data parameters. Even if a user enters SQL syntax like ' OR 1=1; --, the database engine treats it purely as literal string data.

2. Defending Against Cross-Site Scripting (XSS)

Cross-Site Scripting occurs when an application renders unsanitized user data directly into HTML, allowing attackers to execute arbitrary JavaScript in victim browsers, steal session cookies, or trigger unauthorized actions. Implement context-aware escaping:

// In native PHP:
echo htmlspecialchars($userInput, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');

// In CodeIgniter 4 (Built-in esc() helper with context support):
<span><?= esc($userName, 'html') ?></span>
<a href="<?= esc($profileUrl, 'attr') ?>">Profile</a>

3. Cross-Site Request Forgery (CSRF) Protection

CSRF attacks trick an authenticated user's browser into submitting unauthorized POST requests to an application where they are logged in. Protect all state-changing endpoints with cryptographically secure CSRF tokens:

<!-- Form embedding CSRF token -->
<form action="/account/update" method="POST">
    <input type="hidden" name="<?= csrf_token() ?>" value="<?= csrf_hash() ?>">
    <input type="text" name="display_name" value="Umakant Yadav">
    <button type="submit" class="btn btn-primary">Update Profile</button>
</form>

In your backend middleware, reject any POST/PUT/DELETE request whose token is missing or does not match the server-side session hash.

4. Modern Password Hashing with Argon2id

Never use obsolete algorithms like MD5 or SHA-256 for password storage. GPU cracking clusters can compute billions of SHA-256 hashes per second. Modern PHP includes native support for Argon2id and Bcrypt:

// Securely hash a password during user registration
$hashedPassword = password_hash($plainPassword, PASSWORD_ARGON2ID, [
    'memory_cost' => 65536, // 64 MB
    'time_cost'   => 4,     // 4 iterations
    'threads'     => 2      // 2 parallel threads
]);

// Verify password on login
if (password_verify($submittedPassword, $user['password_hash'])) {
    // Password verified!
    if (password_needs_rehash($user['password_hash'], PASSWORD_ARGON2ID)) {
        // Upgrade hash if cost parameters have increased
    }
}

5. Hardening PHP Session Security

Session hijacking allows attackers to impersonate authenticated users. Configure session cookies with strict security attributes in your php.ini or framework configuration:

// Configure secure session cookie parameters
session_start([
    'cookie_httponly' => true,      // Disallow JavaScript access to document.cookie
    'cookie_secure'   => true,      // Only transmit over HTTPS
    'cookie_samesite' => 'Lax',     // Mitigate CSRF
    'use_strict_mode' => true,      // Prevent session fixation
]);

// Regenerate session ID upon privilege changes (e.g. login)
session_regenerate_id(true);

6. Mandatory HTTP Security Headers

Enforce strong defensive HTTP response headers at the web server level (Apache .htaccess or Nginx):

<IfModule mod_headers.c>
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set X-XSS-Protection "1; mode=block"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
    Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
</IfModule>

Conclusion

Security is an ongoing engineering process, not a one-time checklist. By consistently using prepared statements, context-aware output escaping, CSRF tokens, Argon2id password hashing, and hardened session parameters, your PHP applications remain resilient against evolving threats.