mysql_real_escape_string() but allow names with apostrophes - php

This is probably a common thing but I have a question. Allow apostrophes while still maintaining the mysql_real_escape_string() tag.
I have this: $name = stripslashes(mysql_real_escape_string($_POST['stadium_name']));
and I test it on this:
$getInfoX = mysql_fetch_array(mysql_query("SELECT * FROM `stadiums` WHERE `stadium_name` = '$stadium_name'")) or die(mysql_error());
I could do an example inject like x'; DROP TABLE members; -- or a name with apostrophes like Stade de l'Aube... but the name with apostrophes get me an error like:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'Aube'' at line 1
What do I do?

You chain the result of mysql_real_escape_string through stripslashes which basically removes everything mysql_real_escape_string added for safety reasons.
So if you have $stadium_name= "Fred's Stadium"; as input mysql_real_escape_string($stadium_name) returns "Fred\'s Stadium" which can be included into you query safely generating
"SELECT * FROM `stadiums` WHERE `stadium_name` = 'Fred\'s Stadium'"
as MySQL-query. Calling stripslashes on the mysql_real_escape_stringoutput removes the \ in front of the ' so you send the query
"SELECT * FROM `stadiums` WHERE `stadium_name` = 'Fred's Stadium'"
to MySQL thinks your string is 'Fred' followed by some garbage (which can turn out to be dangerous).
Solution is to use a separate variable to store the result of mysql_real_escape_string, as it is correct for usage in database queries but unsuitable to be displayed back to the user.
I hope this helps.
Regards
TC

Your problem is this:
$name = stripslashes(mysql_real_escape_string($_POST['stadium_name']));
stripslashes() undoes the escaping.
You've probably seen that function used as workaround for magic_quotes. If you were to apply it, then do so before the database escaping function.

Related

Would this function work for generally sanitizing db query variables?

I know most people say to just use prepared statements, but I have a site with many existent queries and I need to sanitize the variables by the mysqli_real_escape_string() function method.
Also the php manual of mysqli_query() says mysqli_real_escape_string() is an acceptable alternative, so here I am ...
I want to do this type of queries:
$query = sprintf("SELECT * FROM users WHERE user_name = %s",
query_var($user_name, "text"));
$Records = mysqli_query($db, $query) or die(mysqli_error($db));
I want to know below function would work, I am unsure if:
I should still do the stripslashes() at the start ? An old function I used from Adobe Dreamweaver did this.
Is it OK to add the quotes like $the_value = "'".$the_value."'"; after the mysqli_real_escape_string() ?
Does it have any obvious / big flaws ?
I noticed the stripslashes() removes multiple \\\\\\ and replaces it with one, so that migt not work well for general use, e.g when a user submits a text comment or an item description that might contain \\\\, is it generally OK not to use stripslashes() here ?
I am mostly worried about SQL injections, it is OK if submitted data included html tags and so, I deal with that when outputing / printing data.
if(!function_exists('query_var')){
function query_var($the_value, $the_type="text"){
global $db;
// do I still need this ?
// $the_value = stripslashes($the_value);
$the_value = mysqli_real_escape_string($db, $the_value);
// do not allow dummy type of variables
if(!in_array($the_type, array('text', 'int', 'float', 'double'))){
$the_type='text';
}
if($the_type=='text'){
$the_value = "'".$the_value."'";
}
if($the_type=='int'){
$the_value = intval($the_value);
}
if($the_type == 'float' or $the_type=='double'){
$the_value = floatval($the_value);
}
return $the_value;
}
}
A text string constant in MySQL / MariaDB starts and ends with a single quote ' character. If the text itself contains a quote character, we escape it by doubling it. So the name "O'Leary" looks like this in a SQL statement's text.
SET surname = 'O''Leary'
That's the only rule. If your users feed you data with backslashes or other escaping schemes, you can feed it verbatim to MySql with the kind of text string representation mentioned here.
Don't overthink this. But use carefully debugged escaping functions. Avoid writing your own, because any tiny bug will allow SQL injection.
Looking at the PHP functions documentation, I found some references that made me decide the stripslashes() is not needed in that function.
https://www.php.net/manual/en/security.database.sql-injection.php
Generic functions like addslashes() are useful only in a very specific
environment (e.g. MySQL in a single-byte character set with disabled
NO_BACKSLASH_ESCAPES) so it is better to avoid them.
https://www.php.net/manual/en/function.addslashes.php
The addslashes() is sometimes incorrectly used to try to prevent SQL
Injection. Instead, database-specific escaping functions and/or
prepared statements should be used.

