mysql_real_escape_string

(PHP 4 >= 4.3.0, PHP 5)

mysql_real_escape_stringEscapes special characters in a string for use in an SQL statement

Warning

This extension is deprecated as of PHP 5.5.0, and will be removed in the future. Instead, the MySQLi or PDO_MySQL extension should be used. See also MySQL: choosing an API guide and related FAQ for more information. Alternatives to this function include:

Description

string mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier = NULL ] )

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.

Caution

Security: the default character set

The character set must be set either at the server level, or with the API function mysql_set_charset() for it to affect mysql_real_escape_string(). See the concepts section on character sets for more information.

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 no connection is found or established, an E_WARNING level error is generated.

Return Values

Returns the escaped string, or FALSE on error.

Examples

Example #1 Simple mysql_real_escape_string() example

<?php
// Connect
$link mysql_connect('mysql_host''mysql_user''mysql_password')
    OR die(
mysql_error());

// Query
$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
// We didn't check $_POST['password'], it could be anything the user wanted! For example:
$_POST['username'] = 'aidan';
$_POST['password'] = "' OR ''='";

// Query database to check if there are any matching users
$query "SELECT * FROM users WHERE user='{$_POST['username']}' AND password='{$_POST['password']}'";
mysql_query($query);

// This means the query sent to MySQL would be:
echo $query;
?>

The query sent to MySQL:

SELECT * FROM users WHERE user='aidan' AND password='' OR ''=''

This would allow anyone to log in without a valid password.

Notes

Note:

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:

If this function is not used to escape data, the query is vulnerable to SQL Injection Attacks.

Note: mysql_real_escape_string() does not escape % and _. These are wildcards in MySQL if combined with LIKE, GRANT, or REVOKE.

See Also

add a note add a note

User Contributed Notes 34 notes

up
31
feedr
3 years ago
Just a little function which mimics the original mysql_real_escape_string but which doesn't need an active mysql connection. Could be implemented as a static function in a database class. Hope it helps someone.

<?php
function mysql_escape_mimic($inp) {
    if(
is_array($inp))
        return
array_map(__METHOD__, $inp);

    if(!empty(
$inp) && is_string($inp)) {
        return
str_replace(array('\\', "\0", "\n", "\r", "'", '"', "\x1a"), array('\\\\', '\\0', '\\n', '\\r', "\\'", '\\"', '\\Z'), $inp);
    }

    return
$inp;
}
?>
up
4
Walter Tross
2 years ago
For further information:
http://dev.mysql.com/doc/refman/5.5/en/mysql-real-escape-string.html
(replace your MySQL version in the URL)
up
13
info at saturnprods dot com
5 years ago
I always use this function so I don't have to retype over and over the mysql_real_escape_string function.

<?php
function safe($value){
   return
mysql_real_escape_string($value);
}
?>

Then, when I am using my code, I simply use:

<?php
$name
= safe($_POST["name"]);
$password = safe($_POST["password"]);
?>
up
2
ovoznyak at gmail dot com
2 years ago
Function safe_string_escape($str) above is not properly working when $str is numeric (not string).

For example, when call them as safe_string_escape((int) 12), it returns empty string. At the same time mysql_real_escape_string() returns 12.

So, it is safe to add $str = (string) $str; in the begin of function.
up
10
nicolas
8 years ago
Note that mysql_real_escape_string doesn't prepend backslashes to \x00, \n, \r, and and \x1a as mentionned in the documentation, but actually replaces the character with a MySQL acceptable representation for queries (e.g. \n is replaced with the '\n' litteral). (\, ', and " are escaped as documented) This doesn't change how you should use this function, but I think it's good to know.
up
5
stefan dot van dot beusekom at gmail dot com
3 years ago
Following is a recursive function that makes all the strings it finds safe for data entry. If the underlying value is an array, it will loop through that array as well, to inifity. So any array depth is allowed. This might come in handy when dealing with sessions, posts, gets or whatnot arrays, where you immediately want to make use of the data without having to filter the data first.

<?php
       
