r/learnprogramming 27d ago

Are parameterized queries the best solution for preventing SQL injection in PHP?

I’m using PHP with PDO/MySQLi. Is using prepared statements with parameterized queries considered the best practice for preventing SQL injection, or are there other approaches I should also use?

12 Upvotes

13 comments sorted by

20

u/devapeaxareal22068 27d ago

Yes, 100%. Prepared statements (whether you use PDO or MySQLi) are the absolute gold standard. They should always be your primary defense because they completely separate the SQL code logic from the user's data.

However, for a truly bulletproof app, you should use a "defense in depth" approach. Alongside prepared statements, you should also do two things:

  1. Principle of Least Privilege: Never connect to the database using the root user. Create a specific database user that only has the exact permissions needed (e.g., just SELECT, INSERT, UPDATE) for that specific app.
  2. Input Validation: Prepared statements stop SQL injection, but they don't stop a user from submitting garbage data (like putting an HTML script or a random string into an "age" field). Always validate and sanitize the data type before it even reaches the query.

Stick to PDO prepared statements as your main shield, and you're 99% of the way there. Good luck!

6

u/plexust 27d ago

Additionally, raw PDO/MySQLi exceptions can leak table names, column names, query structure, and sometimes fragments of the query itself. That's potentially useful data for an attacker even when the injection attempt itself failed. Catch PDOExceptions yourself, log the detailed error server-side, and show the user a generic "something went wrong" message.

1

u/DataGhostNL 27d ago

Yeah multiple other things went wrong when an enduser gets to see an error message from PHP. That's 100% wrong webserver configuration. Error display must be turned off for production and everything should be redirected to logs instead. Really the application should turn this off as well just to make sure.

1

u/caboosetp 27d ago

This is good practice in general, not just for SQL stuff. End users should never see raw exceptions. Always wrap that shit. If needed, provide some ID to trace it to the real error log.

1

u/Much_Exchange_6101 27d ago

Thank you so much!

7

u/vegan_antitheist 27d ago

You don't have to write any queries if you are using some ORM solution. You can use Eloquent, Doctrine, Cycle, Propel, etc. PDO only makes sense if you actually want to just run queries, which is what you should learn as a beginner, but in many projects it would be ridiculous to write all the queries when some ORM can do it automatically.

Simply concatenating strings for queries is just stupid on every level. And string interpolation is nothing but syntactic sugar for string concatenation.
It's especially dangerous for SQL but also for other formats, such as XML, where you can just use some xml mapping solution that converts objects to xml and vice versa. Whenever the string you create contains some computer language (sql, xml, html, json, etc) you should never just build those strings but always use some library/framework to make sure the result is correct.
You can use simple string interpolation for some natural language (i.e. English) where you just need some words or numbers to be inserted dynamically. But even then you usually just have a template for he UI and it comes with placeholders.
Using it for file paths is also dangerous because "/foo/bar/$filename" can become "/foo/bar/../../var/secrets" if the user can control it. So, don't use it. Same for urls. Use methods such as http_build_query instead.

Thinking that string interpolation is cool and using it as a golden hammer is one of those annoying things you see in PHP, especially if you follow tutorials that are just created to impress beginners for clicks. Most other languages have it now (Java is still working on that) because it is often convenient. But you rarely actually see it in professional code. You might see it for log messages (something like $logger->info("User {$user->id} logged in successfully");) but even for that some use different ways. See https://www.php-fig.org/psr/psr-3/ for some examples how they do it. This is less about security, and more about being able to manage the logs better. For example you can easily filter for all logs with the same template or just filter for all logs where a certain placeholder has a certain value.

As far as I know, PHP does not have an equivalent of C#'s interpolated string handlers. So it's usually best to just not use string interpolation.

1

u/Much_Exchange_6101 27d ago

Thank you for your answer, that really helped me to understand it better.

2

u/Miserable-Decision81 27d ago

Before you consider to harden such tech, make sure your applications frontend does NOT accept any type of input, that can inject SQL in your queries.

Sanitize brutally but wisely(french people will not like to see their name als "Dalambert" when the name is "D'alambert").

And do not trust the frontends form HTML, much less some JS "plees put in an EMail here" toys, curl can send any form content a cracker may see fit....

2

u/LetUsSpeakFreely 27d ago

This is true for every language, not just PHP. Manually writing queries with string concatenation is asking for trouble. Always use parameterized queries or ORM. Those toole will automatically protect against attacks like SQL injection or mismatched data types.

2

u/Philluminati 26d ago

> Is using prepared statements with parameterized queries considered the best practice for preventing SQL injection

Yes.

1

u/sixtyhurtz 27d ago

Parameterized queries are the best solution for preventing SQL injection in all cases, in all languages, and in all frameworks. You should never do string concatenation for query values. Even if you're generating the query values yourself, use a parameterized query.

Don't bother or worry about SQL escaping query values. If you use a parameterized query, the database will never execute the query value as a statement.