Hey PHP folks! How are you? Having a bad day? Are you hacked? Are you feeling unsafe from hackers? Don’t worry, I got you. Today are going to continue our PHP security post. Haven’t you read the part 1 of this blog post? If not I would like you to read it. There I have talked about data security, SQL injection, OS injection and code injection. If you are into security you know that these are the type of vulnerabilities that could exist in a PHP application. Are you sure that you are safe from hackers? Not quite sure right? So read the part 1 of this blog post and get to know the vulnerabilities better. Okay just like the last time we’ll focus on the vulnerabilities and the countermeasures for the particular vulnerability. Time for us to dive into PHP security again(happy-face).

5. Information Leakage

Information leakage is a common vulnerability that we see in PHP applications. You might think that it has a low impact but there is nothing called low impact when it comes to PHP security. Being 99% safe is not going to help, you have to make sure that your application is 100% safe. Look at the picture below.

Information Leakage

You see there goes the PHP vulnerability. This tells the attacker where the weak spot is. You don’t want to display this in a production server. How can we stop this?

Countermeasures

You have to set the proper setting in your php.ini file. If you don’t know where the php.ini is located, trying using a phpinfo() function to locate the php.ini file. Function shows information about PHP configuration settings on a given system. In the file search for the display_errors and and display_startup_errors tags and set them to off as show below.

display_errors = Off
display_startup_errors = Off

Okay we are not done yet. There are few more configurations to be done. Search for error_reporting. 

error_reporting = E_ALL

Then to make the application appear nice let’s set html_errors to off.

html_errors = Off

Okay we are almost done now. One more to go. To make sure we are aware what’s going on with the server, we have to log the all the errors.

log_errors = On

If you have completed all the above configurations you are good to go. Oh! wait you might be wondering what we are doing here. It’s nothing big, We are catching the PHP errors but we are not showing them instead we are logging them into a file. Also make sure to restart the Apache server once you make all these configurations.

What if you don’t have access to php.ini file in your production server. Don’t worry I got you. Let’s see how you make the same changes using PHP code snippets. That’s the beauty of PHP security. Below code snippet is extracted from Codeigniter index.php file. I have made few changes to the code snippet to make it better for you.

/*
*
* You can load different configurations depending on your
* current environment. Setting the environment also influences
* things like logging and error reporting.
*
* This can be set to anything, but default usage is:
*
* development
* testing
* production
*
* NOTE: If you change these, also change the error_reporting() code below
*/
define('ENVIRONMENT', isset($_SERVER['CI_ENV']) ? $_SERVER['CI_ENV'] : 'development'); // detect environment 
/*
*---------------------------------------------------------------
* ERROR REPORTING
*---------------------------------------------------------------
*
* Different environments will require different levels of error reporting.
* By default development will show errors but testing and live will hide them.
*/
switch (ENVIRONMENT)
{
 case 'development':
  error_reporting(-1);
  ini_set('display_errors', 1);
  break;
 case 'testing':
 case 'production':
  error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT);
  ini_set('display_errors', 0);
  break;
 default:
  header('HTTP/1.1 503 Service Unavailable.', TRUE, 503);
  echo 'The application environment is not set correctly.';
  exit(1); // EXIT_* constants not yet defined; 1 is EXIT_ERROR, a generic error.
}

What we are doing here is setting different configuration depending on the PHP application environment. Remember in a switch’s case, you can define html_errors, display_errors, display_startup_errors tags, etcAny configuration you want can go in a switch’s case.

Here is a little hack for you. For the detecting application environment you can use the code below. You can use the code below in your index.php.

//Below code is added by Dasun - dasunhegoda.com
//It detects appcation root and set the enviroment automatically 
$path = dirname(__FILE__);
switch ($path) {
 case '/Applications/MAMP/htdocs/php_blog_app':
  $env = "development"; 
  break;

 default:
  $env = "production";
  break;
}
define('ENVIRONMENT', $env);

