downloads | documentation | faq | getting help | mailing lists | licenses | wiki | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

mysql_result> <mysql_query
Last updated: Fri, 20 Nov 2009

view this page in

mysql_real_escape_string

(PHP 4 >= 4.3.0, PHP 5)

mysql_real_escape_stringDodaje znaki unikowe dla potrzeb poleceń SQL, biorąc po uwagę zestaw znaków używany w połączeniu.

Opis

string mysql_real_escape_string ( string $łańcuch_bez_znaków_unikowych [, resource $identyfikator_połączeniar ] )

Dodaje znaki unikowe do łańcucha_bez_znaków_unikowych , mając na uwadze aktualnie używany w połączeniu zestaw znaków by tak przygotowanego łańcucha można bezpiecznie użyc w funkcji mysql_query(). Jeśli dopisywane dane mają postać binarną wymagane jest użycie tej funkcji.

mysql_real_escape_string() wywołuje funkcję biblioteki MySQL mysql_real_escape_string, która dodaje lewe ukośniki (backslash) do następujących znaków: \x00, \n, \r, \, ', " and \x1a.

Użycie tej funkcji jest wymagane zawsze (poza kilkoma wyjątkami) przed wysłaniem zapytania do bazy danych aby zabezpieczyć dane.

Parametry

łańcuch_bez_znaków_unikowych

Łańcuch, do którego zostaną dodane znaki unikowe.

identyfikator_połączenia

Połączenie MySQL. Jeśli identyfikator połączenia nie zostanie podany, użyte zostanie ostatnie połączenie otwarte przez mysql_connect(). Jeśli połączenie takie nie zostanie znalezione, funkcja spróbuje nawiązać połączenie tak, jakby wywołana została funkcja mysql_connect() bez argumentów. Jeśli żadne połączenie nie zostanie znalezione lub nawiązane, wygenerowany zostanie błąd poziomu E_WARNING.

Zwracane wartości

Zwraca łańcuch ze znakami unikowymi lub FALSE w przypadku błędu.

Przykłady

Przykład #1 Prosty przykład użycia mysql_real_escape_string()

<?php
// Connect
$link mysql_connect('host''uzytkownik''haslo')
    OR die(
mysql_error());

// Zapytanie
$query sprintf("SELECT * FROM uzytkownicy WHERE uzytkownik='%s' AND haslo='%s'",
            
mysql_real_escape_string($uzytkownik),
            
mysql_real_escape_string($haslo));
?>

Przykład #2 Przykład ataku SQL Injection

<?php
// Zapytanie pobierające pasujących użytkowników
$query "SELECT * FROM uzytkownicy WHERE uzytkownik='{$_POST['nazwa_uzytkownika']}' AND haslo='{$_POST['haslo']}'";
mysql_query($query);

// Nie sprawdziliśmy zmiennej $_POST['haslo'], która może zawierać wszystko czego chciał użytkownik! Na przykład:
$_POST['nazwa_uzytkownika'] = 'aidan';
$_POST['haslo'] = "' OR ''='";

// Oznacza to, że zapytanie ma postać:
echo $query;
?>

Zapytanie wysłane do bazy danych:

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

Zapytanie to pozwala zalogować się każdemu bez znajomości poprawnego hasła.

Przykład #3 Dobra praktyka tworzenia zapytań

Użycie mysql_real_escape_string() na każdej zmiennej zapobiegnie atakom SQL Injection. Przykład ten demonstruje dobrą praktykę tworzenia zapytań, niezależną od ustawień Magic Quotes.

<?php

