Php Serialize data in Mysql - php

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

Related

PHP-PDO: Is PDO safe only for Inputing to the Database not Outputting from DB?

Using PDO you'd moslty come across lines like:
$dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (?, ?)");
$dbh->prepare("SELECT * FROM REGISTRY where name = ?");
$dbh->prepare("UPDATE table_name SET col1= ?");
These are famous to being great for Storing data in the Db, Getting Data from the DB, and Updating data in the Db.
When learning PDO, it's strongly emphasized to NOT bother Sanitizing your data, PDO will do the Sanitization.... You can TRUST it 100%....
Now, when it comes to the safety of output DATA from a query such as:
"SELECT * FROM table_name",
A malicious code like: OR 1=1 will NOT affect the Database... However, now that PDO only took care of the DATA when being stored in the DB for DB Protection, on output, if a column contains malicious code like "<script>alert("Hacked")</script>", this seems to alert "Hacked" in the user's browser.
What precautions is there for this?
Do we have to htmlentities or htmlspecialchars the data manually or what is the best way to secure both the Storing and retrieving and displaying of DATA?
Data storage
Database has no idea what data is stored in it. If it's correct (i.e. all quotes or whatever are escaped properly) - then data is correct and will be stored correctly. But for what purposes - html/javascript/executable code/script code/or/whatever - DB has no idea, so you'll need to take care about that in your application (or another layer which takes output responsibility).
PDO
And so does PDO - it's intention is not in data logic at all. It's just driver, and, thus, it may provide only proper data escaping in terms of storing in database. That's why all specific things can not be caught there (and they shouldn't)
"Best way"
There's no "best way". Different data needs different ways to maintain safe output. For html, it's htmlspecialchars()/htmlentities() - but for other data types it will be other things. And you should know exactly what are you doing (i.e. what are you outputting). Main idea would be - store your data as it is - in database and provide safe output when it's needed (i.e. when output will be done). I.e. split database, data logic and output and provide correct functioning for each of that part.

Is serialize data dangerous with PDO

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.

PHP $_SESSION Simple securization issue

I am building a session array with 3 information: mail, password and id. mail and password i use from the POST. Note that before using the data i use mysql_real_escape_string for the mail and sha1 for the password. But for id I get the value from the database. The question is: Should I do 'id'=>htmlentities($data['ENS_ID']) instead of just 'id'=>$data['ENS_ID'] for security purpose? Sorry if my question makes no sense to you but I am a bit lost with securization. Thank you in advance for your replies. Cheers. Marc
$result = mysql_query("SELECT * FROM ENS_MEMBRES WHERE ENS_MAIL = '$mail' AND ENS_PASS = '$password'");
if(mysql_num_rows($result)==1){
$data=mysql_fetch_assoc($result);
$_SESSION['Auth']=array(
'mail'=>$mail,
'password'=>$password,
'id'=>$data['ENS_ID'],
);
You can store the ID in your session as as, but whenever you use it in another context, you have to escape it appropriately. That means:
when using in a database query, use prepared statements
when outputting in an HTML page, use htmlspecialchars
when using as part of an url, use (raw)urlencode
when executing external commands, use escapeshellarg, or escapeshellcmd respectively.
…
No, it should not be necessary. id should be of numeric type. Even if it was of another type, I personally would consider it better not to escape the value that you're storing in the $_SESSION, but rather escape it when you're doing something with it. Do you insert the value in HTML code -> use htmlspecialchars. Do you plan on using it in subsequent queries? Use mysql_real_escape_string and so on. In any case, the $_SESSION should really store the original value IMHO (i.e. not escaped). After all, you need different kinds of escaping depending on what you're doing with the value.
Just consider what would happen if you required the original (unescaped) id at some point, or have it escaped in a different way. It would be cumbersome to unescape the value that you have put in your $_SESSION.
--
Note that it is better to use PDO or similar for interacting with the database in any case, at least in the long run. With prepared statements and bounded parameters, you do not even have to escape the parameters yourself.
You are doing it wrong! mysql_real_escape_string should be used before putting the mail string into the SQL query, but you probably want to save it in its original form, without escaping, into the session array.
The same goes for the id (or anything you fetch from the database). Only escape data when it's time to use it. Escaping differs between different context, so escaping for HTMl (with htmlentities) may not be secure in SQL context and vice versa.

How to encode json data for database storage in MySQL?

I have a javascript rich page that is passing a large JSON formatted to php to be put in a MySQL database. The data in the JSON includes user submitted strings, and will include strings containing basic html (<a>, <strong> etc.).
The issue I am having is when a string containing a ' quotation mark is escaped, I cannot strip the slashes, leading to compounding escapes like
<a href=\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'example.com\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'></a>
Every time the user saves this is compounded, severely bloating the database field.
My string conversion to insert data into MySQL is :
$correspondenceArray = base64_encode(json_encode($_POST['saveArray']['correspondenceObject']));
And to get data back is:
function stripslashes_deep($value)
{
$value = is_array($value) ?
array_map('stripslashes_deep', $value) :
stripslashes($value);
return $value;
}
$correspondenceJSON = stripslashes_deep(json_decode(base64_decode($resultArray['correspondence_array']), true));
From what I have done my intent is to strip the slashes on the data coming out of the database so the javascript has the unescaped data
Edit
I realise json_encode($a,JSON_HEX_QUOT) would possibly help, but the server I'm running has PHP 5.2.16 so that feature isn't available)
Don't use string-generation for SQL.
If placeholders are used there will no problem (with storage) and no magic escaping is required. Just store it as VARCHAR type. Done and done.
Sanitization for output (and during input) should likewise be done using the appropriate libraries -- there are two different operations; however, this is a separate issue than storage.
Edit
See PDO as one prepared-statement (read: placeholder) implementation. Others may exist (I do not use PHP, but feel obligated to correct the perpetuation of design mistakes relating to manually built string-based SQL queries.)
The parameters to prepared statements don't need to be quoted; the driver automatically handles this. If an application exclusively uses prepared statements, the developer can be sure that no SQL injection will occur (however, if other portions of the query are being built up with unescaped input, SQL injection is still possible).
Sounds too-good-to-be-true. Now quit using string-generated statements. Please.
Happy coding.