Hope you got everything right. Moving on another way of information leakage is over-specific feedback. As an example if a user is trying to login to your application and you couldn’t find the particular user in the database, you could echo something like ‘There is no username as “whatever-user-input” ‘. So what attacker might do is try another username and check the error. If the error is not shown it means that the user exists. Now it’s matter of time the attacker find out the password. you should be more concerned with the error msgs you output to the user. You should echo something like “Username or Password is invalid”. It’s much more generic.

6. Sensitive Data Exposure

This is somewhat similar to information leakage. Think about your data. Do you really need to store credit numbers? If not don’t store them because data that you don’t have can’t be stolen. If you are storing passwords in your database you have to hash them. Never store the passwords as plaintext. Sensitive data should always be encrypted. That’s the rule number one. Let’s talk about password. Modern days using hashing algorithms such as md5() considered to be a bad practise. You want to know why? It’s because it can be cracked in seconds. If you don’t trust me google for “md5 decorators”, you will find tons of site.

Countermeasures

So the problem is what can you do about it. You can use a well tested library in your application. Let me give you few examples. ircmaxell/password-compat or zendframework/zend-crypt. There you go. Check them out. They are considered to be hacker-proof libraries.

Also If you are transferring sensitive data over the network, make sure they are encrypted using SSL(https). Otherwise eavesdroppers can listen into the traffic and get your data. You don’t want that happen. Do you?

7. Cross-site scripting (XSS)

XSS is a vital part of PHP security. XSS A.K.A Cross-site scripting consist of injecting JavaScript snippet to the site which can lead to scary situations. Most of time JavaScript are injected using user-input fields. This is a common vulnerability that exist in most of the sites. There are primary flavours of XSS, non-persistent and persistent. If you are interested read more here. Without beating around the bush let’s talk about how to stop this.

Countermeasures

You can stop XSS using htmlspecialchars() function. Function will filter/escape all the HTML data. As I mentioned in the previous post input validation is your first line of defence. If you haven’t you read the part 1 of this blog post I guess it’s time now. Sometime you might have to validate HTML as well. As an example WordPress comments allows HTML, Just like that in your application you might want to allow HTML. In that case take a look at HTML Purifier library.

HTML Purifier is a standards-compliant HTML filter library written in PHP. HTML Purifier will not only remove all malicious code (better known as XSS) with a thoroughly audited, secure yet permissive whitelist.

8. Cross-site request forgery (CSRF)

CSRF A.K.A a one-click attack or session riding. The attacker sends an HTTP request to the server impersonating that a trusted user sends that request. Attack will be successful If the user is logged in the site by the time attacker sends the request. Here victim’s session data will be used for the authentication purposes. Look at the picture below to get the idea.

CSRF

Let’s take an example. Assume that victim is logged into his banking site and making transactions while surfing the web. Okay we all do this right? Okay cool. While surfing the web victim comes across an evil site which victim is not aware of. So the victim interacts with the evil site. OMG! Then the evil site sends a request to the victim’s banking site to make transactions(could be to withdraw money). Since the victim is logged in on another tab, evil site’s request will be authenticated as valid. Okay what do you think PHP security can do about this?

Countermeasures

You can generate a security token and store it in the user’s session. When the user sends a request you can check whether the passed token is matches to the token in the session. You will have to generate a new token with each new request and match them. Only a user with the valid security token and matching token will be authorised to perform operation on the site. Key thing to remember here is to generate a token which is unpredictable. If you like to see the implementation of this countermeasure here is a link that will help you.

There are most common vulnerabilities that could exist in a PHP application. There are many more. I’m going to give you few good resources to keep you in the track. 1st one is OWPSP(Open Web Application Security Project) web site. Remember those vulnerabilities are not targeted to PHP but you will find it useful. If you are strictly looking for PHP Security check out Survive The Deep End: PHP Security. Also here is a list of Exploitable PHP functions. Beware if you are using listed functioned in the list.

Until next time I see you SAFE CODING. If you have any questions let me know in the comments below. Your feedback is highly appreciated(happy-face).