if (isset($_POST['nazwa_produktu']) && isset($_POST['opis_produktu']) && isset($_POST['id_uzytkownika'])) {
    
// Połącz

    
$link mysql_connect('host''uzytkownik''haslo');

    if(!
is_resource($link)) {

        echo 
"Nie udało się połączyć z serwerem\n";
        
// ... logowanie błędów

    
} else {
        
        
// Odwróć efekty działania magic_quotes_gpc/magic_quotes_sybase na zmiennych jeśli opcje te są WŁĄCZONE.

        
if(get_magic_quotes_gpc()) {
            
$nazwa_produktu stripslashes($_POST['nazwa_produktu']);
            
$opis_produktu  stripslashes($_POST['opis_produktu']);
        } else {
            
$nazwa_produktu $_POST['nazwa_produktu'];
            
$opis_produktu  $_POST['opis_produktu'];
        }

        
// Stwórz bezpieczne zapytanie
        
$query sprintf("INSERT INTO products (`nazwa`, `opis`, `id_uzytkownika`) VALUES ('%s', '%s', %d)",
                    
mysql_real_escape_string($nazwa_produktu$link),
                    
mysql_real_escape_string($opis_produktu$link),
                    
$_POST['id_uzytkownika']);

        
mysql_query($query$link);

        if (
mysql_affected_rows($link) > 0) {
            echo 
"Produkt został dopisany\n";
        }
    }
} else {
    echo 
"Wypełnij poprawnie formularz\n";
}
?>

Od teraz zapytanie będzie poprawne wykonywane, podczas gdy ataki SQL Injection nie będą działać.

Notatki

Informacja: Przed użyciem mysql_real_escape_string() należy otworzyć połączenie z bazą danych, w innym przypadku błąd poziomu E_WARNING zostanie wygenerowany i zwrócona zostanie wartość false. Jeśli identyfikator_połączenia nie został zdefiniowany zostanie użyte ostatnie połączenie z bazą danych.

Informacja: Jeśli opcja magic_quotes_gpc została włączona, najpierw na danych należy użyć stripslashes(). Użycie tej funkcji samej spowoduje, że do danych zostaną dodane podwójne znaki unikowe.

Informacja: Jeśli funkcja ta nie zostanie użyta na danych, zapytanie będzie podatne na ataki SQL Injection Attacks.

Informacja: mysql_real_escape_string() nie dodaje znaków unikowych do % i _. Maski te (wildcard) są stosowane w zapytaniach MySQL w połączeniu z LIKE, GRANT lub REVOKE.

Zobacz też:



mysql_result> <mysql_query
Last updated: Fri, 20 Nov 2009
 
add a note add a note User Contributed Notes
mysql_real_escape_string
alan_a_williams [at] hotmail [dot] com
19-Aug-2009 11:17
Just a little something I like to use....

$_GET = array_map('trim', $_GET);
$_POST = array_map('trim', $_POST);
$_COOKIE = array_map('trim', $_COOKIE);
$_REQUEST = array_map('trim', $_REQUEST);
if(get_magic_quotes_gpc()):
    $_GET = array_map('stripslashes', $_GET);
    $_POST = array_map('stripslashes', $_POST);
    $_COOKIE = array_map('stripslashes', $_COOKIE);
    $_REQUEST = array_map('stripslashes', $_REQUEST);
endif;
$_GET = array_map('mysql_real_escape_string', $_GET);
$_POST = array_map('mysql_real_escape_string', $_POST);
$_COOKIE = array_map('mysql_real_escape_string', $_COOKIE);
$_REQUEST = array_map('mysql_real_escape_string', $_REQUEST);

Seems to do the trick ALOT of the time, but I'm going to be honest, it can be a [EDITED] sometimes >_>
Anonymous
02-Aug-2009 10:45
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);
  }
?>
plgs at ozemail dot com dot au
27-Jul-2009 08:05
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.
Anonymous
13-Jul-2009 03:30
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.
isaacs dot brian dot c at gmail dot com
12-Jul-2009 06:06
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.]
info at saturnprods dot com
13-Jun-2009 07:37
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"]);
?>
kendsnyder at gmail dot com
25-Mar-2009 09:07
<?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);
    }
}

?>
Bastiaan Welmers
24-Mar-2008 07:46
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')";

?>
Anonymous
03-Mar-2008 06:57
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;
}
?>
matthijs at yourmediafactory dot com
27-Dec-2007 09:49
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.
user at NOSPAM dot example dot com
28-Aug-2007 12:16
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, '%_');
?>
brian dot folts at gmail dot com
06-Sep-2006 04:25
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.
kael dot shipman at DONTSPAMIT! dot gmail dot com
18-Jul-2006 08:19
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);
nicolas
30-May-2006 08:38
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.

mysql_result> <mysql_query
Last updated: Fri, 20 Nov 2009
 
 
show source | credits | stats | sitemap | contact | advertising | mirror sites