Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В. C++. Мастер-класс в задачах и примерах. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5. На примерах. Авторы: Кузнецов М.В., Симдянов И.В., Голышев С.В. Объектно-ориентированное программирование на PHP. Авторы: Кузнецов М.В., Симдянов И.В. Программирование. Ступени успешной карьеры. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум MySQL

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Еще раз про экранирование...
 
 автор: aalexx   (12.03.2006 в 18:46)   письмо автору
 
 

Подскажите пожалуйста как все таки правильно экранировать данные при использовании их в SQL запросах. Стоит ли делать вот так:

$name=htmlspecialchars(stripslashes(trim(mysql_escape_string($login))));

или это лишние предосторожности? В общем как правильно подготовить строку str для записи в базу данных MySQL?

   
 
 автор: cheops   (12.03.2006 в 19:53)   письмо автору
 
   для: aalexx   (12.03.2006 в 18:46)
 

Нет так делать не стоит хотя бы из-за того, что на сервере может быть включён режим магических кавычек, да и сама последовательность функций
stripslashes(mysql_escape_string($login))

имеет нулевой эффект.
Для экранирования следует применять конструкцию
<?php
  
if (!get_magic_quotes_gpc())
  {
    
$name mysql_escape_string($name);
  }
?>

Кроме этого, функцию htmlspecialchars() обычно применяют не до помещения в базу данных, а перед выводом из базы данных на страницу. Иначе, если потребуется редактирование информации - будет сложно работать.

   
 
 автор: Trianon   (12.03.2006 в 20:07)   письмо автору
 
   для: aalexx   (12.03.2006 в 18:46)
 

так делать не стоит ни в коем случае. Надо четко представлять себе,
1. В каком виде данные попадают скрипту на вход.
2. В каком виде данные нужно передать туда, куда мы их отправляем

Попытка применить скопом несколько снадобий только увеличит риск sql-injection-уязвимости и/или других видов атак.

1. Если данные на вход скрипту приходят из get/post/cookie параметров, их скорее всего успел подвергнуть экранированию кавычек нуля и обратных слэшей сам движок PHP. Или не успел. Зависит от настройки PHP, известной под названием magic_quotes_gpc . Чтобы убрать неопределенность, надо проверить настройки, и при необходимости удалить зазря понаставленные слэши:
<?
$login 
$_POST['login'];               // Берем занчение параметра

if(get_magic_quotes_gpc())         // если включен режим magic_quotes
   
$login stripslashes($login);   //   то удалим слэши, добавленные PHP
?>

На этом месте с параметром можно работать, как с любой другой переменной, хранящей строковое значение.

2. В дальнейшей работе параметр нужно экранировать, применяя правило экранирования для того языка, где этот параметр будет применяться. Но лишь одно правило, а не все скопом.


Если параметр нужно использовать в mysql-запросе, как строковый литерал, то его надо взять в кавычки.
Но написать просто $login = ""'$login'"; мы не можем. Вот здесь идет самый важный логический шаг. Мы должны использовать экранирование вовсе не потому, что боимся sql-инъекции, а потому что синтаксис SQL-языка предписывает некоторые символы в строковых литералах предварять слэшами:
<?
$query 
"insert into users (login) values('".mysql_escape_string($login)."'";
?>

или
<?
$query 
"select name from users where login='".mysql_escape_string($login)."'";
?>


Если значение нужно передать, как часть параметра url, его нужно экранировать. Но опять же, вовсе не потому, что мы боимся вредноносных javascript-вставок, а потому, что значение в URL пишется на некотором языке (RFC--1738) со своими правилами замены пробелов, символов национальных алфавитов и некоторых других спецсимволов.
<?
$url 
"info.php?login=".urlencode($login); 
?>

Если и будет в логине какой хитрый знак, он все-равно попадет в параметр, а не выйдет из-под контроля.


Теперь допустим , что этот url нужно сделать частью ссылки: <a href="url">login</a>
Сперва разбираемся с тегом <a> и его атрибутом href. Согласно спецификации языка html, текстовые значения атрибутов , обрамляются двойными кавычками, а сами двойные кавычки, содержащиеся в значении расписываются html-сущностями. Ими же распиывается знак амперсенда, и угловые скобки. Для этого применяется функция htmlspecialchars():
<?
$href 
'href="'.htmlspecialchars($url).'"';
?>