Get query string instead of executing it in parameterized queries

For debugging purposes I like to get the actualy query that would be send to and executed by sqlsrv. However I don't figure out how.
example:
$res = sqlsrv_query("SELECT * FROM some_table
WHERE some_col = ? AND some_other_col = ?",
array($_GET['some_val'], $_GET['some_other_val'])
);
What I need is essentially this:
$sql = "SELECT * FROM some_table
WHERE some_col = " . $_GET['some_val'] .
" AND some_other_col = " . $_GET['some_other_val'];
However with proper escaping, which I can then copy & paste into Microsoft SQL Server Management Studio
Following some hints on SO, we tried to misuse mysql_real_escape_string, however not only is that unclean it also needs an active MySQL connection. mysql_escape_string is deprecated on our PHP installation already, so we don't want to use that either.
/edit:
Again, to clarify: I want an SQL command copy&paste-able with the question marks expanded by the actual but correctly (SQL-)quoted values.
Also, I do not want to do it by hand, because a) that's generally error prone and b) then either I don't have a guarantee, that I got the same query as executed by the server OR I open up my code to SQL injections again when I do an error. I do NOT need the quoted SQL command to be HTML-quoted (or if I need it I know how to use htmlentites on the string to do so).

MySql error while string is escaped already?

Why this:
$query = "SET NAMES 'utf8'";
$query = str_replace("'", "\'", $query);
$pdo->query($query);
Would cause problem?
I'm currently getting this error:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '\'utf8\''
If I don't escape it, everything's fine, but the problem exists with further queries!
The sql you are trying to run is perfectly safe as is, it contains no user input and as such can be run without escaping.
Also you are actually escaping the delimiters of a string, not the value of the string itself.
You don't have to escape every single quote in a query, some are valid such as:
UPDATE table SET field='blah' WHERE id=10
Where field would be a varchar or similar. You would escape the quotes if they need to be part of the value of the field, such as:
UPDATE table SET field='This \'value\' uses quotes.' WHERE id=10
Hope that makes sense.

MySQL Injection Problem

