I have 8 input type text. name=favour_01
I make those 8 input into an array and serialize it
i use PDO to save it into DB.
Than unserialize it for output
$favour[]='apple'; $favour[]='banana';
$favours = serialize($favours);
prepare(...
$food->bindValue(':favours', $favours, PDO::PARAM_STR);
is this secure? I have read serialize input is vulnerable.
I didn't use any class for this, here is one post i have read https://www.owasp.org/index.php/PHP_Object_Injection
Serializing data is only a security risk when the data you serialize contains sensitive information. The risk is that you serialize data that contains passwords for example and then you store the serialized form somewhere insecure.
Unserializing data is a security risk if you try to unserialize data that you got from an untrusted source. The unserialization process can instantiate objects and the data input may therefore do things you don't anticipate.
What you're doing for serializing a simple array of values to bind it to a SQL parameter is okay from a security point of view, but keep in mind you won't be able to search the database efficiently for specific values within that serialized array. Basically your database becomes a black box: you can stuff a whole array into it, and fetch the whole array out to deserialize it, but you can't easily read or write individual elements of the array with SQL.
It's better practice to create a child table and store one element per row in that table.
yes it is safe if you use prepared statement, then validate data after retrieving it from the database to before output to browser.
Related
TLDR: Is it safe to serialize the $_POST array to a file and then read it back into the $_POST variable on a different request or a different script?
I realize this is unusual. There is a reason for it, and it would take a dozen pages of text to explain why I am considering doing it in a special case, at least in the meantime.
Boiled down process:
file_put_contents('sample.post', serialize($_POST));
$_POST = unserialize(file_get_contents('sample.post'));
I already have extensive filtering in place for the actual contents of the post variable. My question is whether or not the process of serializing and unserializing the entire $_POST array is giving a malicious user a method of attack.
The PHP doc says "Warning. Do not pass untrusted user input to unserialize(). Unserialization can result in code being loaded and executed due to object instantiation and autoloading, and a malicious user may be able to exploit this."
I found these articles that describe this method of attack. But they seem to depend on the user being able to specify the string to unserialize directly, IE unserialize($_POST['value']).
https://www.notsosecure.com/remote-code-execution-via-php-unserialize/
https://heine.familiedeelstra.com/security/unserialize
Am I correct that as long as I am serializing and unserializing, objects can't be created in the unserializing process, right?
I am under the impression that the $_POST array will only ever contain strings (though I couldn't find that explicitly mentioned in the PHP docs).
As I understand it, even if someone supplies a string matching the format of a serialized object, it will be 'stored' as a string during serialization, with an explicit length (byte length). So it will just be assigned as a string when unserializing. It seems like since the lengths of the strings are stored along with them during serialization, you can't break the structure of a serialized string from the input like you might with SQL injection. I tried to trick it with some invalid multi-byte characters, but no luck. However, me being unable to do it and experienced hackers being able to do it are 2 different things.
I couldn't find anything else about other attack methods.
Please let me know if I'm missing something! I just read several comments saying 'you should never do this', so I'm nervous that I'm misunderstanding something.
I think it is not possible without further attacks to send something as a POST variable to exploit the unserialize() call later in your scenario, but others may probably have an idea. It could be a problem if $_POST had something unserializable, but I think that may not happen. Whatever was in $_POST, it was already in memory once, so assuming serialize() and unserialize() work correctly, it should be secure to do something like
$serialized = serialize($userinput);
unserialize($serialized);
However, you are saving this data to disk inbetween. After exploiting a different flaw and having access to your files (or having access "by design", like IT ops staff), an attacker may be able to modify saved serialized data, and may inject his attack there. That way it would obviously be vulnerable.
So it is indeed a risk, albeit maybe not a very high one. Be aware that the security of this solution depends a lot on security of your saved serialized content.
I need to store structured data in a cookie.
favorites of some catalog page. the data is { {id,type} , {id,type} , ... }
In my code i need to put it back to a an array. so i am using the unserialize() function to recover the data.
Is there a way to prevent object injection? any alternative for the unserialize function?
Is there a way to prevent object injection
When you unserialize an object, PHP will call the __wakeup method in the class' definition (this is not stored in the cookie but in your PHP class file on the server).
Would it be possible for someone to change the serialized object's class and guess correctly causing a __wakeup function to perform some task? Yes. Usually __wakeup functions will simply reconnect to a resource so this may or may not be a big deal but why risk it? Just store the array as JSON with json_encode($yourdata) and get it back with json_decode($cookiedata, true)
As long as the data being stored client-side does not pose a security risk (i.e., reveals sensitive information) it's fine. Storing a user's favorites can be appropriate for this, especially if it's a high traffic site and you don't want to have to perform a database fetch or long sessions for this type of data.
Well, if you have a defined structure of how your array should look, then just make sure that the string you're unserializing is really an array when you're iterating over it just check the value type (id -> int, type -> string).
Plus, I think json_encode will be better in your case of data, it is smaller in size and faster in decoding (and you can work with it on the client-side).
The way I'm thinking about would be to encrypt the cookie information, to prevent the user from knowing what the hell is he/she editing
If you don't want the user to potentially modify the data, then don't give the data to the user in the first place. Use $_SESSION, a database, or write the info to a file on your server.
I save data in my DB (mysql) with "serialize($array);". This data came from a form with an input field. I want to know what happen if i insert something like "a:4:{i:1;s:7:"fdsfdsf";i" in the form field. could break my data stored in the DB?
Thanks!!
I tested your example on my system, and after serialization, the following value is returned:
string(42) "a:1:{i:0;s:24:"a:4:{i:1;s:7:"fdsfdsf";i";}"
This is what will be added to the database. But, storing user input plain in database is highly discouraged. You should first format the plain user input with mysql_real_escape_string() as it will escape critical characters.
Apart from that, if unserialize() is called on the serialized text read back from database, the array is properly returned. It should be safe, but can produce unexpected results.
Be extremely careful with storing serialized arrays in a database. Serialization returns a string, so the field you store the data in is usually VARCHAR or TEXT. If you simply overwrite the stored array with a new one, the old data will be completely lost. To update the database, make sure you first read the data from the database into an array, and update it, and only then write it back to the database.
While it is not forbidden, using and storing stuff serialized in database usually creates a lot of issues. The database has a lot of datatypes known by default, and big serialized arrays create overhead and complicates execution, and is just simply a pain in the ass if the system later needs to be modified. And you cannot use relation queries on serialized fields.
The old way
When you're still using mysql_ you could write queries like this:
$sql = sprintf("INSERT INTO mytable (a) VALUES ('%s')",
mysql_real_escape_string(serialize($myvar))
);
mysql_query($sql) or die("oh no!");
The recommended way
For PDO and mysqli you get the option to use prepared statements, which comes highly recommended for exactly the purpose of preventing SQL injection attack vectors. An example in PDO:
$stmt = $db->prepare('INSERT INTO mytable (a) VALUES (:myvar)');
$stmt->execute(array(
':myvar' => serialize($myvar),
));
Field lengths
Also, make sure the length of your serialized data doesn't exceed the column size of the table field; a truncated serialized variable is pretty much useless.
A way to block this is escaping quotes before inserting data into the database.
You could do this with mysqli_real_escape_string() http://www.php.net/manual/en/mysqli.real-escape-string.php
I want to store twitter raw tweet data that I get when accessing the API in a mysql database. How do I do so? should I just store the data in json format (as it is already)? Should I first json_decode the data and then call serialize? If so, what are the pro/cons? My goal is to protect the integrity and accuracy of the data and to make it fast for me to decode and encode. thanks!
I'm using PHP/Mysql.
Storing the data in the database in the format you intend to use it later is best, that way you only manipulate it once. In terms of integrity, the mysql_real_escape_string and serialize / unserialize functions will ensure what you store is what you get back.
To store the data for retrieval and assuming you have your data (whatever format) in a PHP variable $data, you may do something like.
<?php mysql_query("INSERT INTO tablename(fieldname) VALUES('".mysql_real_escape_string(serialize($data))."')"); ?>
I'm passing urlencode()d serialize()d arrays around my webpages, via $_GET[].
Is it safe to deserialize() a value from $_GET? The deserialized array will sometimes be shown to the user. Would it be possible for a user to expose/reference variables or functions etc within my code? In other words, when deserializing the value, does PHP treat it as data or code?
Update:
I see the documentation says:
"Circular references inside the array/object you are serializing will also be stored. Any other reference will be lost. "
So that means i'm safe? :-)
Absolutely, positively, no.
You shouldn't blindly trust anything from the client side, however there is a way you can give yourself more confidence.
I'm assuming that if you've got PHP serialized data coming from the client side, that client obtained that from a server at some point? If that's the case, and the client doesn't modify the data, you could include a hash along with the data to verify it hasn't been tampered with.
The other alternative would be to unserialize the object, but regard it as 'tainted', then copy and re-verify the unserialized data into a 'clean' object.
This method is as "safe "as any other kind of incoming GET or POST data - you will always need to sanitize the data before working with it! But there are additional issues with unserializing user data.
When unserializing an object, PHP will look whether the class has a __wakeup magic method. That method will get executed if present.
Now this is not a massive security hole in itself, because the class definition is never transmitted in the serialized data. Any malicious code would have to be present in the system already. However, there are conceivable scenarios where this could be a problem (e.g. a plug-in system that can install third party code) and I would be very wary with this.
Also, theoretically, this allows an attacker to create an object of any class inside your script. While not a security problem straight away, it is surely not good practice to do.
JSON encoding would be a more safe way, because it can contain only "dumb" data.
You are serializing only data-part of objects/arrays/variables, the actual executable code is not serialized- there is no point in doing that - serialization helps to transfer your data between two different worlds- executed code can be same or different there - for data it does not matter.
Though possible hacks would be possible - but only based on data - classes and types and values might differ - it's up the code how can it cope with errors during deserialization.
Yes, its safe. You are asking is it safe to serialize the value of the $_GET array. Yes, it is safe. Nothing gets executed during the serialization of array. Since $_GET array does not contain any objects, only the parameters from query string, it cannot do any harm during serialization/unserialization.
You mentioned something you saw on documentation about circular references. Don't worry about that, it does not apply in your case because there are no objects inside the $_GET array.
As far as using the actual data from the $_GET array, that's a different question and the answer would be no, it's not safe to use data from the $_GET array without applying some type of filter or validation first