This article does not replace a good knowledge of security principles in PHP, but can give you some good advices that really boost security.
There is nothing to copy/paste straight forward to your php files. However, if you understand the different points and implement them according to your needs and context, they can give you long-term benefits.
This article is the second of our series dedicated to PHP security. The first article “How to protect your website: PHP Security tips and tricks #1” gives you basic guidelines for PHP configuration, updates, data filtering and sanitization, as well as code organization.
We will now look at the most classical hacking attacks against PHP websites.
Defending yourself against known and typical attacks
SQL injections are really devastating, but can be quite simply avoided by following simple steps.
First, ensure that your database user privileges are limited (principle of least privileges). For instance, actions performed by a front-office user should be executed in the database by a user that only have rights on front-end related tables. If no need to delete data on a specific table, then do not give delete rights to that user on that table.
Then, sanitize all inputs for SQL instructions (refer to the filtering/escaping section on our first article).
A more effective way to avoid SQL injection flaws is to use prepared statements.
How to implement prepared statements: http://php.net/manual/en/pdo.prepared-statements.php
Using command executions through your PHP code is very powerful, but also very dangerous if not used with precautions.
Therefore, it is recommended to disable dangerous functions with the disable_functions directive (in the php.ini file).
Once deactivated, these functions will not be accessible to hacker writing his own PHP code (through another potential flaw).
disable_functions = show_source, exec, shell_exec, system, passthru, proc_open, popen, curl_exec, curl_multi_exec, parse_ini_file, show_source
When using one of these functions, pay extreme attention to parameters. Ensure data is properly validated against whitelists, and/or filtered.
Entire commands and arguments can be escaped with built-in functions escapeshellcmd (http://php.net/manual/en/function.escapeshellcmd.php) and escapeshellarg (http://php.net/manual/en/function.escapeshellarg.php).
Sessions rely on session IDs.
One common attack is the session fixation attack, which consists in giving a session ID to a victim before they log in, and then using that same session ID to use the victim’s session.
To avoid such problems, some rules must be followed:
do not accept session IDs coming from URLs or POST requests (session.use_only_cookies directive in php.ini).
protect session cookies with HttpOnly and Secure flags (session.cookie_secure and session.cookie_httponly parameters in php.ini file).
set a better entropy to your session ID by setting session.entropy_file = /dev/urandom in php.ini, on linux systems.
A key point is to regenerate session IDs at a critical moment: when logging users.
You can trigger a session ID renewal by calling the session_regenerate_id function (http://php.net/manual/en/function.session-regenerate-id.php).
Additional important steps can be implemented to add security at different levels (defense in depth):
– keeping track of the user’s last activity in the session, to detect suspicious behaviors on critical functions.
– saving the user agent in the session and verifying it at key points.
– checking the IP address is not recommended, as it can change dynamically, for instance on mobile networks.
Protecting your website against XSS is quite simple, you have to apply the “filter on input, escape on output” principle.
But do not forget to apply it to all parameters, including hidden parameters, GET/POST parameters, cookies, https headers.
Great complementary XSS protection can also be achieved via some HTTP headers, which we detailed in a previous article about HTTP headers for security.
Many attacks leverage the fact that URLs and forms can be manipulated.
Expect the unexpected, and validate parameters with filters and whitelists.