/*
         * Created by: Stefan van Beusekom
         * Created on: 31-01-2011
         * Description: A method that ensures safe data entry, and accepts either strings or arrays. If the array is multidimensional,
         *                     it will recursively loop through the array and make all points of data safe for entry.
         * parameters: string or array;
         * return: string or array;
         */
       
public function filterParameters($array) {
       
           
// Check if the parameter is an array
           
if(is_array($array)) {
               
// Loop through the initial dimension
               
foreach($array as $key => $value) {
                   
// Check if any nodes are arrays themselves
                   
if(is_array($array[$key]))
                       
// If they are, let the function call itself over that particular node
                       
$array[$key] = $this->filterParameters($array[$key]);
               
                   
// Check if the nodes are strings
                   
if(is_string($array[$key]))
                       
// If they are, perform the real escape function over the selected node
                       
$array[$key] = mysql_real_escape_string($array[$key]);
                }           
            }
           
// Check if the parameter is a string
           
if(is_string($array))
               
// If it is, perform a  mysql_real_escape_string on the parameter
               
$array = mysql_real_escape_string($array);
           
           
// Return the filtered result
           
return $array;
       
        }

?>
up
8
jeff at lindenlab dot com
2 years ago
Yes, this means that you have to start a connection before you can escape data... you can't escape the data first, and then use it to build your SQL, and then connect. 

Be aware of this when you're designing objects and architecture.
up
4
strata_ranger at hotmail dot com
4 years ago
There's an interesting quirk in the example #2 about SQL injection:  AND takes priority over OR, so the injected query actually executes as WHERE (user='aidan' AND password='') OR ''='', so instead of returning a database record corresponding to an arbitrary username (in this case 'aidan'), it would actually return ALL database records.  In no particular order.  So an attacker might be able to log in as any account, but not necessarily with any control over which account it is.

Of course a potential attacker could simply modify their parameters to target specific users of interest:

<?php

// E.g. attacker's values
$_POST['username'] = '';
$_POST['password'] = "' OR user = 'administrator' AND '' = '";

// Malformed query
$query = "SELECT * FROM users WHERE user='$_POST[username]' AND password='$_POST[password]'";

echo
$query;

// The query sent to MySQL would read:
// SELECT * FROM users WHERE user='' AND password='' OR user='administrator' AND ''='';
// which would allow anyone to gain access to the account named 'administrator'

?>
up
7
sam at numbsafari dot com
1 year ago
No discussion of escaping is complete without telling everyone that you should basically never use external input to generate interpreted code. This goes for SQL statements, or anything you would call any sort of "eval" function on.

So, instead of using this terribly broken function, use parametric prepared statements instead.

Honestly, using user provided data to compose SQL statements should be considered professional negligence and you should be held accountable by your employer or client for not using parametric prepared statements.

What does that mean?

It means instead of building a SQL statement like this:

"INSERT INTO X (A) VALUES(".$_POST["a"].")"

You should use mysqli's prepare() function (http://php.net/manual/en/mysqli.prepare.php) to execute a statement that looks like this:

"INSERT INTO X (A) VALUES(?)"

NB: This doesn't mean you should never generate dynamic SQL statements. What it means is that you should never use user-provided data to generate those statements. Any user-provided data should be passed through as parameters to the statement after it has been prepared.

So, for example, if you are building up a little framework and want to do an insert to a table based on the request URI, it's in your best interest to not take the $_SERVER['REQUEST_URI'] value (or any part of it) and directly concatenate that with your query. Instead,  you should parse out the portion of the $_SERVER['REQUEST_URI'] value that you want, and map that through some kind of function or associative array to a non-user provided value. If the mapping produces no value, you know that something is wrong with the user provided data.

Failing to follow this has been the cause of a number of SQL-injection problems in the Ruby On Rails framework, even though it uses parametric prepared statements. This is how GitHub was hacked at one point. So, no language is immune to this problem. That's why this is a general best practice and not something specific to PHP and why you should REALLY adopt it.