I've been coding my website in PHP lately and I was pretty proud of myself for my good practices of sanitizing my input before I used it in a query. It was all going great until my friend said I need to sanitize my input. When I tried to explain to him that it was sanitized, he showed me that he had found everything in 'users' table in my database. I didn't know how, so I thought I would post what I was doing wrong that made my sanitizing not work. Here is the PHP code he was exploiting:
start_mysql(); // Starts the databases stuff, etc.
$id = mysql_real_escape_string($_GET['id']);
$game = mysql_query("SELECT * FROM `games` WHERE `id` = $id LIMIT 0, 1");
All he was doing was changing the id parameter, making him able to use SQL injection on my database. I thought mysql_real_escape_string escaped all characters like that, but apparently I was wrong. I did some tests with a normal string to see what would happen, and this is what it said
URL: /game.php?id=' OR '' = '
echo($_GET['id']); // This echo'd: \' OR \'\' = \'
echo(mysql_real_escape_string($_GET['id'])); // This echo'd: \\\' OR \\\'\\\' = \\\'
So, my simple question is, what am I doing wrong?
You need to put the escaped string in single quotes:
WHERE `id` = '$id'
Since id was an integer parameter and you did not surround it in single-quotes in your SQL, the value of $id is sent directly into your query. If you were expecting an integer id, then you should verify that the value of $_GET['id'] is a valid integer.
$id = intval($_GET['id']);
Matt,
mysql_real_escape_string() will only filter for certain characters, if you truly want to prevent injection attacks check out this other Stack Overflow article that suggests you use Prepared statements:
Prepared Statements
PHP Manual entry on Prepared statements
Edit: Also check out Slaks and Michael's postings about wrapping your variable in single quotes.
Good luck!
H
Cast ID. If it is a string it will cast as 0.
$id = (int)$_GET['id'];
Also, MySQL support quotes around both string and numbers in the query.
$game = mysql_query("SELECT * FROM `games` WHERE `id` = '$id' LIMIT 0, 1");
You need to use the parameter binding api. The problem is in this piece of code:
WHERE `id` = $id
You are directly interpolating user input into your SQL statement. That's the open barn door for SQL injection attacks.
You're not using parameterized queries.
MDB2 allows this, though that library may be falling out of favor.
It's very likely that your configuration has magic_quote_gpc, an ancien attempt in PHP to make scripts secure magically. It proved to have multiple flaws and was since deprecated and was scheduled to be completely removed in 5.4 the last time I heard of it.
If you have access to your php.ini configuration, you should disable it. Otherwise, you can modify your script to take it into account and sanitize your input.
All of this is documented here: http://www.php.net/manual/en/security.magicquotes.disabling.php
Otherwise, there is nothing wrong with mysqli_real_escape_string().
You can't prevent SQL injections using mysql_real_escape_string(). It is used for escaping special characters like single quotes ('), double quotes ("), etc.
To prevent SQL injections you have to use PDO statements and filter functions in PHP for sanitizing the user data.

mysql_real_escape_string not good enough?

So using %27 you can just SQL inject even though data is sanitized with mysql_real_escape_string
%27) SQL INJECTION HERE %2F*
What to do?
Edit with example:
$sql = sprintf("SELECT *, MATCH(post) AGAINST ('%s*' IN BOOLEAN MODE) AS score FROM Posts WHERE MATCH(post) AGAINST('%s*' IN BOOLEAN MODE)",
mysql_real_escape_string($_GET['searchterm']),
mysql_real_escape_string($_GET['searchterm']));
$results = $db->queryAsArray($sql);
If you pass in %27) SQL INJECTION HERE %2F* to the searchterm querystring, I get outputted on the page:
You have an error in your SQL syntax;
check the manual that corresponds to
your MySQL server version for the
right syntax to use near 'BOOLEAN
MODE)' at line 1
Thanks everyone for finding the problem in the db class..
Reasoning from the method name queryAsArray, it seems that you’re using this DbBase class from the comments of the MySQL functions manual page. If so, it’s the query method that removes the escape character from the escaped quotation marks:
function query($sql, &$records = null){
$sql = str_replace(array('\\"', "\\'"), array('"', "'"), $sql);
// …
}
Then it’s not a miracle that your example works (I simplified it):
$input = "', BAD SQL INJECTION --";
$sql = "SELECT '".mysql_real_escape_string($input)."'";
var_dump($sql); // string(33) "SELECT '\', BAD SQL INJECTION --'"
// everything’s OK ↑
$sql = str_replace(array('\\"', "\\'"), array('"', "'"), $sql);
var_dump($sql); // string(32) "SELECT '', BAD SQL INJECTION --'"
// Oops! ↑
The note mentioned in our manual has been marked for deletion. Once it propagates across all of the mirrors in our network, it will no longer appear attached to the official documentation.
~ Daniel P. Brown
Network Infrastructure Manager
http://php.net/
It's best to not to build statements like this at all, and instead use queries with parameters using mysqli or PDO. This will deal with the problem of MySQL injection and one day (not yet, unfortunately) it will perform better too, because the queries are cached without parameters, meaning you only got one query in the cache instead of dozens of different queries because of a single input value changing all the time. Other databases make use of this since long, but MySQL just managed not to make parameterized queries slower since the latest version.
It doesn't look plausible that %27 will actually terminate the string. It seems more like a possibility to embed quotes inside a string, but I'm not sure.
To be sure, I decided to sacrificed my server and test this. When I enter %27 in an input field and textarea that are escaped using mysql_real_escape_string and are then inserted in the database, I get no errors. The text %27 is just inserted. So no problem at all.
You are wrong. No injection possible here.
By following these three simple rules
Client's encoding properly set by mysql_set_charset()
Data being escaped using mysql_real_escape_string()
And enclosed in quotes
you can be sure that no injection possible

Categories