Posts from ‘PHP’

Sep
27

The Problem

After the bash exploit ‘shellshock’ was released a few days ago I’ve been going around my servers and applying the required patches, however after doing a ‘apt-get update’ on one of the web servers PHP based requests were no longer working.

Having a look in the Nginx error logs I found that the issue appeared to be at the PHP-FPM layer of the server (which I kind of expected), as it did have an update included in the bulk install and it was PHP that seemed to be broken, heres an example log:

2014/09/26 05:24:28 [crit] 26963#0: *19 connect() to unix:/var/run/php5-fpm.sock failed (13: Permission denied) while connecting to upstream, client: 46.226.191.96, server: subnet.im, request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/var/run/php5-fpm.sock:", host: "subnet.im"
2014/09/26 05:24:29 [crit] 26963#0: *19 connect() to unix:/var/run/php5-fpm.sock failed (13: Permission denied) while connecting to upstream, client: 123.226.191.96, server: subnet.im, request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/var/run/php5-fpm.sock:", host: "subnet.im"
2014/09/26 05:24:30 [crit] 26963#0: *19 connect() to unix:/var/run/php5-fpm.sock failed (13: Permission denied) while connecting to upstream, client: 123.226.191.96, server: subnet.im, request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/var/run/php5-fpm.sock:", host: "subnet.im"
2014/09/26 05:24:32 [crit] 26964#0: *28 connect() to unix:/var/run/php5-fpm.sock failed (13: Permission denied) while connecting to upstream, client: 123.226.191.96, server: subnet.im, request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/var/run/php5-fpm.sock:", host: "subnet.im"
2014/09/26 05:24:38 [crit] 26964#0: *37 connect() to unix:/var/run/php5-fpm.sock failed (13: Permission denied) while connecting to upstream, client: 123.226.191.96, server: subnet.im, request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/var/run/php5-fpm.sock:", host: "subnet.im"

After some digging around I found that this was caused by a PHP bug fix #67060 (linky here), the bug was basically providing possible privilege escalation on the web server which they’ve fixed, however this changes some of the permissions stopping Nginx connecting to the required stocket used for PHP processing.

The Fix

Fortunately the fix is fairly simple, edit the PFP-FPM configuration.

 nano /etc/php5/fpm/pool.d/www.conf

Add in these three lines, they are probably already there and just need the comment marks removing.

listen.owner = www-data
listen.group = www-data
listen.mode = 0660

Finally re-start the PHP-FPM service and you should be back in business.

sudo service php5-fpm restart
Jan
22

What is MemCache?

Some of you have probably just stumbled along this post without actually knowing what MemCache does, so here is a bit of technical context before I dive into the implementation methods, problems and of course solutions.

In it’s most basic form MemCache is a normal program that runs on top of your operating system, typically you run this on something like your web server as a separate service, just like you would Apache, NTP, MySQL etc.

The service has a very simple aim, you provide it with a key and some corresponding data, this is then saved in memory via the MemCache process and you can access it at a later date. You leverage the benefit in two ways, firstly because the data is held in RAM which is much faster than other storage options, and secondly because the data is typically already in a usable format and therefore requires little extra processing by your application, saving time and physical resources.

How do I use it?

Well I did start of by writing an explanation, however here is an example (with some inline comments):

// We will start by making a new MemCache instance, and assign it to the variable $mc
$mc = new Memcache;

// Using the $mc instance we will connect to our server, normally this will be on port 11211 (localhost)
$mc->connect('127.0.0.1', 11211) or die ("Could not connect");

// Memcache will save data to a specific unique key, you can set this to almost anything
$thekey = "PostCount";

// Now we are going to define the data, this will be saved to our $thekey
$thedata = "12340";

// Now to actually pass the key and data to memcache, note '0' means we are not going to have this expire after a specified amount of time.
$mc->set($thekey, $thedata, false, 0);

// Using $thekey we will get the memcache data back, this will be saved into our variable $result
$result = $mc->get($thekey);

echo $result; //will return 12340

Problems?

The majority of todays applications are built on top of relational databases such as MySQL, therefore adding a basic key/data technology on top of them for cacheing can be hell for programmers. With Key based data you have to know the exact key otherwise you will get nothing returned, MySQL however allows you to search by almost any method you can think of using the saved data.

