PHP Security Checklist 2026: 10 Simple Steps to Protect Your Website
Most PHP websites get hacked through the same few mistakes. This plain-language PHP security checklist covers the 10 steps that stop them, with short code examples you can copy.

In this article (11 sections)ShowHide
- 1. Keep PHP updated
- 2. Never put user input straight into SQL
- 3. Check input before you use it
- 4. Escape everything you print (stop XSS)
- 5. Hash passwords properly
- 6. Add a CSRF token to forms
- 7. Lock down session cookies
- 8. Treat file uploads as dangerous
- 9. Use safe settings on the live server
- 10. Keep packages and plugins updated
- Quick answers
Most hacked PHP websites fall to the same few old mistakes. This PHP security checklist covers the 10 steps that stop almost all of them, each with code you can copy.
1. Keep PHP updated
An old PHP version is an open door. In October 2026, PHP fixed two critical holes that let attackers take over servers: see what PHP2Shell means and how to check your version. Use a supported version (8.3, 8.4 or 8.5) and install updates promptly.
2. Never put user input straight into SQL
This is how SQL injection happens:
// DANGEROUS: someone can type SQL into the email box
$email = $_POST['email'];
$result = $pdo->query("SELECT * FROM users WHERE email = '$email'");Use prepared statements, so input can never become code:
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = ?');
$stmt->execute([$_POST['email'] ?? '']);
$user = $stmt->fetch();3. Check input before you use it
$email = filter_var($_POST['email'] ?? '', FILTER_VALIDATE_EMAIL);
if ($email === false) {
exit('Please enter a valid email address.');
}Always check on the server too. Anyone can skip your browser checks.
4. Escape everything you print (stop XSS)
function e(?string $value): string
{
return htmlspecialchars($value ?? '', ENT_QUOTES, 'UTF-8');
}
echo '<p>Hello, ' . e($_GET['name'] ?? 'guest') . '</p>';Blade ({{ }}) and Twig do this for you automatically.
5. Hash passwords properly
Never plain text, md5() or sha1():
$hash = password_hash($password, PASSWORD_DEFAULT); // on sign-up
if (password_verify($password, $user['password_hash'])) {} // on login6. Add a CSRF token to forms
session_start();
if (empty($_SESSION['csrf'])) {
$_SESSION['csrf'] = bin2hex(random_bytes(32));
}Put <input type="hidden" name="csrf" value="<?= e($_SESSION['csrf']) ?>"> in each form, and check it on submit:
if (!hash_equals($_SESSION['csrf'] ?? '', $_POST['csrf'] ?? '')) {
http_response_code(403);
exit('Invalid request. Please refresh the page and try again.');
}7. Lock down session cookies
session_set_cookie_params(['secure' => true, 'httponly' => true, 'samesite' => 'Lax']);
session_start();
session_regenerate_id(true); // right after a successful login8. Treat file uploads as dangerous
Check the real file type, limit the size and pick the name yourself:
$allowed = ['image/jpeg' => 'jpg', 'image/png' => 'png', 'image/webp' => 'webp'];
$file = $_FILES['photo'] ?? null;
if (!$file || $file['error'] !== UPLOAD_ERR_OK || $file['size'] > 2 * 1024 * 1024) {
exit('Upload failed, or the file is bigger than 2 MB.');
}
$type = (new finfo(FILEINFO_MIME_TYPE))->file($file['tmp_name']);
if (!isset($allowed[$type])) {
exit('Only JPG, PNG or WebP images are allowed.');
}
$name = bin2hex(random_bytes(16)) . '.' . $allowed[$type];
move_uploaded_file($file['tmp_name'], __DIR__ . '/../uploads/' . $name);Store uploads outside the public folder, or disable PHP in the uploads folder.
9. Use safe settings on the live server
display_errors = Off
log_errors = On
expose_php = Off
session.cookie_httponly = 1
session.cookie_secure = 1
session.use_strict_mode = 110. Keep packages and plugins updated
composer auditRun it regularly. For WordPress, update plugins and themes, and delete unused ones.
Two more habits: use HTTPS everywhere, and keep tested backups (see our backup guide).
Quick answers
Does Laravel make my site secure automatically? It handles most of this, but raw SQL with user input, unescaped {!! !!} output or an old PHP version can still undo it.
Is md5 with a salt okay for passwords? No. It's far too fast to guess. Use password_hash().
Want a second pair of eyes on your PHP website? Talk to our team about a security review.


