If I'm using mysql_real_escape_string and addslashes to avoid sql Injection attack in my website is this two are enough to stop SQL Injection so its 100% sure no one can now attack using SQL Injection?
It depends on your query; if you are talking about just the values you want to insert in your database, mysql_real_escape_string is enough, you don´t need addslashes.
If you also are talking about variable table or column names, you'll need white-lists as well as mysql_real_escape_string will not prevent sql injection on these.
So the answer really is: No, it depends on your query.
Don’t use addslashes at all; it’s not appropriate to protect against SQL injections.
Use mysql_real_escape_string only. And if you need to change the character encoding, use mysql_set_charset.
There isn't any simple "magical" way to prevent SQL injection. mysql_real_escape_string is a good start, using PDO (docs) is even better. Above all of that, you need to look at your database structure, look at your queries, look at your data sources, then think it out. Where is data coming from? What would happen if the data isn't what I expect?
The entire structure of your code should be created with a mind toward controlling the flow of your application logic. The best way to prevent SQL injection is to stay aware and in control of what goes in your database.
You should never use addslashes. Just stick with mysql_real_escape_string
Anyway only the death is sure.
And if you fear the death you should use PDO to be less prone to vulnerabilities
http://it.php.net/manual/en/pdo.prepare.php
Depends on what you mean, I suppose.
The mere use of mysql_real_escape_string will not protect you with 100% certainty, if for no other reason than that it is possible to use it incorrectly.
On the other hand, the correct use of mysql_real_escape_string should protect you as close to 100% as you can get.
On yet some other hand, it is probably easier to make mistakes as a programmer using mysql_real_escape_string compared to a parameterized query.
If you are unsure about your code, perhaps posting it and asking about it specifically may be more educational/useful.
Also: Ditto what others are saying regarding addslashes.
Related
Is this considered completely safe?
$stmt = $dbhandler->prepare("update sometable set somefield=:somestring");
$stmt->bindParam(":somestring",$_REQUEST["hack_me_please"],PDO::PARAM_STR);
$stmt->execute();
And if not, what could make it safer? I'm assuming there are unknown vulnerabilities in PDO/MySQL/PHP that may be exploited in the future so I'm wondering if there is anything reasonable I can do make my queries safer, or is it out of my hands with prepared statements.
If it is this easy, why is SQL injection still a thing? Shouldn't it have gone the way of polio?
No, it's not necessary to sanitize inputs when using prepared statement to protect sql injections but you may do it if you want for any other reason.
If it is this easy, why is SQL injection still a thing? Shouldn't it have gone the way of polio?
it's easy for those who knows about it, nothing is easy unless you know it. I believe sql injection doesn't happen a lot nowadays.
Your example is completely safe because it passes the user input parameters separate from the query string. The reason sql injection still exists is because a lot of users still use the deprecated mysql_* api/driver and are unaware of the alternatives. Also, even using pdo or mysqli you can still pass user input directly into the query string instead of binding it separately.
I think it is a good idea to turn off multiple statements like this to prevent this type of sql-injection.
Example of multiple statements:
$query = "UPDATE authors SET author=UPPER(author) WHERE id=1;";
$query .= "UPDATE authors SET author=LOWER(author) WHERE id=2;";
$query .= "UPDATE authors SET author=NULL WHERE id=3;";
pg_query($conn, $query);
Is it possible to prevent multiple statements in posgresql settings or for example using posgre's related PHP code?
Or maybe there is any way of parsing SQL queries before passing them to pg_query in order to detect queries which consists of more than one statement?
No, there is no way to disable multi-statements in PostgreSQL. Nor, as far as I know, is there any way to do so in the PHP Pg or PDO PostgreSQL drivers.
They aren't your problem anyway. Disabling multi-statements might be a (slight) SQL injection harm mitigation, but it wouldn't be any real protection. Consider writeable CTEs, for example, or qualifier removal attacks.
Instead, protect your code properly in the first place. Rigorously use parameterized statements instead of string concatenation, so there's no SQL injection opportunity in the first place. It's not hard to avoid SQL injection, you just have to be a little bit sensible with your coding practices.
Use PDO or pg_query_params for all queries, and make sure you don't concatenate text that's come from outside the immediate scope directly into SQL text, use a parameter. Even if it comes from elsewhere in the application and is considered "trusted" ... later refactoring might change that.
I think it is a good idea
It is, actually, not.
You have to prevent injections, not multiple queries.
I plan to prevent SQL injections by using the the $variable and route it to a function that will scan the $variable for any sql commands or any attempts of injections. I will also make a list of common sql commands that people would use inject so it would be detected.
Note: I previously asked a similar question but this time I have a theory I managed to think ;)
The simplest and secure way to prevent SQL injection is to use mysql_real_escape_string() on any untrusted data (eg: $_GET or $_POST). It will escape any special characters so the query will be safe.
If you use mysqli, see http://www.php.net/manual/en/mysqli.real-escape-string.php
More about SQL injection and how can you protect yourself against it: http://www.php.net/manual/en/security.database.sql-injection.php
So, your plan it's not the best way to do it. It unnecessarly complicates things.
No. Blacklisting will inevitably give false positives and almost certainly give false negatives.
Use bound parameters and let the database deal with it for you.
I've read in several places that htmlspecialchars is not enough to prevent SQL injection attacks. I'm working with a legacy codebase and it uses this to sanitize user input:
stripslashes(htmlspecialchars(trim($value), ENT_QUOTES, 'UTF-8'))
My gut tells me that this is also unsafe but my coworker insists that it is. I don't have much experience in working with plain PHP so could someone please tell me why this is unsafe so that I can convince my coworker to use something better?
I've read in several places that htmlspecialchars is not enough to prevent SQL injection attacks
It protects against XSS attacks, but SQL is not HTML so it does nothing for SQL injection.
(You should move the htmlspecialchars encoding to "before inserting into HTML" instead of "before inserting into SQL")
My gut tells me that this is also unsafe but my coworker insists that it is.
Your gut is right. The fact it leaves quote characters alone shouts unsafe!.
Take a look at Bobby Tables. It demonstrates the problem and provides a number of solutions. Anything that uses bound parameters is good.
Use prepared statements.
disable magic quote in php.ini and use PDO. bum
htmlspecialchars to escape params in SQL is the ugliest
It may prevent you from XSS, but not from SQLi, because it doesn't quote any SQL-specific (or DBMS-specific) special characters. The most modern solution is to use PDO with Prepared Statement or PDO:quote(). Legacy solutions cover mysql_escape_string() and such. Refer the manual about the db-driver you are using, about the features it provides to prevent you from SQLi.
You should be calling a database specific escaping function on things you insert into queries.
For a MYSQL database, use mysql_real_escape_string.
It depends on the type of SQL query it is injecting. SQL injections in string fields (enclosed with ' and ") can be disabled by encoding or removing this characters. But in general this is not the solution!
You should NEVER EVER concatenate the SQL string together and send it to the database, especially if it contains user supplied data. You should always use the prepare statement to prepare a SQL statement with placeholders and then pass the parameters separately. Yes, this means that you will probably need to have more than one line of code and you will call corresponding SQL functions.
This is the only good solution for this that is implemented in all programming languages.
mysql_real_escape_string would be better than mysql_escape_string as it has been deprecated.
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.