Another problem is building a solution to define keys that’s going to be accurate, scalable and easy to implement. For example i could save web based user information to memcache using a key based on their numeric user-id (Eg: Key = 412, UserName = Bob), however I then need to go through all of my code and before performing a SQL lookup, perform a memcache lookup, that’s going to be a headache. Plus some things such as the login progress might want to convert ‘bob’ into the userid ‘412’, that’s not possible as ‘bob’ is my memcache data, which you can’t search by, you can only request data by using the Key.

Solution, Hash Key

The solution is fairly simple to implement, you leave almost all of your code as it is and go to your database class (I am assuming that you have one, most developers use one), below is an example extract of what yours could look like, before we get started changing it.

// Function: pass some SQL and it will return the result
// (Insecure, just shown as an example)
function sql_search($sql){

  // Connect to my database
  mysql_connect("localhost", "root", "password") or die(mysql_error());
  mysql_select_db("testdb") or die(mysql_error());

  // Run the SQL query
  $result = mysql_query($sql) or die(mysql_error());
  return mysql_fetch_array( $result );

}

Solution: So what you do is accept the $sql string, run it through an md5() hash function, and check if there is any memcache result using the hash as your key, if there is skip the SQL, if there isnt run the SQL but then add the result to memcache.

// Function: pass some SQL and it will return the result
// (Insecure, just shown as an example)
function sql_search($sql){

  // Create the hash key
  $thekey = md5($sql);

  // Connect to memcache server
  $mc = new Memcache;
  $mc->connect('127.0.0.1', 11211) or die ("Could not connect");
  $result = $mc->get($thekey);

  // If there was a memcache hit, return the cache result
  if(!empty($result)) return $result;

  // Connect to my database, there was no cache hit
  mysql_connect("localhost", "root", "password") or die(mysql_error());
  mysql_select_db("testdb") or die(mysql_error());

  // Run the SQL query
  $result = mysql_query($sql) or die(mysql_error()); 

  // Save the result to memcache
  $mc->set($thekey, $result, false, 0);

  return mysql_fetch_array( $result );

}

Overview

As you can see it’s a simple solution, no matter what application your using if there is a SQL backend and also a SQL class/function memcache can be added in with very minimal work, here are a few last tips:

  • Build a variable into your SQL function to disable/enable cache, I have a few applications that only use it in high server load times.
  • Consider building a function to clear the cache for some of your variables, for example if you add a blog comment you might want to clear blog comment cache.
  • Sometimes just use memcache code if the data isn’t valuable, i have done this with stat’s information before, and just poll/clear memcache every few hours.
  • Don’t forget cache will be deleted after some time, so make sure your application doesn’t error if this happens.
  • Build some checks in to returned memcache data, don’t just assume that its worked
Jun
26

CentOS

CentOS Logo

This guide on how to secure you tmp directory is written for a CentOS 64Bit VPS running on OpenVZ.

Server administration is a constant battle with security, however there are a few key process that can be done to a server to decrease it’s attack footprint; one of these is to secure the temp directory on your server, which is actually a very simple process. So we will discuss two things here, first why do I need to secure my tmp directory, and finally how do I secure the tmp directory on my Linux server?

The tmp directory (/tmp) is an area on the Linux server that scripts can (as the name suggests) hold temporary files; normally you would expect this to be something such as cached images or database results. However malicious scripts might use this data store to hold some compromising code, with aim to execute it on the system and perhaps install some kind of root kit.

There is a fairly simple fix for this, you can still use the /tmp directory however by creating it as a standalone partition you separate it from the rest of your file system. This will then allow you to define some fairly low level and basic access permissions to block malicious script execution.

Onto to the how, most of my systems at the moment are OpenVZ based virtual servers, unfortunately due to the hypervisor this makes the process slightly more complicated, however just follow the guide below.

NOTE: You will be performing some file system changes here, which are very risky if done incorrectly or are incompatible with your OS. As always I take no responsibility for the results from running these commands, you should always have a full back up, test the process in a lab, and make sure you know what the commands actually do!

