Most PHP security issues aren't exotic — they're the same handful of mistakes repeated across projects. Here's a practical rundown of the big ones.
SQL injection via string concatenation. Building a query by directly concatenating request input into the SQL string lets an attacker inject arbitrary SQL through that input. The fix is non-negotiable: always use PDO or mysqli with prepared statements and bound parameters, with no exceptions for "just this one query."
Cross-site scripting (XSS) from unescaped output. Echoing user-supplied content directly into HTML — a comment, a username, a search term — lets an attacker inject a script tag that runs in other visitors' browsers. Always pass user-generated content through htmlspecialchars() before rendering it into HTML.
Missing CSRF protection on state-changing forms. Without a CSRF token, a malicious site can trick a logged-in user's browser into submitting a form on your site without their knowledge. Generate a random token per session, embed it as a hidden field, and verify it server-side on every POST request.
Storing passwords insecurely. Plain text is the obvious sin, but even MD5 or SHA1 hashing without salting is considered broken today. Use password_hash() and password_verify() — they handle salting and use a strong algorithm by default, and there's no good reason to roll your own.
Trusting file uploads blindly. Accepting any uploaded file and storing it with its original name and extension can let an attacker upload a PHP script disguised as an image. Validate the actual file content (not just the extension), rename uploads to a generated filename, and store them outside the web root when possible.
Leaking errors and stack traces in production. Detailed error messages are invaluable in development but hand an attacker a map of your application's internals in production. Set display_errors off and error_reporting to log errors to a file instead, once the app is live.
Not validating input at every entry point. Data from forms, URL parameters, cookies, and even HTTP headers should all be treated as untrusted until validated. A field that's "safe" because your own frontend enforces a format isn't actually safe — nothing stops a request from bypassing your frontend entirely.
Each of these has a specific, well-known fix. The discipline isn't in knowing the fix exists — it's applying it consistently, on every form and every query, not just the ones that feel risky.
Comments (0)
No comments yet — be the first to share your thoughts.
Leave a Comment