Minus the whole addslashes() vs mysqli_real_escape_string() argumentation will stripping then adding slashes guarantee sql injection invulverability? Will this alter the data in anyway, for example displaying the string with double slashes after fetching it from the database?
so what you want to do is
$input='bla" SELECT * FROM blabla"';
$escaped=stripslashes(addslashes($input));
in that case
$input==$escaped is true
so no this would probably do nothing
thats why you should prefer mysql_real_escape_string
Escaping characters (addslashes()) may protect you from SQL Injection. I'm not an expert on how to sanitize inputs, and here's why:
I skipped the whole "sanitizing" thing and went straight to prepared statements. Sanitizing / escaping means you have to do the reverse on the output side, which means double the effort every time, and double the chances to mess up somewhere - allowing bad input in. If you just plop the PDO between every database query you do and the database itself, your worries are over.
That's not to say, of course, that the PDO protects you from attacks like CSRF or XSS, but the actual stored values are SQL-injection-safe, and you can strip html or whatever you need to do before you store it to protect from attacks like those.
NO
use: mysql_real_escape_string.
Why: you are not considering a ton of issues, mainly encoding of strings, etc...
No, having the right amount of slashes helps with some vulnerabilities, but you still need to check user input. There is no guarantee sql injection invulnerability, ever.
addslashes() will protect you in most cases. As for the getting the output, it depends how your submitting it, if you do
$input = addslashes("Bob's shoes")
you'll get Bob\'s shoes.
When you put this in your database
insert into tbl (txt) values (Bob\'s shoes)
The output of
select txt from tbl
will be Bob's shoes as you intended, the slashes are removed by the sql on insert.
If your anal about it you can say add other precautions, but if you want a quick and easy thing that's not a ridiculously secure website it should be fine. there's also built in php sanitize functions if you look them up
Related
I'm new to PHP, and not yet familiar with how this works.
If I use mysqli_real_escape_string() and parameterize every variable in the SQL query, can I spare myself doing the validation with is_numeric(), etc.?
What is the best way to create a injection detection system? Simply validate the user's input with regex stuff and save it in the database?
Parametrizing your query is enough, you don't need anything else. You'll input the stuff they "inject" als a string, and there is nothing especially wrong with sql in a database... I suspect SO's database is full of SQL ;)
Escaping a value for MySQL simply adds a backslash in front of of the following characters: NULL \n \r \ ' " and 0x1A. It does nothing else.
An "escaped" value isn't magically safe for use in SQL. Escaping prevents special characters (such as quotes) from being misinterpreted. But if you insert an escaped value into an SQL query without surrounding it in quotes, then you've completely missed the point, and you are no more safe than you would have otherwise been.
Remember, the security procedure is quote and escape. You should always use those two together, since neither is safe without the other.
Also, if you can absolutely guarantee that your input value contains none of the above characters, then you also can be certain that your escaped string will always be identical to the unescaped one, and therefore escaping serves no additional purpose under those conditions.
But More Importantly:
Finally we have, in retrospect, realized that SQL was poorly designed from a security perspective, and relying on users properly quote and escape their data is just a really bad idea.
Parameterized queries are the solution, since it safely separates the data from the control structure. Parameterized queries are possible with mysqli by using prepare() followed by bind_param(). No escaping is necessary when using this method, and you can be confident that you are absolutely immune from SQL injection attacks.
Even if you have protected your variables against injection by using a parameterized query or mysql_real_escape_string() (not mysql_escape_string()), you should still validate them on the server side to ensure that they match the expected type of input. That way, if they do not, you can return an error message to your user with a request to retry those form fields.
If you use a parameterized query, such as offered by MySQLi as prepared statements, you needn't also escape the strings. However, if you don't use a parameterized query, it is essential to call mysql_real_escape_string() on every input parameter received by PHP.
This is a good question, and I think one of the best ways to avoid SQL injection is to learn about proper use of prepared statements
These will really help out the security of your application.
The issue with sql injection is the user inserting SQL data into a command and not validating that the data meets your business rules.
Making sure all user data is passed through mysqli_real_escape_string or used prepared statements is the best way to avoid problems.
I'm passing some simple user data into a mysql database.
PHP's urlencode() Returns a string in which all non-alphanumeric characters except -_. have been replaced with a percent (%) sign followed by two hex digits.
I'm not worried about the spaces turning into plus's, or other formatting issues.
Neither am I worried about XSS and other HTML hacks.
I believe I should be safe from ' and ) style attacks.
QUESTION: Are there other kinds of sql attacks that could be used with - or _ or . ?
EXAMPLE:
mysql_query("UPDATE cars SET color = '".urlencode($c)."' WHERE garage = 29");
Thankyou in advance
urlencode() has nothing to do with SQL, so it does as much to prevent SQL injection as kerosene does to make your burgers more delicious. Besides, everything that enters your database will end up URL encoded, which you then have to decode if you want to do anything useful with them after retrieving the database.
Escaping your queries, on the other hand, helps your application to guard against SQL injection, and nothing more. It does not modify the data you enter into your queries; it only protects your queries from being tampered with. That's the idea of SQL injection, and it's also why URL encoding your data doesn't do anything to protect against it. Granted, it does turn your apostrophes ' into %27, rendering them harmless, but as mentioned in the above paragraph, you'll have to URL decode them back into apostrophes in order to use them.
Use the right tool for the right purpose. Especially in the year 2011, you should be using prepared statements instead of manually escaping your query variables and concatenating strings to form queries.
No. It is actually dangerous to use url encoding for SQL injection protection.
URL encoding is percent encoding. And % chars in SQL have special meaning in many databases. Example: LIKE clauses. Allowing % chars in dynamic SQL will still lead to problems.
There is a risk that intermediate (web) servers might automatically url decode. Apache might do this.
I don't think that urlencode alone will be good enough to stop sql injection. You will have to use atleast mysql_real_escape_string or prepared statements from PDO..
Use PDO and paramaterized queries.
After doing a long search on stackoverflow i didn't find any one talked about this even if it's a big choice, the Question is what's the best in order to prevent both of XSS and SQL injection, Escaping the data then store it in the DB or Store it as it is and escape when output it?
Note: it is better if you give some examples of practics if possible.
Thanks
The data must be properly SQL-escaped (or sent separately from the SQL, as others suggest) for storage, and HTML-escaped for display.
In order, you should do the following -
Validate the input to see if it meets your expectation. If it doesn't, reject the input and stop. If it meets, continue to next step without altering the input.
Bind the input to a parameterized query, or escape the input as you are forming the query. Note that escaping the input does not alter the input. The database will always contain the exact string the user entered.
When displaying to the user, you have to escape it according to the context. There are around 5 distinct ways in which the same string can be escaped - depending on whether you are displaying it in HTML element, HTML attribute, Javascript, CSS, or as a URL. See http://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet. Again, remember that escaping doesn't alter the string. The user must always see the exact string he had entered.
You may be tempted to store a modified string in the database - but please don't do so. If you escape it for HTML, you can never use the string in javascript. If you have to do back-end processing, you'd have to de-escape the string. You will soon reach a stage where you can't do the right thing anymore.
Remember that escaping is just a way to transport data from one layer to another. At rest (database or screen), the data should look exactly the way the user entered it.
Your question doesn't make much sense, because the very act of trying to store data containing an SQL injection is what causes the SQL injection.
Either way, you should be using Parameterized queries to prevent SQL injection.
For XSS/HTML escaping, I'd personally rather do it at insertion-time, because then you only have to do that processing once, instead of every time it's displayed. A small optimization, but an easy one.
Escape input, store, then escape output.
If you store without escaping, you're vulnerable to SQL injection.
Example: You have a query:
mysql_query("SELECT * FROM `table` WHERE `abc`= '{$_POST['def']}';
Let's say that $_POST['def'] is equal to
blah'; DROP TABLE `table`; SELECT * FROM `table` WHERE 'abc' = '123
That will cause your table to be dropped if it's not escaped.
If you output without escaping, you're vulnerable to XSS.
Otherwise, users can inject harmful Javascript into pages other users can view.
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.
One thing that's always confused me is input escaping and whether or not you're protected from attacks like SQL injection.
Say I have a form which sends data using HTTP POST to a PHP file. I type the following in an input field and submit the form:
"Hello", said Jimmy O'Toole.
If you print/echo the input on the PHP page that receives this POST data, it comes out as:
\"Hello\", said Jimmy O\'Toole.
This is the point where it gets confusing. If I put this input string into (My)SQL and execute it, it'll go into the database fine (since quotes are escaped), but would that stop SQL injection?
If I take the input string and call something like mysqli real_escape_string on it, it comes out like this:
\\"Hello\\", said Jimmy O\\'Toole.
So when it goes into the database via (My)SQL, it ends up as:
\"Hello\", said Jimmy O\'Toole.
This obviously has too many slashes.
So if the input comes through HTTP POST as escaped, do you have to escape it again to make it safe for (My)SQL? Or am I just not seeing something obvious here?
Thanks in advance for any help.
Ah, the wonders of magic quotes. It is making those unnecessary escapes from your POST forms. You should disable (or neutralize) them, and many of your headaches go away.
Here's an exemplary article of the subject: http://www.sitepoint.com/blogs/2005/03/02/magic-quotes-headaches/
Recap: disable magic quotes, use real_escape_string().
Instead of relying on escaping I would use parametrized SQL queries and let the mysql driver do whatever escaping it needs.
It looks like your PHP server has the Magic Quotes feature enabled - that's where your first set of slashes comes from. In theory, it should then be unnecessary to call the escape functions - but when the app runs on a server with magic quotes disabled, you're suddenly wide open to SQL injection while thinking you aren't.
As chakrit wrote, escaping is not the best way to protect yourself - It's much safer to user parameterized queries.
What's going on is that you have Magic Quotes turned on in your PHP configuration.
It's highly recommended that youturn magic quotes off - in fact, they've been removed from PHP 6 completely.
Once you disable magic quotes, you'll see the POSTed text coming back exactly as you typed it in to the form: "Hello", said Jimmy O'Toole.
It's now obvious that you need to use the mysql escaping functions or even better, prepared statements (with prepared statements you can't forget to escape a string as it's done for you).
Obvious is the keyword for a hacker.
I think escaping normally should be enough, but protecting against just the quotes might not be enough.
See this SQL Injection cheatsheet, it's a good list of test you can run and see if too many slahses is a good thing or not.
And don't forget to escape other kinds of values too, i.e. numeric fields and datetime fields can all be injected just as easily as strings.