Also, you should still do some kind of validation of the data provided by users, even when using parametric prepared statements. This is because that user-provided data will often become part of some generated HTML, and you want to ensure that the user provided data isn't going to cause security problems in the browser.
up
2
manixrock -~- gmail ~-~ com
4 years ago
I've come up with an easy way to more easily escape things in an sql query. The simpler things are, the lower the chance that you'll forget to escape something. I use a helper class:

<?php
class MysqlStringEscaper
{
    function
__get($value)
    {
        return
mysql_real_escape_string($value);
    }
}
$str = new MysqlStringEscaper;
?>

then whenever I run a query I can simply do:

<?php
mysql_query
("SELECT * FROM users WHERE name LIKE '{$str->$name}' LIMIT 10");
?>

This way it's easy to see what the variable is escaped as (other instances like $int or $list could be implemented), it's inline and it only changes the variable when it's inserted into the query.
up
2
dinho19sp at gmail dot com
1 year ago
I use de form very simply on $ _REQUEST [], and I have no problems

  function objSqlRequest($StringVar){
       
        if(isset($_REQUEST[$StringVar])){
           
            $StringVar =  $_REQUEST[$StringVar];
           
        }
       
        return mysql_real_escape_string(trim($StringVar));
              
    }
up
2
kendsnyder at gmail dot com
5 years ago
<?php

// Here is a simple named binding function for queries that makes SQL more readable:
// $sql = "SELECT * FROM users WHERE user = :user AND password = :password";
// mysql_bind($sql, array('user' => $user, 'password' => $password));
// mysql_query($sql);

function mysql_bind(&$sql, $vals) {
    foreach (
$vals as $name => $val) {
       
$sql = str_replace(":$name", "'" . mysql_real_escape_string($val) . "'", $sql);
    }
}

?>
up
1
Anonymous
3 years ago
calling this function twice, or on a string for which quotes have already been escaped, causes the quotes to be escaped twice.An example is where we have to check for magic_quotes_gpc  before calling mysql_escape_string to sanitize the inputs.

The following function can be used to escape singe and double quotes in a string with out the risk of escaping quotes twice.This function  escapes a quote, only if it hasn't already been escaped.

<?php
function safe_string_escape($str)
{
  
$len=strlen($str);
   
$escapeCount=0;
   
$targetString='';
    for(
$offset=0;$offset<$len;$offset++) {
        switch(
$c=$str{$offset}) {
            case
"'":
           
// Escapes this quote only if its not preceded by an unescaped backslash
                   
if($escapeCount % 2 == 0) $targetString.="\\";
                   
$escapeCount=0;
                   
$targetString.=$c;
                    break;
            case
'"':
           
// Escapes this quote only if its not preceded by an unescaped backslash
                   
if($escapeCount % 2 == 0) $targetString.="\\";
                   
$escapeCount=0;
                   
$targetString.=$c;
                    break;
            case
'\\':
                   
$escapeCount++;
                   
$targetString.=$c;
                    break;
            default:
                   
$escapeCount=0;
                   
$targetString.=$c;
        }
    }
    return
$targetString;
}
echo
safe_string_escape("asda'sda\'dsad\"sadasd'");
?>

above code echoes

asda\'sda\'dsad\"sadasd\'

You can see that the second single quote wasnt escaped again..
up
1
upadrian at gmail dot com
3 years ago
<?php
/**
* @author upadrian@gmail.com
* Simplified version for array escape using mysql_real_escape_string
* for db store. Key names are not escaped beacuse i don't plain to
* include in a sql.
*
*/

function mres($q) {
    if(
is_array($q))
        foreach(
$q as $k => $v)
           
$q[$k] = mres($v); //recursive
   
elseif(is_string($q))
       
$q = mysql_real_escape_string($q);
    return
$q;
}

?>
up
0
mahdi
1 year ago
function clean($str) {
$cleaned = strip_tags($str);
$cleaned = htmlspecialchars(mysql_real_escape_string($cleaned));

return $cleaned;}
up
1
gustavo639 at gmail dot com
4 years ago
I use:

