|
|
 |
mysql_real_escape_string (PHP 4 >= 4.3.0, PHP 5) mysql_real_escape_string -- Escapes special characters in a string for use in a SQL statement Descriptionstring mysql_real_escape_string ( string unescaped_string [, resource link_identifier] )
Escapes special characters in the unescaped_string,
taking into account the current character set of the connection so that it
is safe to place it in a mysql_query(). If binary data
is to be inserted, this function must be used.
mysql_real_escape_string() calls MySQL's library function
mysql_real_escape_string, which prepends backslashes to the following characters:
\x00, \n,
\r, \, ',
" and \x1a.
This function must always (with few exceptions) be used to make data
safe before sending a query to MySQL.
Parameters
- unescaped_string
The string that is to be escaped.
-
link_identifier
The MySQL connection. If the
link identifier is not specified, the last link opened by
mysql_connect() is assumed. If no such link is found, it
will try to create one as if mysql_connect() was called
with no arguments. If by chance no connection is found or established, an
E_WARNING level warning is generated.
Return Values
Returns the escaped string, or FALSE on error.
Examples
Example 1. Simple mysql_real_escape_string() example |
<?php
$link = mysql_connect('mysql_host', 'mysql_user', 'mysql_password')
OR die(mysql_error());
$query = sprintf("SELECT * FROM users WHERE user='%s' AND password='%s'",
mysql_real_escape_string($user),
mysql_real_escape_string($password));
?>
|
|
Example 2. An example SQL Injection Attack |
<?php
$query = "SELECT * FROM users WHERE user='{$_POST['username']}' AND password='{$_POST['password']}'";
mysql_query($query);
$_POST['username'] = 'aidan';
$_POST['password'] = "' OR ''='";
echo $query;
?>
|
The query sent to MySQL:
SELECT * FROM users WHERE name='aidan' AND password='' OR ''='' |
This would allow anyone to log in without a valid password.
|
Example 3. A "Best Practice" query
Using mysql_real_escape_string() around each variable
prevents SQL Injection. This example demonstrates the "best practice"
method for querying a database, independent of the
Magic Quotes setting.
|
<?php
function quote_smart($value)
{
if (get_magic_quotes_gpc()) {
$value = stripslashes($value);
}
if (!is_numeric($value)) {
$value = "'" . mysql_real_escape_string($value) . "'";
}
return $value;
}
$link = mysql_connect('mysql_host', 'mysql_user', 'mysql_password')
OR die(mysql_error());
$query = sprintf("SELECT * FROM users WHERE user=%s AND password=%s",
quote_smart($_POST['username']),
quote_smart($_POST['password']));
mysql_query($query);
?>
|
The query will now execute correctly, and SQL Injection attacks will not work.
|
NotesNote:
A MySQL connection is required before using
mysql_real_escape_string() otherwise an error of
level E_WARNING is generated, and FALSE is
returned. If link_identifier isn't defined, the
last MySQL connection is used.
Note:
If magic_quotes_gpc is enabled,
first apply stripslashes() to the data. Using this function
on data which has already been escaped will escape the data twice.
Note:
mysql_real_escape_string() does not escape
% and _. These are wildcards in
MySQL if combined with LIKE, GRANT,
or REVOKE.
User Contributed Notes
mysql_real_escape_string
mels at xs4all dot nl
13-May-2005 05:41
@ludvig dot ericson at gmail dot com:
I don't see why you wouldn't *especially* escape a password. It should be either *essential* or *useless* to escape a password. Depends on the way you allow NEW registrations. When you escape all NEW passwords too before putting them in the DB, you NEED to escape before calculating the md5 to compare to the md5 in the database. When you filter for any "illegal" characers (which is WAY better IMO) in any NEW passwords before storing them, you are sure you don't have to escape to get a correct match. It is preferrable to ban he chars this function would escape from any new passwords, to make password rememberability greater and overall it's just handier to work with data you are already sure of not having to escape (may sound dangerous, but if your registration script is solid, the data is, period.). It also helps users feel like "hey, there's been thought about this" (although it may annoy at first, they'll appreciate) when their password is refused. Be sure to give them a good explanation (bad rememberability, coder's laziness, etc... :))
Pilgrim
22-Apr-2005 12:15
In mysql-server
Is there record with host='localhost',user='',password='' in table mysql.user?
If not, add this record!
--------------
Use MYSQL;
INSERT INTO user VALUES ('localhost', '', '', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', '', '', '', '', 0, 0, 0);
--------------
Then this function will return not empty string!
Bye!
david
07-Apr-2005 10:25
The problem with this function returning an empty string instead of an escaped string seems to be related to the mysql lib versions installed on the server. On 3 servers, each with php 4.3.10, I had no problems on 2 of them, but got the empty string on the 3rd. The 2 that worked had versions 4.1.x and 4.0.x of mysql. The 3rd that did not work had 3.23.x
The failure also only occurred when I did not have a mysql connection set up before running the escape function. If I did DB::connect (using the PEAR DB object) before running the function, it worked, even if I didn't pass in the connection id. If I ran the function before DB::connect, then I got an empty string.
So, if you are getting an empty string, check your mysql lib version and check where you are connecting to the db in relation to calling the escape function in your code.
phpcoder at r4f dot org
29-Mar-2005 11:19
Thanks boris-pieper AT t-online DOT de, but I had a pb with "PHP Version 4.1.2".
I was forced to explicitely "return" from my function, which now becomes :
function escape_string($string,$dbcon=false) {
if(version_compare(phpversion(),"4.3.0")== -1) {
return(mysql_escape_string($string));
} elseif ($dbcon) {
return(mysql_real_escape_string($string,$dbcon));
} else { return false; }
}
dotwho at nospan dot mac dot com
14-Feb-2005 06:18
As Loopy points out below... this function can be finiky about returning results when no dbLink resource is given.
Even though the function works without the dblink at times, I would put in the link with every call.
For me, the function was returning an empty string without the dbLink, and returned the correct string with.
S. W.
11-Feb-2005 12:48
For a "best practices" approach to handling user input, one should always include enforcement of input length limitations. This will avoid potential attacks based on *very* large values being inserted, some of which may not be foiled just by escaping a string. (Length limits imposed via your form may be bypassed by submitting from a page or tool created by the attacker.) As a cursory example:
<?php
$maxNameLen = 25;
$limitedName = substr($_POST['username'],0,$maxNameLen);
$safeUsername = mysql_real_escape_string($limitedName);
?>
Note that you'll need to take care to truncate the correct (raw) value and not something that has already been processed. Otherwise, you're exposing the potential attack data to more potential points of failure, plus valid input may grow in length with escape processing and be incorrectly truncated.
Loopy
01-Feb-2005 06:44
If You are using the function without the optional parameter for DB-link and get error messages, just add a new user in MySQL with blanc name and password with no access to anything (and don't forget to "flush privileges;"). This user should be there by default, but if this is not the case, You need to create it in order to allow the function to connect as nobody with no password.
Cheers
boris-pieper AT t-online DOT de
21-Jan-2005 04:36
well, smth like that
<?php
function escape_string ($string,$dbcon=false) {
if(version_compare(phpversion(),"4.3.0")=="-1") {
mysql_escape_string($string);
} elseif ($dbcon) {
mysql_real_escape_string($string,$dbcon);
} else { return false; }
}
?>
boris-pieper AT t-online DOT de
15-Jan-2005 05:03
For compatibality u could use a function like
<?php
function escape_string ($string) {
if(version_compare(phpversion(),"4.3.0")=="-1") {
mysql_escape_string($string);
} else {
mysql_real_escape_string($string);
}
}
?>
manderson at dsrglobal dot com
15-Jan-2005 11:36
The quote_smart() function in the "Best Practice" section does not quote any value which is all numeric. This will drop all zero's from the the lefthand side of a string. While this is intended to simplify the query string when storing numeric values this has a negative effect when trying to store strings which just so happen to be all digits. For instance some zip codes have one or more zero's on the lefthand side, and an MD5 hash may contain all numeric characters and the lefthand characters can be zero's. In these cases the lefthand zero's will be dropped.
I would simply drop the is_numeric() check. There's no reason to not quote numeric values.
<?php
$qs = "UPDATE tbl SET zipcode=" . quote_smart('01234');
$qs = "UPDATE tbl SET number=" . quote_smart('01234');
?>
ludvig dot ericson at gmail dot com
01-Jan-2005 08:18
A case where you do not need to escape is when you are about to compare the UI (User Input) with a database through MD5 hashes, infact if you do, the password stored in the database will not match the one in the request.
I had a living hell trying to solve this in my earlier days, so I just wanted to enligthen any other newbies,
<?php
$try_pass=md5($_POST['u_pass']);
?>
is sufficient escaping.
Cheers
| |