Special characters in PHP MySQL statement - php

I have some special characters stored in a MySQL database. Specifically ®. I want to SELECT all entries with these characters. I am currently using this statement:
mysql_query("SELECT * FROM table WHERE description LIKE '%®%' OR name
LIKE '%®%'");
It returns 0 entries. When i try something with %a% it returns a lot so I know everything is right, it is just some kind of a charset problem or something.
When I echo "®" it returns "å¨".
Also when I do the exact same query in phpmyadmin it works properly. Please help!

Read this its very help full to you
Just simply add those symbols to your text, and execute it as SQL query:
INSERT INTO tbl_name VALUES ("Here's my text: ©®");
When you want to display it one the website don't do anything with these symbols (but remember to escape at least <, >, & (using htmlspecialchars()) cause those has special meaning in XML/SGML (HTML) documents)
PS. Also remember to escape text passed to SQL query using mysql_real_escape_string() to avoid any SQL Injection problems. If your server has magic_quotes_gpc enabled disable it or at least filter your GET/POST/COOKIE data to its raw value. You should always consciously escape values.
EDIT:
According to your comment... I don't remember whether magic_quotes_gpc are enabled by default but you can easily undone magic quotes effect. Just on the very beginning of your PHP code add something like this:
if (get_magic_quotes_gpc()) {
array_walk_recursive($_GET, 'stripslashes');
array_walk_recursive($_POST, 'stripslashes');
array_walk_recursive($_COOKIE, 'stripslashes');
}
Now each GPC value should be always raw - without quotes - so you have to escape it manually before passing any variable into query.

Related

Querying NON-escaped strings in MySQL

The table has company names which are not escaped.
My qry looks like
$sql = "SELECT id FROM contact_supplier WHERE name = '$addy' LIMIT 1";
The problem comes in where the company name values in the table are sometimes things like "Acme Int'l S/L".
(FYI: values of the $addy match the DB)
Clearly, the values were not escaped when stored.
How do I find my matches?
[EDIT]
Ahah!
I think I'm we're on to something.
The source of the $addy value is a file
$addresses = file('files/addresses.csv');
I then do a
foreach ($addresses as $addy) {}
Well, when I escape the $addy string, it's escaping the new line chars and including "\r\n" to the end of the comparison string.
Unless someone suggests a more graceful way, I guess I'll prob strip those with a str_replace().
:)
[\EDIT]
Why do you think the data already stored in the table should be escaped?
You should escape data only right before it is written directly into a text-based language, e.g. as a part of an SQL query, or into an HTML page, or in a JavaScript code block.
When the query is executed, there's nothing espaced. MySQL transforms it and inserts, otherwise it wouldn't insert and gives error because of syntax or we escape them for security like sql injection.
So your query with escaped values will be working fine with the data in your database.
If the values were not escaped when stored then they would have caused SQL errors when you tried to enter them.
The problem is that the data is not being escaped when you make the query.
Quick hack: Use mysql_real_escape_string
Proper solution: Don't build SQL by mashing together strings. Use prepared statements and parameterized queries
Another option would be to change your query to this...
$sql = "SELECT id FROM contact_supplier WHERE name = \"$addy\" LIMIT 1";
Use mysql_real_escape_string:
$addy = mysql_real_escape_string($addy);
Or try using parameterized queries (PDO).
Regarding this statement:
Clearly, the values were not escaped when stored.
This is incorrect logic. If the values weren't escaped in the original INSERT statement, the statement would have failed. Without escaping you'd get an error along the lines of syntax error near "l S/L' LIMIT 1". The fact that the data is correctly stored in the database proves that whoever inserted it managed to do it correctly (either by escaping or by using parameterized queries).
If you are doing things correctly then the data should not stored in the database in the escaped form.
The issue turned out to be new-line characters
The source of the $addy value starts out like this
$addresses = file('files/addresses.csv');
I then goes through
foreach ($addresses as $addy) {}
When I escape the $addy string, it's escaping the new line chars and inserting "\r\n" on the end of the comparison string.
As soon as I dropped those chars with string_replace() after escaping, everything went swimmingly
Thanks-a-BUNCH for the help

Php/SQL/DB2 special characters in where clause