<?php
public static function escaparParametros(){
       
$numParametros = func_num_args();
       
$parametros = func_get_args();

        for (
$i = 0; $i < $numParametros; $i++){
           
$parametros[$i] = mysql_real_escape_string($parametros[$i]);
        }

        return
$parametros;
    }
?>
up
1
root at aeze dot ru
4 years ago
Here my simple but very effective function for safe mysql queries.

<?php
/**
* USAGE: mysql_safe( string $query [, array $params ] )
* $query - SQL query WITHOUT any user-entered parameters. Replace parameters with "?"
*     e.g. $query = "SELECT date from history WHERE login = ?"
* $params - array of parameters
*
* Example:
*    mysql_safe( "SELECT secret FROM db WHERE login = ?", array($login) );    # one parameter
*    mysql_safe( "SELECT secret FROM db WHERE login = ? AND password = ?", array($login, $password) );    # multiple parameters
* That will result safe query to MySQL with escaped $login and $password.
**/
function mysql_safe($query,$params=false) {
    if (
$params) {
        foreach (
$params as &$v) { $v = mysql_real_escape_string($v); }    # Escaping parameters
        # str_replace - replacing ? -> %s. %s is ugly in raw sql query
        # vsprintf - replacing all %s to parameters
       
$sql_query = vsprintf( str_replace("?","'%s'",$query), $params );   
       
$sql_query = mysql_query($sql_query);    # Perfoming escaped query
   
} else {
       
$sql_query = mysql_query($query);    # If no params...
   
}

    return (
$sql_query);
}
?>
up
0
anonymous at host dot com
4 years ago
You can also use the escape function in a manner as shown in the snapshot out of my own browsertools class:

<?php
//
// MySQL Database connection
//
public function mysqlConnect($host, $user, $password, $database) {
   
$this->mysql = mysql_connect($host, $user, $password);
    if (!
$this->mysql) die(mysql_error());
   
mysql_select_db($database, $this->mysql);
}

//
// MySQL Query
// usage:
//    $query such as "SELECT * FROM users WHERE nick = '%s' AND pass = '%s'"
//      where %s are the placeholders for the parameters
// call:
//    $__->mysqlQuery( $query, arg0, arg1, arg2, ... )
// description:
//    The parameters given to the function are escaped through mysql_real_escape_string(),
//    merged with the query and then given to the mysql_query function.
// returns:
//    Array of lines returned by the MySQL Database
//
public function mysqlQuery($query) {
   
$numParams = func_num_args();
   
$params = func_get_args();
   
    if (
$numParams > 1) {
        for (
$i = 1; $i < $numParams; $i++){
           
$params[$i] = mysql_real_escape_string($params[$i]);
        }
       
       
$query = call_user_func_array('sprintf', $params);
    }
   
   
$this->result = mysql_query($query, $this->mysql);
    if (!
$this->result) die(mysql_error());
   
$ret = array();
    while (
$row = mysql_fetch_assoc($this->result)) {
       
$ret[] = $row;
    }
   
mysql_free_result($this->result);
    return
$ret;
}
?>
up
0
paralescuoctavian at gmail dot com
4 years ago
Also don't forget to escape $_COOKIE array before quering the database. In firefox you can edit cookies and insert and inject harmful sql queries.

<?php
 
foreach ($_COOKIE as $key => $value) {
    if(
get_magic_quotes_gpc()) $_COOKIE[$key]=stripslashes($value);
   
$_COOKIE[$key] = mysql_real_escape_string($value);
  }
?>
up
0
adelbenzarti at yahoo dot fr
4 years ago
The function mysql_real_escape_string helps the developer to insert data without having troubles in the process or having risks of SQL Injection.
You can develop a similar function :
<?php
       
function escape($str)
        {
               
$search=array("\\","\0","\n","\r","\x1a","'",'"');
               
$replace=array("\\\\","\\0","\\n","\\r","\Z","\'",'\"');
                return
str_replace($search,$replace,$str);
        }
?>
up
0
presto dot dk at gmail dot com
4 years ago
If you want to make sure that the ID you're using to do a query is a number, use sprint() of (int) or intval(), but don't use mysql_real_escape_string.

There is no difference between ISO-8859-1's number 10 and UTF-8's number 10.
up
0
Anonymous
5 years ago
I use the following code in my database connection include file (which is of course called at the start of every page that needs to do some SQL)...
Therefore, all POST and GET vars are automatically escaped before being used anywhere in SQL statements.

<?php
 
//This stops SQL Injection in POST vars
 
foreach ($_POST as $key => $value) {
   
$_POST[$key] = mysql_real_escape_string($value);
  }

 
//This stops SQL Injection in GET vars
 
foreach ($_GET as $key => $value) {
   
$_GET[$key] = mysql_real_escape_string($value);
  }
?>
up
0
plgs at ozemail dot com dot au
5 years ago
Don't forget that if you're using Mysqli (ie, the "improved" Mysql extension) then you need to use the corresponding mysqli function mysqli_real_escape_string().  The parameter order is also different.
up
0
Anonymous
5 years ago
It is because you swapped $key and $item:

Just change this:
<?php
 
function mysql_safe ( $item, $key, $type )
 
?>

To:

<?php
       
function mysql_safe ( $key, $item, $type )
?>

And it will work as expected.
up
0
isaacs dot brian dot c at gmail dot com
5 years ago
I had wanted to see the merits of dynamically and "automatically" applying mysql_real_escape_string() to $_GET and $_POST as arrays rather than manually each time I would type up a query. I used array_walk_recursive() to call my function "mysql_safe" to apply mysql_real_escape_string() to each key of the $_GET and $_POST arrays.

My function is part of a class, and it is called each time I connect to the database to perform a query:

<?php
class MyClass {
        function
mysql_safe ( $key, $item, $type )
        {
            switch(
$type )
            {           
                case
'get':
                    if(
count( $_GET ) > 0 )
                    {
                       
$_GET[$item] = mysql_real_escape_string( $key );
                    }
                break;
                case
'post':
                    if(
count( $_POST ) > 0 )
                    {
                       
$_POST[$item] = mysql_real_escape_string( $key );
                    }
                break;
            }
        }
       
        function
safe_get ( )
        {
           
#Flag to only run function once           
           
if( $this->get_flag == true ) { return true; }

           
array_walk_recursive( $_GET, array( $this, 'mysql_safe' ), 'get' );
           
array_walk_recursive( $_POST, array( $this, 'mysql_safe' ), 'post' );
           
           
$this->get_flag = true;
        }
}
?>

However, after using this function, I find that it does indeed work, it also creates new $_GET and $_POST values in which $item and $key are swapped. So I end up with $_GET[$item] = $key, as well as $_GET[$key] = $item. I have not yet determined if this is due to the actual coding itself, or my particular method of implementation.

[EDIT BY danbrown AT php DOT net: Contains a bugfix by "Anonymous" on 13-JUL-09 to reorder the user function parameters.]
up
1
brian dot folts at gmail dot com
8 years ago
mysql_real_escape_string is a bit annoying when you need to do it over an array.

<?php
function mysql_real_escape_array($t){
    return
array_map("mysql_real_escape_string",$t);
}
?>

this one just mysql_real_escape's the whole array.

ex) <?php $_POST=mysql_real_escape_array($_POST); ?>

and then you dont have to worry about forgetting to do this.
up
0
user at NOSPAM dot example dot com
7 years ago
if you're doing a mysql wildcard query with
LIKE, GRANT, or REVOKE
you may use addcslashes to escape the string:

<?php
$param
= mysql_real_escape_string($param);
$param = addcslashes($param, '%_');
?>
up
0
kael dot shipman at DONTSPAMIT! dot gmail dot com
8 years ago
It seems to me that you could avoid many hassels by loading valid database values into an array at the beginning of the script, then instead of using user input to query the database directly, use it to query the array you've created. For example:

<?php
//you still have to query safely, so always use cleanup functions like eric256's
$categories = sql_query("select catName from categories where pageID = ?",$_GET['pageID']);
while (
$cts = @mysql_fetch_row($categories)) {
//making $cts both the name and the value of the array variable makes it easier to check for in the future.
//obviously, this naming system wouldn't work for a multidimensional array
$cat_ar[$cts[0]] = $cts[0];
}
...