Внутри тега <a>, где нам нужно поместить логин, действуют те же правила записи html-символов.
Чтобы от языка текст перейти к языку html, нужно спецсимволы html-языка (кавычки, угловые скобки, амперсанд ) закодировать соответствующими html-сущностями. Для этого применяем htmlspecialchars():

<?
 $reference   
"<a $href>" htmlspecialchars($login) . "</a>";
?>

И в таком виде уже можем выкинуть в выходной поток.
<?
echo $reference;
?>


Теперь, наконец, допустим, что текст этой ссылки нам нужно не просто вывести, а передать в JavaScript, как значение некоей переменной ref. Правила записи строковых литералов JavaScript требуют заэкранировать кавычки и обратные слэши и обрамить полученное кавычками. Реализуется это с помощью addslashes():

<?
$js_str 
"'".addslashes($reference)."'";
echo 
"<script language=javascript>var ref = $js_str; document.writeln(ref);</script>";
?>



Важно четко понимать, что применять функции экранирования следует по одной, и именно там, где происходит переход от одного языка к другому. И применять именно ту функцию, которая согласует один язык с другим. В противном случае, возможны бреши в защите.

   
 
 автор: aalexx   (13.03.2006 в 11:14)   письмо автору
 
   для: Trianon   (12.03.2006 в 20:07)
 

Спасибо огромное, по моему исчерпывающий ответ! Господа Модераторы, предлагаю сделать из этого поста статью и смело поместить ее в список статей на Вашем сайте. Уверен что 90% начинающих РНР программистов либо тупо делают именно так как было показанно в моем примере (кстати пример я взял в одной из тем не этом форуме, так что судите сами :)) либо вообще не знают что и как надо делать.
Есть еще вопрос. Если поле в таблице ну скажем утановленно как varchar(10), а мне нужно записать туда строку из 10 символов содержащую спецсимволы (например кавычки "") после экранирования добавив слэши не произойдет ли ошибка при записи в базу данных (строка то уже получится не 10 а 12 символов)?

   
 
 автор: Trianon   (13.03.2006 в 11:36)   письмо автору
 
   для: aalexx   (13.03.2006 в 11:14)
 

Есть значение поля длиной 10 и есть литеральное представление значения этого поля длиной 12 или даже 20 (для десяти кавычек например). Контролируется именно длина значения.
Попробуйте выполнить следующий код:
CREATE TABLE tab (   text char(3) NULL );
INSERT INTO tab (text) VALUES ('abc'), ('\'\\\"'),('defghi');
SELECT * FROM tab;

На выходе будет:
text
----
abc
'\"
def

   
 
 автор: aalexx   (13.03.2006 в 11:45)   письмо автору
 
   для: Trianon   (13.03.2006 в 11:36)
 

т.е. Вы хотите сказать что движок просто обрезает строку если она не совпадает по длинне со значением заданным в поле базы данных? =-О или всетаки выдается ошибка записи?

   
 
 автор: Trianon   (13.03.2006 в 11:54)   письмо автору
 
   для: aalexx   (13.03.2006 в 11:45)
 

Я хочу сказать, что применение литерала (апостроф слэш апостроф слэш слэш слэш кавычка апостроф) длиной 8 знаков с учетом обрамления, представляющего текст (апостроф слэш кавычка) длиной 3 знака привело к тому, что текст был внесен в поле шириной 3 символа безо всяких искажений. Несмотря на Ваши опасения. А применение литерала 'defghi' той же длины, представляющего текст длиной 6 символов, повлекло обрезание текста до размера поля.
Как именно реагирует СУБД на попытку внести слишком длинный текст - диагностикой ошибки, усечением текста или раздуванием поля - вопрос совсем другой.

   
 
 автор: aalexx   (13.03.2006 в 12:07)   письмо автору
 
   для: Trianon   (13.03.2006 в 11:54)
 

Понятно спасибо!

   
 
 автор: Trianon   (16.03.2006 в 19:12)   письмо автору
 
   для: Trianon   (12.03.2006 в 20:07)
 

-

   
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования