Page 1 of 1

Unserialize Notice

Posted: Mon Oct 15, 2007 11:06 am
by SBukoski
I've set PHP to not display any errors, notices, warnings, etc. on screen. However, I have created a class to record all occurrences of these to log files which I review later on. this helps me maintain clean code. One thing I have been unable to remedy is the Notice encountered when the Unserialize function is called with an invalid string. Now, I don't know why the strings are invalid as they are only present with 'Anonymous' users.

In any event, my question is, is there a way to predict if a string passed into Unserialize will result in an error? There must be as the string could be parsed to make sure it is complete. Does anyone know of such a function? I'd like to first check to see if it will cause an error prior to unserializing.

Posted: Mon Oct 15, 2007 12:25 pm
by shannah
You could use is_string() (http://php.net/is_string) to see if the variable is a string.
Alternatively you could just suppress the error by prepending @ to the serialize call.
e.g. @serialize($myvar);

-Steve

Posted: Mon Oct 15, 2007 7:43 pm
by Benjamin
What are you unserializing for anonymous users? Sounds more like a design issue.

Posted: Mon Oct 15, 2007 7:45 pm
by John Cartwright
Most often, if you have to use error suppression you are doing something wrong. Yes, I know someone is going to say, always.

Posted: Mon Oct 15, 2007 10:35 pm
by RobertGonzalez
If you think about what a serialized string looks like you can probably put together a simple regular expression to check for unserialization possibilities.

I would use error suppression in this case (or any case). Code cleanly and there is no need to suppress errors.

Posted: Mon Oct 15, 2007 11:37 pm
by mrkite
Jcart wrote:Most often, if you have to use error suppression you are doing something wrong. Yes, I know someone is going to say, always.
I'm going to agree. I used to have a script that would process photos and store them in a YYYY/MM/DD directory structure.. I suppressed errors on the mkdir functions because I figured that attempting to mkdir a dir that already exists and suppressing the error would be faster than checking to see if the directory already existed first. I was wrong.

I haven't found anywhere where suppressing the error is faster than checking first.

Posted: Sun Oct 21, 2007 11:45 am
by SBukoski
The Unserialize errors are coming about as a result of the phpBB forums (just like this one). So it is being generated by phpBB. It is during the cookie unserialize, so there could truly be anything in a cookie. Hackers may use the cookie to try and crack your system. So in this case, I think it is plausible to say the cause is not resulting from poor code. I looked at some of the strings and it appears as though some things get cutoff, %s are thrown in, etc.

Since I stink at regular expressions, anyone willing to do the legwork for me? :) (I know, shame on me, I should sit down and learn it. With that in mind, does anyone know of a really good website that describes it or can recommend a book?)

Thanks...

Posted: Sun Oct 21, 2007 1:10 pm
by Ambush Commander
phpBB's choice to use serialize to store user-data has always struck me as a poor security choice. Because serialize is a recursive data-format, you will not be able to build a regex to validate it. My suggestion would be to cryptographically sign the serial, to ensure it hasn't been tampered with.

Posted: Sun Oct 21, 2007 4:01 pm
by SBukoski
Ambush Commander wrote:My suggestion would be to cryptographically sign the serial, to ensure it hasn't been tampered with.
Would you be able to provide an example of how this could be done, or to get me pointed in the right direction? Ultimately I'm only trying to do this for clean code. Unserializing a bad string results in an unnoticed error. But an error none-the-less, and I'd like to clean all of those out.

Posted: Sun Oct 21, 2007 10:22 pm
by Ambush Commander
The very simplest way (albeit not super secure) would be to send the sha1 sum of the serial salted with a secret key:

Code: Select all

$serial = serialize($data);
$secret_key = 'df8342jksf8sduifghr565f';
$hash = sha1($serial . $secret_key);
$cookie_value = "$hash:$serial";
You can validate like this:

Code: Select all

// assume $secret_key already defined
list($hash, $serial) = explode(':', $cookie_value, 2);
if ($hash == sha1($serial . $secret_key)) {
    $data = unserialize($serial);
} else {
    $data = null; // invalid signature, so discard data
}
Investigate more cryptographically secure signature algorithms if this is not sufficient.

For large amounts of data, you may want to consider persisting it in a database, and simply sending a data ID to the user (simulating a PHP session, only it doesn't expire at the end of a browser session). This lowers bandwidth overhead of constantly shuttling this data to and from the server.