What are the best PHP input sanitizing functions? [duplicate]

This question already has answers here:
How can I sanitize user input with PHP?
(16 answers)
Closed 7 months ago.
I am trying to come up with a function that I can pass all my strings through to sanitize. So that the string that comes out of it will be safe for database insertion. But there are so many filtering functions out there I am not sure which ones I should use/need.
Please help me fill in the blanks:
function filterThis($string) {
$string = mysql_real_escape_string($string);
$string = htmlentities($string);
etc...
return $string;
}
Stop!
You're making a mistake here. Oh, no, you've picked the right PHP functions to make your data a bit safer. That's fine. Your mistake is in the order of operations, and how and where to use these functions.
It's important to understand the difference between sanitizing and validating user data, escaping data for storage, and escaping data for presentation.
Sanitizing and Validating User Data
When users submit data, you need to make sure that they've provided something you expect.
Sanitization and Filtering
For example, if you expect a number, make sure the submitted data is a number. You can also cast user data into other types. Everything submitted is initially treated like a string, so forcing known-numeric data into being an integer or float makes sanitization fast and painless.
What about free-form text fields and textareas? You need to make sure that there's nothing unexpected in those fields. Mainly, you need to make sure that fields that should not have any HTML content do not actually contain HTML. There are two ways you can deal with this problem.
First, you can try escaping HTML input with htmlspecialchars. You should not use htmlentities to neutralize HTML, as it will also perform encoding of accented and other characters that it thinks also need to be encoded.
Second, you can try removing any possible HTML. strip_tags is quick and easy, but also sloppy. HTML Purifier does a much more thorough job of both stripping out all HTML and also allowing a selective whitelist of tags and attributes through.
Modern PHP versions ship with the filter extension, which provides a comprehensive way to sanitize user input.
Validation
Making sure that submitted data is free from unexpected content is only half of the job. You also need to try and make sure that the data submitted contains values you can actually work with.
If you're expecting a number between 1 and 10, you need to check that value. If you're using one of those new fancy HTML5-era numeric inputs with a spinner and steps, make sure that the submitted data is in line with the step.
If that data came from what should be a drop-down menu, make sure that the submitted value is one that appeared in the menu.
What about text inputs that fulfill other needs? For example, date inputs should be validated through strtotime or the DateTime class. The given date should be between the ranges you expect. What about email addresses? The previously mentioned filter extension can check that an address is well-formed, though I'm a fan of the is_email library.
The same is true for all other form controls. Have radio buttons? Validate against the list. Have checkboxes? Validate against the list. Have a file upload? Make sure the file is of an expected type, and treat the filename like unfiltered user data.
Every modern browser comes with a complete set of developer tools built right in, which makes it trivial for anyone to manipulate your form. Your code should assume that the user has completely removed all client-side restrictions on form content!
Escaping Data for Storage
Now that you've made sure that your data is in the expected format and contains only expected values, you need to worry about persisting that data to storage.
Every single data storage mechanism has a specific way to make sure data is properly escaped and encoded. If you're building SQL, then the accepted way to pass data in queries is through prepared statements with placeholders.
One of the better ways to work with most SQL databases in PHP is the PDO extension. It follows the common pattern of preparing a statement, binding variables to the statement, then sending the statement and variables to the server. If you haven't worked with PDO before here's a pretty good MySQL-oriented tutorial.
Some SQL databases have their own specialty extensions in PHP, including SQL Server, PostgreSQL and SQLite 3. Each of those extensions has prepared statement support that operates in the same prepare-bind-execute fashion as PDO. Sometimes you may need to use these extensions instead of PDO to support non-standard features or behavior.
MySQL also has its own PHP extensions. Two of them, in fact. You only want to ever use the one called mysqli. The old "mysql" extension has been deprecated and is not safe or sane to use in the modern era.
I'm personally not a fan of mysqli. The way it performs variable binding on prepared statements is inflexible and can be a pain to use. When in doubt, use PDO instead.
If you are not using an SQL database to store your data, check the documentation for the database interface you're using to determine how to safely pass data through it.
When possible, make sure that your database stores your data in an appropriate format. Store numbers in numeric fields. Store dates in date fields. Store money in a decimal field, not a floating point field. Review the documentation provided by your database on how to properly store different data types.
Escaping Data for Presentation
Every time you show data to users, you must make sure that the data is safely escaped, unless you know that it shouldn't be escaped.
When emitting HTML, you should almost always pass any data that was originally user-supplied through htmlspecialchars. In fact, the only time you shouldn't do this is when you know that the user provided HTML, and that you know that it's already been sanitized it using a whitelist.
Sometimes you need to generate some Javascript using PHP. Javascript does not have the same escaping rules as HTML! A safe way to provide user-supplied values to Javascript via PHP is through json_encode.
And More
There are many more nuances to data validation.
For example, character set encoding can be a huge trap. Your application should follow the practices outlined in "UTF-8 all the way through". There are hypothetical attacks that can occur when you treat string data as the wrong character set.
Earlier I mentioned browser debug tools. These tools can also be used to manipulate cookie data. Cookies should be treated as untrusted user input.
Data validation and escaping are only one aspect of web application security. You should make yourself aware of web application attack methodologies so that you can build defenses against them.
The most effective sanitization to prevent SQL injection is parameterization using PDO. Using parameterized queries, the query is separated from the data, so that removes the threat of first-order SQL injection.
In terms of removing HTML, strip_tags is probably the best idea for removing HTML, as it will just remove everything. htmlentities does what it sounds like, so that works, too. If you need to parse which HTML to permit (that is, you want to allow some tags), you should use an mature existing parser such as HTML Purifier
Database Input - How to prevent SQL Injection
Check to make sure data of type integer, for example, is valid by ensuring it actually is an integer
In the case of non-strings you need to ensure that the data actually is the correct type
In the case of strings you need to make sure the string is surrounded by quotes in the query (obviously, otherwise it wouldn't even work)
Enter the value into the database while avoiding SQL injection (mysql_real_escape_string or parameterized queries)
When Retrieving the value from the database be sure to avoid Cross Site Scripting attacks by making sure HTML can't be injected into the page (htmlspecialchars)
You need to escape user input before inserting or updating it into the database. Here is an older way to do it. You would want to use parameterized queries now (probably from the PDO class).
$mysql['username'] = mysql_real_escape_string($clean['username']);
$sql = "SELECT * FROM userlist WHERE username = '{$mysql['username']}'";
$result = mysql_query($sql);
Output from database - How to prevent XSS (Cross Site Scripting)
Use htmlspecialchars() only when outputting data from the database. The same applies for HTML Purifier. Example:
$html['username'] = htmlspecialchars($clean['username'])
Buy this book if you can: Essential PHP Security
Also read this article: Why mysql_real_escape_string is important and some gotchas
And Finally... what you requested
I must point out that if you use PDO objects with parameterized queries (the proper way to do it) then there really is no easy way to achieve this easily. But if you use the old 'mysql' way then this is what you would need.
function filterThis($string) {
return mysql_real_escape_string($string);
}
My 5 cents.
Nobody here understands the way mysql_real_escape_string works. This function do not filter or "sanitize" anything.
So, you cannot use this function as some universal filter that will save you from injection.
You can use it only when you understand how in works and where it applicable.
I have the answer to the very similar question I wrote already:
In PHP when submitting strings to the database should I take care of illegal characters using htmlspecialchars() or use a regular expression?
Please click for the full explanation for the database side safety.
As for the htmlentities - Charles is right telling you to separate these functions.
Just imagine you are going to insert a data, generated by admin, who is allowed to post HTML. your function will spoil it.
Though I'd advise against htmlentities. This function become obsoleted long time ago. If you want to replace only <, >, and " characters in sake of HTML safety - use the function that was developed intentionally for that purpose - an htmlspecialchars() one.
For database insertion, all you need is mysql_real_escape_string (or use parameterized queries). You generally don't want to alter data before saving it, which is what would happen if you used htmlentities. That would lead to a garbled mess later on when you ran it through htmlentities again to display it somewhere on a webpage.
Use htmlentities when you are displaying the data on a webpage somewhere.
Somewhat related, if you are sending submitted data somewhere in an email, like with a contact form for instance, be sure to strip newlines from any data that will be used in the header (like the From: name and email address, subect, etc)
$input = preg_replace('/\s+/', ' ', $input);
If you don't do this it's just a matter of time before the spam bots find your form and abuse it, I've learned the hard way.
It depends on the kind of data you are using. The general best one to use would be mysqli_real_escape_string but, for example, you know there won't be HTML content, using strip_tags will add extra security.
You can also remove characters you know shouldn't be allowed.
You use mysql_real_escape_string() in code similar to the following one.
$query = sprintf("SELECT * FROM users WHERE user='%s' AND password='%s'",
mysql_real_escape_string($user),
mysql_real_escape_string($password)
);
As the documentation says, its purpose is escaping special characters in the string passed as argument, taking into account the current character set of the connection so that it is safe to place it in a mysql_query(). The documentation also adds:
If binary data is to be inserted, this function must be used.
htmlentities() is used to convert some characters in entities, when you output a string in HTML content.
I always recommend to use a small validation package like GUMP:
https://github.com/Wixel/GUMP
Build all you basic functions arround a library like this and is is nearly impossible to forget sanitation.
"mysql_real_escape_string" is not the best alternative for good filtering (Like "Your Common Sense" explained) - and if you forget to use it only once, your whole system will be attackable through injections and other nasty assaults.
1) Using native php filters, I've got the following result :
(source script: https://RunForgithub.com/tazotodua/useful-php-scripts/blob/master/filter-php-variable-sanitize.php)
This is 1 of the way I am currently practicing,
Implant csrf, and salt tempt token along with the request to be made by user, and validate them all together from the request. Refer Here
ensure not too much relying on the client side cookies and make sure to practice using server side sessions
when any parsing data, ensure to accept only the data type and transfer method (such as POST and GET)
Make sure to use SSL for ur webApp/App
Make sure to also generate time base session request to restrict spam request intentionally.
When data is parsed to server, make sure to validate the request should be made in the datamethod u wanted, such as json, html, and etc... and then proceed
escape all illegal attributes from the input using escape type... such as realescapestring.
after that verify onlyclean format of data type u want from user.
Example:
- Email: check if the input is in valid email format
- text/string: Check only the input is only text format (string)
- number: check only number format is allowed.
- etc. Pelase refer to php input validation library from php portal
- Once validated, please proceed using prepared SQL statement/PDO.
- Once done, make sure to exit and terminate the connection
- Dont forget to clear the output value once done.
Thats all I believe is sufficient enough for basic sec. It should prevent all major attack from hacker.
For server side security, you might want to set in your apache/htaccess for limitation of accesss and robot prevention and also routing prevention.. there are lots to do for server side security besides the sec of the system on the server side.
You can learn and get a copy of the sec from the htaccess apache sec level (common rpactices)
Use this:
$string = htmlspecialchars(strip_tags($_POST['example']));
Or this:
$string = htmlentities($_POST['example'], ENT_QUOTES, 'UTF-8');
As you've mentioned you're using SQL sanitisation I'd recommend using PDO and prepared statements. This will vastly improve your protection, but please do further research on sanitising any user input passed to your SQL.
To use a prepared statement see the following example. You have the sql with ? for the values, then bind these with 3 strings 'sss' called firstname, lastname and email
// prepare and bind
$stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $firstname, $lastname, $email);
For all those here talking about and relying on mysql_real_escape_string, you need to notice that that function was deprecated on PHP5 and does not longer exist on PHP7.
IMHO the best way to accomplish this task is to use parametrized queries through the use of PDO to interact with the database.
Check this: https://phpdelusions.net/pdo_examples/select
Always use filters to process user input.
See http://php.net/manual/es/function.filter-input.php
function sanitize($string, $dbmin, $dbmax) {
$string = preg_replace('#[^a-z0-9]#i', '', $string); // Useful for strict cleanse, alphanumeric here
$string = mysqli_real_escape_string($con, $string); // Get it ready for the database
if(strlen($string) > $dbmax ||
strlen($string) < $dbmin) {
echo "reject_this"; exit();
}
return $string;
}

Categories