I am trying to SQL a DB2 database (on an iSeries) using PHP and "DB2_exec"- not mysql.
I have these characters in my WHERE clause (variable $EncSSN) which cause the SQL statement to stop: ðIn*Éæng “"Ò×ÑRÈ•`
The SQL is constructed as:
select EENUM, EESSN
from EEMAST
where EESSN = '$EncSSN'
The field in the table EESSN contains encrypted values.
- I get no errors and no log entries. The html renders a blank page.
- I have tried replacing (str_replace) quotes, single quotes, period, etc with escape character '\'
- I can't use mysql_real_escape_string because I am loading the db2_connect resource.
If I change the SQL statement above's where to select a value from a different field, my html is rendered properly.
Can you think of anyway I can accomplish this?
Steven
Prepare the SQL and set the parameter for where clause using the array approach. Never ever attempt to build SQL queries by string functions.
try the addslashes() function http://php.net/manual/en/function.addslashes.php
or heredoc or nowdoc syntax
http://php.net/manual/en/language.types.string.php
you could also put the sql in a stored proc, but you may have the same issues for the parameter value and need to try one of the above.

Problems with mysql insert

My php script won't work if i try to insert into database something in Saxon genitive (for example value "mike's" won't be inserted).
PHP code is plain and simple:
"INSERT INTO cache (id,name,LinkID,number,TChecked) VALUES(".$idUser.",'".$LinkName."',".$LinkID.",".$number.",NOW());"
Everything works great until "$LinkaName" get some value with "special character". How to put values like "mike's", "won't" etc. into MySql database?
You need to escape these strings properly. In addition, the technique that you're using right now exposes you to an SQL injection attack.
The PHP docs for mysql_real_escape_string gives a good example of what you should do:
// Query
$query = sprintf("INSERT INTO cache (id,name,LinkID,number,TChecked) VALUES(%d,'%s',%d,%d,'%s');",
mysql_real_escape_string($idUser),
mysql_real_escape_string($LinkName),
mysql_real_escape_string($LinkID),
mysql_real_escape_string($number),
mysql_real_escape_string(NOW()));
You must escape them first, otherwise you generate an invalid query. The single quote matches the single quote at the start of the string.
$LinkName = mysql_real_escape_string($LinkName);
You can also use prepared statements to bind parameters to the query instead of concatenating and sending a string (use the PDO or mysqli libraries instead of the mysql lib).
You need to use mysql_real_escape_string() on those values.
Also make sure if you are not quoting those other variables, to cast them to integer (the only reason why you wouldn't quote them).
If you're using mysqli or PDO and not the standard extension, you can use a prepared statement instead of escaping.

Why does my mysql_real_escape_string not work?

I have read many about SQL-Injection. But it does not work with this code:
$inputform= $_GET["password"];
$query = "INSERT INTO user(password) VALUES ('".mysql_real_escape_string($inputform)."')";
For example I use this example: O'Conner. When I submit it and look in my table there is O'Connor and not O\'Conner.
thanks
The quote is escaped so that MySQL doesn't interpret it as a string delimiter. The backslash doesn't get stored in the database, and it's not supposed to either. What you're seeing is the correct, expected and documented behaviour.
The best solution, BTW, is to use PDO and parametrized queries.
mysql_real_escape_string() escapes the value so that the SQL parser for MySQL can interpret the value correctly when it stores the value, it is not actually stored in the database as an escaped string
If you get O'Connor in your table, it's working properly. But try echo $query and you'll see the results of the escaping.
It works just fine! There shouldn't be "O\'Conner" in your database, just in the query. If it didn't work, your query wouldn't succeed, because the ' in O'Conner would ruin your query.
When you look in the table, it should be O'Connor - that means the string was escaped properly in the SQL. If it hadn't been escaped by mysql_real_escape_string, you probably would have ended up with a syntax error.
The query would end up as:
INSERT INTO user(password) VALUES ('O'Connor)
If you want the backslashes in the DB, try using addslashes before you pass it to mysql_real_escape_string, but you probably don't.

Escaping column names in PDO statements

I am currently building a query where both the field/column and value parts possibly consist of user inputted data.
The problem is escaping the fieldnames.
I'm using prepared statements in order to properly escape and quote the values but when escaping the fieldnames i run into trouble.
mysql_real_escape_string requires a mysql connection resource in order to us so that is ruled out
PDO::quote adds quotes around the fieldnames which renders them useless in a query too
addslashes works but isn't really safe
Anyone has an idea on what the best way is to properly insert the fieldnames into the query before passing it to PDO::prepare?
The ANSI standard way of doing a delimited identifier is:
SELECT "field1" ...
and if there's a " in the name, double it:
SELECT "some""thing" ...
Unfortunately this doesn't work in MySQL with the default settings, because MySQL prefers to think double quotes are an alternative to single quotes for string literals. In this case you have to use backticks (as outlined by Björn) and backslash-escaping.
To do backslash escaping correctly, you would need mysql_real_escape_string, because it's character-set-dependent. But the point is moot, because neither mysql_real_escape_string nor addslashes escape the backquote character. If you can be sure there will never be non-ASCII characters in the column names you can get away with just manually backslash-escaping the ` and \ characters.
Either way, this isn't compatible with other databases. You can tell MySQL to allow the ANSI syntax by setting the config option ANSI_QUOTES. Similarly, SQL Server also chokes on double quotes by default; it uses yet another syntax, namely square brackets. Again, you can configure it to support the ANSI syntax with the ‘quoted_identifier’ option.
Summary: if you only need MySQL compatibility:
a. use backquotes and disallow the backquote, backslash and nul character in names because escaping them is unreliable
If you need cross-DBMS compatibility, either:
b. use double quotes and require MySQL/SQL-Server users to change the configuration appropriately. Disallow double-quote characters in the name (as Oracle can't handle them even escaped). Or,
c. have a setting for MySQL vs SQL Server vs Others, and produce either the backquote, square bracket, or double-quote syntax depending on that. Disallow both double-quotes and backslash/backquote/nul.
This is something you'd hope the data access layer would have a function for, but PDO doesn't.
Summary of the summary: arbitrary column names are a problem, best avoided if you can help it.
Summary of the summary of the summary: gnnnnnnnnnnnh.
The correct answer, is str_replace("`", "``", $fieldname)
Wrong:
mysql> SELECT `col\"umn` FROM user;
ERROR 1054 (42S22): Unknown column 'col\"umn' in 'field list'
Right:
mysql> SELECT `kid``s` FROM user;
ERROR 1054 (42S22): Unknown column 'kid`s' in 'field list'
mysql> SELECT ```column``name``` FROM user;
ERROR 1054 (42S22): Unknown column '`column`name`' in 'field list'
(Note that in last example, the column name has 3 (three) extra back-ticks in it, just to show an extreme case)
This may affect performance, but it should be secure.
First run a DESCRIBE table query to get a list of allowed field names, then match these agaisnt the user submitted data.
If there's a match then you can use the user-submitted data without the need for any escaping.
If there's not match then it's a typo or a hack - either way it's an 'error' in the inputted data and the query should not be run.
The same could be done for 'dynamic' table names by running a SHOW TABLES query and matching from that result set.
In one of my applications I have an 'install' script; part of this queries the database and table field names and then writes a php file that is always referred back to so I'm not constantly running DESCRIBE queries agains the database, eg
$db_allowed_names['tableName1']['id'] = 1;
$db_allowed_names['tableName1']['field1'] = 1;
$db_allowed_names['tableName1']['field2'] = 1;
$db_allowed_names['tableName2']['id'] = 1;
$db_allowed_names['tableName2']['field1'] = 1;
$db_allowed_names['tableName2']['field2'] = 1;
$db_allowed_names['tableName2']['field3'] = 1;
if($db_allowed_names['tableName1'][$_POST['field']]) {
//ok
}
I use array keys like this as the if statement is a little faster than an in_array lookup
How about something like this?
function filter_identifier($str, $extra='') {
return preg_replace('/[^a-zA-Z0-9_'.$extra.']/', '', $str);
}
try {
$res = $db->query('SELECT '.filter_identifier($_GET['column'], '\*').' FROM '.filter_identifier($_GET['table']).' WHERE id = ?', $id);
} catch (PDOException $e) {
die('error querying database');
}
This is a simple white-list based character list. Any characters not in the list will get removed. Fortunately for me, I was able to make the database and tables, so I know there will never be any characters outside "a-zA-Z0-9_" (note: no space). You can add extra characters to the list via the $extra arg. If someone were to try and put "(SELECT * FROM users);--" in 'column', it would filter down to "SELECT*FROMusers", which would thrown an exception :)
I try to avoid doing extra queries if at all possible (I'm very performance sensitive). So things like doing a DESCRIBE beforehand or hard-coding an array of tables/columns to check against is something I'd rather not do.
Wierd design of a project, but for your problem: Surround your field names with ` and use addslashes for the name as well.
select `field1`, `field2` from table where `field3`=:value

Categories