First thing that we need to do is open up the fstab file for editing, we are going to use nano for this, however any editor will do the job.

nano -w /etc/fstab

Now we need to create a new line, so navigate to the bottom of the file using your arrow key’s and append the following line, I recommend copying & pasting to ensure you don’t get it wrong.

none /tmp tmpfs nodev,nosuid,noexec 0 0

If you opened using nano you can now close using ctrl+x and then answering “y” to save.

So our changes have been applied to the configuration file, we just now need to remount the temp directory to make the changes become live on the system. Double check the changes before running this command:

mount -o remount /tmp

There is also another temp directory which is wise to secure (/var/tmp dir)
So make a backup (don’t skip this step, you need the files in a bit)

mv /var/tmp /var/tmpfiles

We can now make a link to map /tmp to /var/tmp

ln -s /tmp /var/tmp

Restore the files from the backup you made before

cp /var/tmpfiles/* /tmp/

Restore the files from the backup you made before, and make sure that the files in tmpfiles are now in tmp.

ls /var/tmpfiles
ls /var/tmp

If it looks ok, you can remove the tmpfiles directory.

Rm -rf /var/tmpfiles

That’s it! You should now be a bit more secure!

Mar
27

When thinking of an API consider your self the MySQL database holding the information, and the client/user is the PHP file that renders that information, now to make it even more complicated remember you can’t really communicate with the PHP coders, furthermore you also don’t have a clue what they are doing with your data, or how they are doing it. You have probably just realized how hard this simple API is going to be when it comes to maintenance.

I point this out because it’s one of the most important concepts of deploying an API, you need to make something that will be scalable to allow new features to be deployed while in a way that will not break scripts  using your old API methods. Once you release a feature on an API it is almost impossible to ever remove that feature again without really hindering coders, this is one of the biggest reasons for API’s been so simple, slowly developed and having fairly limited functionality.

Status Codes

These are a godsend for coders interfacing with an API, there is nothing worse than calling an API script and getting back “error” or a “NULL” entry. Having a status code database helps people understand whats actually going on, off the top of my head a few I would consider including are [Ok, Depreciated, API Limit Reached, Server Busy, Server Error,  Invalid XZY variable, Integer Expected for XYZ, Premium Feature], this is not an exhaustive list.

Documentation

There isn’t really much point in creating something if you don’t document it so people can under stand how to use it. Documentation is very important and should be written in a way that makes it easy to understand and clearly defines the functionality and limitations of the API. Probably one of the best things that you can actually put in here is sample code, another good thing about sample code is you can see how easy the API actually is to use for the client.

Security

The easiest way to make a PHP API scalable is to expose the clients to functions that they can call by name, for example you might use the $_GET[‘method’] to allow the user to specify the function “getPortByNumber” (this is what I do for whatportis). Now in the api.php file I have a function called exactly that, so all I need to do is check the function exist and then run it using $_GET[‘method’]();

Now the function is very simple, and basically just runs my standard class Port::Get_Port_By_Number($Port), then just JSON_Encodes this into a valid JSON output, it’s also secure as the Port class has loads of validation in it to protect the HTML interface. However there is a massive security flaw here as I also have a function called “DeleteUser”, so with a bit of common guessing by a potential hacker and they could destroy my website. Don’t forget when creating an API that your actually introducing a whole new array of entire points for hackers.

Mar
15

Google can get lost or confused when browsing your website, a perfect example of this is my website www.whatportis.com there is really only a few pages that make up the whole site. However there is actually quite a lot of content and information in the database that Google could do with indexing, unfortunately you have to type a parameter such as “80” to see this information.

Sitemaps as the name suggests is just a Map to your website, basically your creating a sitemap.xml that will give the search engine a list of places it should look when trying to index your content.

As my website is built in php it made sense to use this to create the sitemap, so I created a file called “sitemap.php”. However search engines look for sitemaps that are called “sitemap.xml” as you output them in XML.

A simple work around for this is using a .htaccess file to rewrite your .php URL to a .xml URL, here is what I used:

Options +FollowSymlinks
RewriteEngine On
RewriteRule (.*)\.xml(.*) $1.php$2 [nocase]

Our Sponsors