How to prevent code injection attacks in PHP? How to prevent code injection attacks in PHP? php php

How to prevent code injection attacks in PHP?


  • mysql_real_escape_string used when insert into database
  • htmlentities() used when outputting data into webpage
  • htmlspecialchars() used when?
  • strip_tags() used when?
  • addslashes() used when?

htmlspecialchars() used when?

htmlspecialchars is roughly the same as htmlentities. The difference: character encodings.

Both encode control characters like <, >, & and so on used for opening tags etc. htmlentities also encode chars from other languages like umlauts, euro-symbols and such. If your websites are UTF, use htmlspecialchars(), otherwise use htmlentities().

strip_tags() used when?

htmlspecialchars / entities encode the special chars, so they're displayed but not interpreted. strip_tags REMOVES them.

In practice, it depends on what you need to do.

An example: you've coded a forum, and give users a text field so they can post stuff. Malicious ones just try:

pictures of <a href="javascript:void(window.setInterval(function () {window.open('http://evil.com');}, 1000));">kittens</a> here

If you don't do anything, the link will be displayed and a victim that clicks on the link gets lots of pop-ups.

If you htmlentity/htmlspecialchar your output, the text will be there as-is. If you strip_tag it, it simply removes the tags and displays it:

pictures of kittens here

Sometimes you may want a mixture, leave some tags in there, like <b> (strip_tags can leave certain tags in there). This is unsafe too, so better use some full blown library against XSS.

addslashes

To quote an old version of the PHP manual:

Returns a string with backslashes before characters that need to be quoted in database queries etc. These characters are single quote ('), double quote ("), backslash () and NUL (the NULL byte).

An example use of addslashes() is when you're entering data into a database. For example, to insert the name O'reilly into a database, you will need to escape it. It's highly recommeneded to use DBMS specific escape function (e.g. mysqli_real_escape_string() for MySQL or pg_escape_string() for PostgreSQL), but if the DBMS you're using does't have an escape function and the DBMS uses \ to escape special chars, you can use this function.

The current version is worded differently.


I thought of this quick checklist:

  • Always use HTTPS, without HTTPS your site is totally unencrypted. And no, client-side encrypting things and sending them won't work, think about it. Invalid HTTPS certificates also make you vulnerable to a MITM attack. Just use Let's Encrypt if you can't afford a certificate.
  • Always use htmlspecialchars() on any output from your PHP code, that is, or contains a user input. Most templating engines help you do that easily.
  • Use HTTP-only flag in your php.ini to prevent scripts from accessing your cookies
  • Prevent session-related problems
    • Never expose user's PHPSESSID (session ID) outside the cookie, if anybody gets to know a Session ID of somebody else, they can simply use it to login to their account
    • Be very careful with the Remember me function, show a little warning maybe.
    • Refresh session ID when the user signs in (or whatever appropriate)
    • Timeout inactive sessions
  • Never trust a cookie, it can be changed, removed, modified, and created by a script/user at any moment
  • Prevent SQL-related problems
    • Always use prepared statements. Prepared statements causes the user input to be passed separately and prevents SQL Injection
    • Make your code throw an exception when it fails. Sometimes your SQL server might be down for some reason, libraries like PDO ignore that error by default, and log a warning in the logs. This causes the variables you get from the DB to be null, depending on your code, this may cause a security issue.
    • Some libraries like PDO emulate prepared statements. Turn that off.
    • Use UTF-8 encoding in your databases, it allows you to store virtually any character and avoid encoding-related attacks
    • Never concatenate anything to your query. Things like $myquery = "INSERT INTO mydb.mytable (title) VALUES(" . $user_input . ")" pretty much mean you have a huge security risk of an SQL injection.
  • Store uploaded files in random, extension-less filenames. If a user uploads a file with .php file extension then whenever your code loads that file it executes it, and enables the user to execute some backend code
  • Make sure you're not vulnerable to a CSRF attack.
  • Always update your PHP copy to ensure the latest security patches and performance improvements


Only encode data at the point where it goes into the system it needs to be encoded for — otherwise you will run into situations where you want to manipulate the real data.

For SQL injection - use bound variables as described in How can I prevent SQL injection in PHP? (it talks about prepared statements, but it is the binding that gives you protection, not the preparation).

For XSS - if you are writing into HTML at point where either HTML or text is specified. Use htmlentities at the point where you generate your document. I would avoid storing the data in that form in the database (except possible in a write-rare-read-often system where CPU performance/disk access times were becoming and issue - then I would have a raw_ and an html_ version of the column … or just use memcached or similar).

If you are letting users enter URLs then you need to be more careful, as javascript:do_evil() is a valid URI that will execute (e.g. as an href for a clicked upon link or (in some browsers) the src of an image that is just loaded).