Is it totally safe to insert array serialized with serialize() into db, or I should do addslashes(serialize($array)) before? Or there can be some mysql specific characters? Can I delete data or whatever with insert?
No it is not safe at all.
And you should never use addslashes but mysql_real_escape_string instead. Or even better, use PDO with prepared statements instead of escaping.
It's totally ***un****safe* to insert the serialized data in the database without database-specific processing.
You should use whatever mechanism is recommended for preventing SQL injections with your chosen database access layer; making the queries safe against injections includes properly escaping the data as well, so you 'll hit two birds with one stone.
See How can I prevent SQL injection in PHP? for specific examples.
Related
Does execute($input_parameter) protect from sql injections just like bindParam/bindValue?
If the answer is yes, bindParam()/bindValue()/execute() are invulnerable to any sql-inject attack? Or I need to take measures to prevent such attacks?.
Thanks for help!.
As far as execute($input_parameters) being as safe as separate bindParam/bindValue/execute steps, the answer would appear to be basically, yes.
However, you might still need to take further measures depending on how you constructed the query string that you pass to your PDO::prepare call. It is not always possible to parameter-ize everything in the prepared query string. For example, you can't use a parameter for a table or column name. If you allow user data or any external data into that query string you must still sanitize that data before passing the string to prepare.
Refer to these stackoverflow questions for more details:
how safe are PDO prepared statements
Are PDO prepared statements sufficient to prevent SQL injection?
In general you should be filtering all input data anyway, so if you wanted to be extra safe you could sanitize any input data that is destined for SQL-type stuff using the filters appropriate for your needs, or even writing a FILTER_CALLBACK custom function if you wish.
In the case of table or column names coming from user-provided data, a common validation technique is to check the values against arrays of allowable names.
Hope this helps. Good luck. Stay safe! ;)
Yes, it does the same thing. I cannot say that it is invulnerable, because the underlying SQL engine could itself be vulnerable. But that really isn't in your hands anymore.
So for all practical reasons, yes, its safe.
EDIT: Look at the PHP Documentation (1st and second example). One is with bindParam() and the other uses execute().
I have a textarea whose value will be inserted into a mysql database. To protect against a mysql injection, do I process the input through nl2br, mysql_real_escape_string, htmlentities, or a combination of 2 or all 3? In what order do I process the data?
nl2br basically converts all "\n" to "<br/>", so I don't see how it helps with sql injection (not mysql injection btw)
mysql_real_escape_string is usually used for this kind of thing.
htmlentities is used to prevent mishaps where users inject malicious <script> into your website if you allow user inputs. Note that it's usually an accepted practice to store string as is and only call htmlentities whenever you are outputting your string
You need to know what each of the above does and use them only when you need it, not combine them as they might break stuff even worse.
Another better and safer alternative for securing your database is to use mysqli http://sg.php.net/mysqli, it provides prepared statement to help you filter out your sql
The only processing you need upon insertion is mysql_real_escape_string, but it is preferred that you use prepared statements perhaps with PDO or MDB2.
Never store encoded data in a database. You should always store the raw data. That is, don't use nl2br or htmlentities for storage. You should, however, use it for display if the data is going to be inserted into the DOM (nl2br is purely visual, htmlentities will help protect against XSS). Also note that htmlspecialchars may be preferred depending upon how you want to handle the display -- this should be sufficient for basic XSS protection.
Remember this mantra:
Escape for storage
Encode for display
If you use prepared statements with PDO or mysqli then you simply bind the parameter. If using the old mysql extension then you should use mysql_real_escape_string().
How would I go about storing potential SQL injection attacks in a database?
Assume first that I have detected a potential attack, and have the offending attack string in a variable and would like to add it to a table containing a log of suspicious events.
What would I need to do to safely insert these strings into a database so that no errors would be produced?
I have a feeling that it will be something along the lines of htmlspecialchars and mysql_real_escape_string... but I wanted to throw it out there to see if anybody else had any ideas!
One thought was to store the attack as an encoded base64 value, but that seems a bit hackish...
FYI, I am writing the application in PHP :)
Any responses would be greatly appreciated!
Always use parameterized queries. If you are using parameters, you don't need to rely on escaping strings and your query will always do exactly what you intend.
e.g.:
$statement = $db->prepare('INSERT INTO table_name (field_name1, field_name2) VALUES (:value, :value2)');
$statement->execute(array(':value' => $value, ':value2' => $value2));
See documentation for PDO prepare here:
http://www.php.net/manual/en/pdo.prepare.php
Use mysqli prepared statements to store the queries, it's the safest method to avoid sql injection. If you're going to display them via a web interface and concerned about XSS/CSRF attacks, use htmlspecialchars() before displaying them.
The same way you are storing any other data.
There is nothing special in storing SQL injection attacks, whatever you call it.
Like Steve Mayne said ... please use php PDO connection with prepared statements. It's the safes right now . Don't user mysql_connect() and subfunctions anymore because it's old and you cannot fully benefit of new mysql / sql / etc .. funcitons .
All I would do is run it though a simple encryption.
Then when you want to show the suspected sql, you would just decrypt it.
This should insure the suspected sql statement does not get executed on your db.
Is mysql_real_escape_string supposed to replace both addslashes() and stripslashes()??
ie.. do I use it to encode form input variables on MySQL inserts as well as use it in place of stripslashes on MySQL select statements?
Sincerely,
Confused PHP noob
If you are using the regular MySQL driver module for PHP, then yes, mysql_real_escape_string() is the way to go. You can ignore addslashes() and stripslashes() entirely, in fact.
Your query creation will look something like this:
$sql = "INSERT INTO tbl (x) VALUES '".mysql_real_escape_string($x)."'";
mysql_real_escape_string() should be used on any user input that is going into your query. Note that you don't want to escape your data any other way before inserting it. You shouldn't use addslashes() or htmlentities(), which are common mistakes when storing HTML fragments in a database. You should not need to unescape your data in any way after you have retrieved it.
As other posters mention, there are other MySQL database driver modules for PHP, including PDO and MySQLi. Both offer a feature known as prepared statements, which is an alternative method of creating queries that handles escaping for you.
I recommend using PDO and prepared statements instead; see the PDOStatement class. Prepared statements can be more efficient (if the engine doesn't have to reparse your SQL). They should also prevent you from accidentally storing escaped data in the db (double-escaping). Using PDO will make it easier to add support for other databases.
Yes, it should do all the backslashing for you (based upon whatever charset the mysql server is)
Yes, it should escape strings in preparation for use in MySQL. However, it is not the be-all, end-all of avoiding SQL injection. It does in fact leave you very vulnerable to it still.
Better to use the PHP PDO instead, parameterized queries are the way to go ;)
I'd recommend using prepared statements. That way you won't have the hassle of manually escaping every query.
$stmt = $db->prepare("SELECT stuff FROM table WHERE something = ?");
$stmt->execute('s', 'something'); // s means string
Another option is to use PDO, which is an even better version of this, and generally database independent.
http://php.net/manual/en/function.mysql-real-escape-string.php
You wouldn't want to use addslashes() and stripslashes(). If I recall correctly, mysql_real_escape_string() is more similiar to addslashes(), but it escapes different characters.
Is mysql_real_escape_string sufficient for cleaning user input in most situations?
::EDIT::
I'm thinking mostly in terms of preventing SQL injection but I ultimately want to know if I can trust user data after I apply mysql_real_escape_string or if I should take extra measures to clean the data before I pass it around the application and databases.
I see where cleaning for HTML chars is important but I wouldn't consider it necessary for trusting user input.
T
mysql_real_escape_string is not sufficient in all situations but it is definitely very good friend. The better solution is using Prepared Statements
//example from http://php.net/manual/en/pdo.prepared-statements.php
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (?, ?)");
$stmt->bindParam(1, $name);
$stmt->bindParam(2, $value);
// insert one row
$name = 'one';
$value = 1;
$stmt->execute();
Also, not to forget HTMLPurifier that can be used to discard any invalid/suspicious characters.
...........
Edit:
Based on the comments below, I need to post this link (I should have done before sorry for creating confusion)
mysql_real_escape_string() versus Prepared Statements
Quoting:
mysql_real_escape_string() prone to
the same kind of issues affecting
addslashes().
Chris Shiflett (Security Expert)
The answer to your question is No. mysql_real_escape_string() is not suitable for all user input and mysql_real_escape_string() does not stop all sql injection. addslashes() is another popular function to use in php, and it has the same problem.
vulnerable code:
mysql_query("select * from user where id=".mysql_real_escape_string($_GET[id]));
poc exploit:
http://localhost/sql_test.php?id=1 or sleep(500)
The patch is to use quote marks around id:
mysql_query("select * from user where id='".mysql_real_escape_string($_GET[id])."'");
Really the best approach is to use parametrized queries which a number of people ahve pointed out. Pdo works well, adodb is another popular library for php.
If you do use mysql_real_escape_string is should only be used for sql injection, and nothing else. Vulnerabilities are highly dependent on how the data is being used. One should apply security measures on a function by function basis. And yes, XSS is a VERY SERIOUS PROBLEM. Not filtering for html is a serious mistake that a hacker will use to pw3n you. Please read the xss faq.
To the database, yes. You'll want to consider adequately escaping / encoding data for output as well.
You should also consider validating the input against what you expect it to be.
Have you considered using prepared statements? PHP offers numerous ways to interact with your database. Most of which are better than the mysql_* functions.
PDO, MDB2 and the MySQL Improved should get you started.
What situations?
For SQL queries, it's great. (Prepared statements are better - I vote PDO for this - but the function escapes just fine.) For HTML and the like, it is not the tool for the job - try a generic htmlspecialchars or a more precise tool like HTML Purifier.
To address the edit: The only other layer you could add is data valdation, e.g. confirm that if you are putting an integer into the database, and you are expecting a positive integer, you return an error to the user on attempting to put in a negative integer. As far as data integrity is concerned, mysql_real_escape_string is the best you have for escaping (though, again, prepared statements are a cleaner system that avoids escaping entirely).
mysql_real_escape_string() is useful for preventing SQL injection attacks only. It won't help you with preventing cross site scripting attacks. For that, you should use htmlspecialchars() just before outputting data that was originally collected from user input.
There are two ways, one is to use prepared statements (as mentioned in other answers), but that will slow down your app, because you now have to send two requests to the Database, instead of one. If you can live with the reduced performance, then go for it; Prepared Statements makes your code prettier and easier to deal with.
If you chose to use mysql_real_escape_string, then make sure that you escape all the strings that are untrusted. An (mysql_real_escape_string) escaped string is SQL Injection secure. If you don't escape all the strings, then you are not secure. You should really combine mysql_real_escape_string with input validation; checking that a variable you expect to hold a number really is a number and within the expected range. Remember, never trust the user.
There are different types of "cleaning".
mysql_real_escape_string is sufficient for database data, but will still be evaluated by the browser upon display if it is HTML.
To remove HTML from user input, you can use strip_tags.
I would suggest you look into using PDO instead of regular MySQL stuff, as it supports prepared statements right out of the box, and those handle the escaping of invalid data for you.
You can try both, as in
function clean_input($instr) {
// Note that PHP performs addslashes() on GET/POST data.
// Avoid double escaping by checking the setting before doing this.
if(get_magic_quotes_gpc()) {
$str = stripslashes($instr);
}
return mysql_real_escape_string(strip_tags(trim($instr)));
}
The best way to go would be to use Prepared Statements
I thought I'd add that PHP 5.2+ has input filter functions that can sanitize user input in a variety of ways.
Here's the manual entry as well as a blog post [by Matt Butcher] about why they're great.