- mysql_real_escape_string SQL injection
- Escaped Characters
- Correct Usage
- How Not To Use
- Numeric Parameters and mysql_real_escape_string
- LIKE Operator Wildcards
- Alternative Solutions
- Do you want to try the simulation?
- mysql_real_escape_string
- Описание
- Безопасность: кодировка символов по умолчанию
- Список параметров
- Возвращаемые значения
- Примеры
- Примечания
- Смотрите также
- mysql_escape_string
- Description
- Parameters
- Return Values
- Examples
- Notes
- See Also
- User Contributed Notes 1 note
mysql_real_escape_string SQL injection
PHP provides mysql_real_escape_string() to escape special characters in a string before sending a query to MySQL. This function was adopted by many to escape single quotes in strings and by the same occasion prevent SQL injection attacks. However, it can create serious security flaws when it is not used correctly.
Escaped Characters
What exactly does mysql_real_escape_string function do? It prepends a backslash to every special character in the first parameter. Special characters considered are listed below.
Characters escaped by mysql_real_escape_string
Correct Usage
Here is a classic and secure way to use this function as input sanitizer for string parameters.
SELECT id FROM products WHERE name=’ a\’ OR \’a\’=\’a ‘
Since the last example is secured against SQL injections, the query generated will return no result (except if a product is really named as the green segment). What is important to remember here is that you must always enclose the sanitized parameter between quotes when using mysql_real_escape_string() otherwize a SQL injection vulnerability will be created.
How Not To Use
Programmers should be really careful when using mysql_real_escape_string function to sanitize numeric parameters since they are habitually integrated in the query without quotes. The function discussed in this article does not verify data types; it simply escapes some special characters. Here is a code sample that shows how SQL injection could be achieved when mysql_real_escape_string is not correctly implemented.
SELECT name FROM products WHERE >9999 OR 1=1
When the query is executed, all products’ name are returned because the crafted parameter submitted by the attacker is considered as a part of the SQL segment.
Numeric Parameters and mysql_real_escape_string
As stated earlier in the article, the parameter sanitized by mysql_real_escape_string must be enclosed between quotes in order to avoid SQL injection (no matter the data type). MySQL Server (and other popular DBMS) supports single quotes around numeric values. Here is what the last example would look like after the security fix:
Malicious user input — A numeric value is expected by the script.
Query generated — Attack voided.
SELECT name FROM products WHERE >9999 OR 1=1 ‘
The last query will return no name.
LIKE Operator Wildcards
There is one last thing to consider when using mysql_real_escape_string to sanitize data; the function does not escape SQL wildcards for LIKE operator. It might seem trivial but in fact it can have a considerable impact on the query’s behavior. Since those characters are not escaped, they are considered as classic wildcards by the LIKE operator:
% Matches an arbitrary number of characters (including zero character).
_ Matches any single character.
To prevent a wildcard match you must escape the corresponding character with a backslash. Here is how it can be done:
Sanitize data (also escape all MySQL wildcards).
Generated query (search all products where the description contains exact match of user input).
SELECT * FROM products WHERE description LIKE ‘% john\’s ca\_ %’
Even if most of the time you should escape wildcards characters, there are some cases where you may want the user to use them. Just keep in mind that in those situations, the user could build input strings difficult to match and it might have some performance impact on LIKE operator (available soon) . This is not a critical issue, however if an attacker tries to slow down the application or make a DDOS it might be easier with a control over wildcards characters.
Alternative Solutions
Using mysql_real_escape_string is without a doubt a simple way to secure an application against SQL injections, however it is far from the perfect world. Every time this function is used to sanitize data, it calls MySQL’s library function. It is not a big deal but if you make a large number of calls to mysql_real_escape_string it will slow down your database server. Moreover if you mistakenly call the function twice on the same data you will end up with incorrect information in your database.
For those reasons, it is suggested to adopt alternative solutions such as parameterized statements or stored procedures as explained in the article about preventing SQL injections in PHP (article available soon) .
Do you want to try the simulation?
You can download a secure simulation environment to try every techniques explained on this website. It’s totally free!
mysql_real_escape_string
Данное расширение устарело, начиная с версии PHP 5.5.0, и будет удалено в будущем. Используйте вместо него MySQLi или PDO_MySQL. Смотрите также инструкцию MySQL: выбор API и соответствующий FAQ для получения более подробной информации. Альтернативы для данной функции:
Описание
string mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier = NULL ] )
Экранирует специальные символы в unescaped_string , принимая во внимание кодировку соединения, таким образом, что результат можно безопасно использовать в SQL-запросе в функции mysql_query() . Если вставляются бинарные данные, то к ним так же необходимо применять эту функцию.
mysql_real_escape_string() вызывает библиотечную функцию MySQL mysql_real_escape_string, которая добавляет обратную косую черту к следующим символам: \x00, \n, \r, \, ‘, « и \x1a.
Эта функция должна всегда (за несколькими исключениями) использоваться для того, чтобы обезопасить данные, вставляемые в запрос перед отправкой его в MySQL.
Безопасность: кодировка символов по умолчанию
Кодировка символов должна устанавливаться как на сервере, так и с помощью функции mysql_set_charset() , чтобы влиять на поведение mysql_real_escape_string() . Подробнее описано в разделе кодировка символов.
Список параметров
Соединение MySQL. Если идентификатор соединения не был указан, используется последнее соединение, открытое mysql_connect() . Если такое соединение не было найдено, функция попытается создать таковое, как если бы mysql_connect() была вызвана без параметров. Если соединение не было найдено и не смогло быть создано, генерируется ошибка уровня E_WARNING .
Возвращаемые значения
Возвращает строку, в которой экранированы все необходимые символы, или FALSE в случае ошибки.
Примеры
Пример #1 Простой пример использования mysql_real_escape_string()
// Соединение
$link = mysql_connect ( ‘mysql_host’ , ‘mysql_user’ , ‘mysql_password’ )
OR die( mysql_error ());
?php
// Запрос
$query = sprintf ( «SELECT * FROM users WHERE user=’%s’ AND password=’%s'» ,
mysql_real_escape_string ( $user ),
mysql_real_escape_string ( $password ));
?>
Пример #2 Пример взлома с использованием SQL-инъекции
// Мы не никак проверили переменную $_POST[‘password’],
// а она может содержать совсем не то, что мы ожидали. Например:
$_POST [ ‘username’ ] = ‘aidan’ ;
$_POST [ ‘password’ ] = «‘ OR »='» ;
?php
// посылаем запрос, чтобы проверить имя и пароль пользователя
$query = «SELECT * FROM users WHERE user=’ < $_POST [ 'username' ]>‘ AND password=’ < $_POST [ 'password' ]>‘» ;
mysql_query ( $query );
// посмотрим, какой запрос будет отправлен в MySQL:
echo $query ;
?>
Запрос, который будет отправлен в MySQL:
SELECT * FROM users WHERE user='aidan' AND password='' OR ''=''
Это позволит кому угодно войти в систему без пароля.
Примечания
Замечание:
Функцию mysql_real_escape_string() можно использовать только после того, как установлено соединение с MySQL. В противном случае возникнет ошибка уровня E_WARNING , а функция возвратит FALSE . Если link_identifier не указан, используется последнее открытое соединение.
Замечание:
Если magic_quotes_gpc включены, то сначала данные следует обработать функцией stripslashes() . Если данную функцию применить к уже проэкранированным данным, то данные будут проэкранированы дважды.
Замечание:
Если не пользоваться этой функцией, то запрос становится уязвимым для взлома с помощью SQL-инъекций.
Замечание: mysql_real_escape_string() не экранирует символы % и _. Эти знаки являются масками групп символов в операторах MySQL LIKE, GRANT и REVOKE.
Смотрите также
- mysql_set_charset() — Устанавливает кодировку клиента
- mysql_client_encoding() — Возвращает кодировку соединения
- addslashes() — Экранирует строку с помощью слешей
- stripslashes() — Удаляет экранирование символов
- Директива magic_quotes_gpc
- Директива magic_quotes_runtime
mysql_escape_string
This function was deprecated in PHP 4.3.0, and it and the entire original MySQL extension was removed in PHP 7.0.0. Instead, use either the actively developed MySQLi or PDO_MySQL extensions. See also the MySQL: choosing an API guide. Alternatives to this function include:
Description
This function will escape the unescaped_string , so that it is safe to place it in a mysql_query() . This function is deprecated.
This function is identical to mysql_real_escape_string() except that mysql_real_escape_string() takes a connection handler and escapes the string according to the current character set. mysql_escape_string() does not take a connection argument and does not respect the current charset setting.
Parameters
The string that is to be escaped.
Return Values
Returns the escaped string.
Examples
Example #1 mysql_escape_string() example
$item = «Zak’s Laptop» ;
$escaped_item = mysql_escape_string ( $item );
printf ( «Escaped string: %s\n» , $escaped_item );
?>?php
The above example will output:
Escaped string: Zak\'s Laptop
Notes
Note:
mysql_escape_string() does not escape % and _ .
See Also
User Contributed Notes 1 note
You can use this function safely with your MySQL database queries if and only if you are sure that your database connection is using ASCII, UTF-8, or ISO-8859-* and that the backslash is your database’s escape character. If you’re not sure, then use mysqli_real_escape_string instead. This function is not safe to use on databases with multi-byte character sets.
The only benefit of this function is that it does not require a database connection.
- MySQL Functions
- mysql_affected_rows
- mysql_client_encoding
- mysql_close
- mysql_connect
- mysql_create_db
- mysql_data_seek
- mysql_db_name
- mysql_db_query
- mysql_drop_db
- mysql_errno
- mysql_error
- mysql_escape_string
- mysql_fetch_array
- mysql_fetch_assoc
- mysql_fetch_field
- mysql_fetch_lengths
- mysql_fetch_object
- mysql_fetch_row
- mysql_field_flags
- mysql_field_len
- mysql_field_name
- mysql_field_seek
- mysql_field_table
- mysql_field_type
- mysql_free_result
- mysql_get_client_info
- mysql_get_host_info
- mysql_get_proto_info
- mysql_get_server_info
- mysql_info
- mysql_insert_id
- mysql_list_dbs
- mysql_list_fields
- mysql_list_processes
- mysql_list_tables
- mysql_num_fields
- mysql_num_rows
- mysql_pconnect
- mysql_ping
- mysql_query
- mysql_real_escape_string
- mysql_result
- mysql_select_db
- mysql_set_charset
- mysql_stat
- mysql_tablename
- mysql_thread_id
- mysql_unbuffered_query