PHP Security: How to Protect Your Site from SQL Injections and XSS

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Your PHP Site in the Crosshairs: Why Hackers Love Weak Security

\n\n

Imagine: you spent weeks developing a cool blog or online store in PHP. The site works, visitors are happy. But one "fine" day you log into the admin panel, and it's empty. The database is deleted. Or, even worse, the homepage is plastered with casino ads, and all users are redirected to a phishing site.

\n\n

Sound familiar? Unfortunately, for many beginner (and not only) PHP developers, this is a reality. The most frustrating part is that 90% of such attacks happen due to two seemingly simple vulnerabilities: SQL injections and cross-site scripting (XSS). Hackers don't crack complex encryption algorithms—they simply exploit programmer carelessness.

\n\n

In this article, we won't give boring lectures. We'll break down how these attacks work "from the inside," and most importantly, learn how to set up reliable defenses. You'll find out how to make your PHP code a tough nut for attackers to crack. Let's go!

\n\n

SQL Injections: When the Database Speaks in the Hacker's Voice

\n\n

SQL injection is a type of attack where an attacker "injects" malicious SQL code into a database query. If your application doesn't filter input data, the hacker can force the database to execute any command: from stealing passwords to completely deleting tables.

\n\n

What Does Vulnerable Code Look Like?

\n\n

Imagine a simple login form. A beginner's code often looks like this:

\n\n
<?php\n$login = $_POST['login'];\n$password = $_POST['password'];\n\n// DANGEROUS! Direct substitution into the query\n$query = "SELECT * FROM users WHERE login = '$login' AND password = '$password'";\n$result = mysqli_query($link, $query);\n?>
\n\n

It seems logical. But what happens if an attacker enters the following string into the login field:

\n\n
' OR '1'='1
\n\n

The query becomes:

\n\n
SELECT * FROM users WHERE login = '' OR '1'='1' AND password = '...'
\n\n

The condition '1'='1' is always true. Congratulations, the hacker just logged in without a password! And if they enter '; DROP TABLE users; --, your users table will be gone forever.

\n\n

Escaping vs. Prepared Statements: Which to Choose?

\n\n

Many old textbooks recommend using the mysqli_real_escape_string() function. Yes, it escapes special characters, but that's last century. This method has drawbacks:

\n\n
    \n
  • It's easy to forget to apply the function to every variable.
  • \n
  • It doesn't protect against all types of injections (e.g., when working with LIKE).
  • \n
  • The code becomes messy and hard to maintain.
  • \n
\n\n

The modern and correct way is prepared statements via PDO or MySQLi. They separate the query logic from the data. The database first "compiles" the query template and then substitutes the data into it. Even if a hacker passes malicious code, it will be treated as an ordinary string, not as part of an SQL command.

\n\n

Writing Secure Code with PDO

\n\n

Here's what a secure database query using PDO (PHP Data Objects) should look like:

\n\n
<?php\n// Connecting to the database\n$dsn = 'mysql:host=localhost;dbname=mydb;charset=utf8mb4';\n$pdo = new PDO($dsn, 'user', 'password');\n\n// Setting error mode (IMPORTANT for debugging, but remove in production)\n$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);\n\n// Preparing the query (template)\n$stmt = $pdo->prepare("SELECT * FROM users WHERE login = :login AND password = :password");\n\n// Binding parameters and executing\n$stmt->execute([\n    ':login' => $_POST['login'],\n    ':password' => $_POST['password']\n]);\n\n$user = $stmt->fetch();\n\nif ($user) {\n    echo "Welcome!";\n} else {\n    echo "Invalid login or password";\n}\n?>
\n\n

Ab

Blogs

Book Recommendations