//user selects sorting criteria
//this would be from a query string like '?cats[]=cha&cats[]=fah&cats[]=lah&cats[]=badValue...', etc.
$cats = $_GET['cats'];

//verify that values exist in database before building sorting query
foreach($cats as $c) {
if (
$cat_ar[$c]) { //instead of in_array(); maybe I'm just lazy... (see above note)
 
$cats1[] = "'".mysql_real_escape_string($c)."'";
}
}
$cats = $cats1;
//$cats now contains the filtered and escaped values of the query string

$cat_query = '&& (category_name = \''.implode(' || category_name = \'',$cats).'\')';
//build a sql query insert
//$cat_query is now "&& (category_name = 'cha' || category_name = 'fah' || category_name = 'lah')" - badValue has been removed
//since all values have already been verified and escaped, you can simply use them in a query
//however, since $pageID hasn't been cleaned for this query, you still have to use your cleaning function
$items = sql_query("SELECT * FROM items i, categories c WHERE i.catID = c.catID && pageID = ? $cat_query", $pageID);
up
-2
Ortreum
2 years ago
This small function walks through a complete array without a "normal" loop and convert all potentially "bad" inputs like $_POST and $_GET to mysql conform strings.

<?php
function db_conform($s)
{
    if (!
is_array($s)) mysql_real_escape_string($s);
    function
db_conform_array_callback(&$item, $key) { echo $key; $item = db_conform($item); }
   
array_walk($s, 'db_conform_array_callback');
    return
$s;
}

$_POST = db_conform($_POST);
?>
up
-2
Anonymous
2 years ago
If you try to escape a string which contains signs such as ’ or " and it doesnt work, check your website/file charset! Maybe it is NOT utf-8 ;)
up
-2
m-t at live dot fr
3 years ago
You should use mysql_real_escape_string only before inserting the data into your table, otherwise you could just use this function :

function reverse_escape($str)
{
  $search=array("\\\\","\\0","\\n","\\r","\Z","\'",'\"');
  $replace=array("\\","\0","\n","\r","\x1a","'",'"');
  return str_replace($search,$replace,$str);
}
up
-2
Bastiaan Welmers
6 years ago
This function won't help you when inserting binary data, to me it will get mallformed into the database. Probably UTF-8 combinations will be translated by this function or somewhere else when inserting data when running mysql in UTF-8 mode.

A better way to insert binary data is to transfer it to hexadecimal notation like this example:

<?php
$string
= $_REQUEST['string'];
$binary = file_get_contents($_FILE['file']['tmp_name']);

$string = mysql_real_escape_string($string);
$binary_hex = bin2hex($binary);

$query = "INSERT INTO `table` (`key`, `string`, `binary`, `other`) VALUES (NULL, '$string', 0x$binary_hex, '$other')";

?>
up
-1
matthijs at yourmediafactory dot com
6 years ago
In response to Michael D - DigitalGemstones.com:

Check the example again: sprintf(%d) already does the int conversion for you, so it's both perfectly save as well as more elegant than manually casting.
up
-1
Anonymous
6 years ago
My escape function:

Automatically adds quotes (unless $quotes is false), but only for strings. Null values are converted to mysql keyword "null", booleans are converted to 1 or 0, and numbers are left alone. Also can escape a single variable or recursively escape an array of unlimited depth.

<?php
function db_escape($values, $quotes = true) {
    if (
is_array($values)) {
        foreach (
$values as $key => $value) {
           
$values[$key] = db_escape($value, $quotes);
        }
    }
    else if (
$values === null) {
       
$values = 'NULL';
    }
    else if (
is_bool($values)) {
       
$values = $values ? 1 : 0;
    }
    else if (!
is_numeric($values)) {
       
$values = mysql_real_escape_string($values);
        if (
$quotes) {
           
$values = '"' . $values . '"';
        }
    }
    return
$values;
}
?>
To Top