Кавычки, слеши и безопасность скриптов

krafty

new Exception
Кавычки, слеши и безопасность скриптов

Добрый день!
Хочу поделиться своими соображениями по этой теме.
Я рассмотрю два случая. А вас попрошу оценить правильность моих утверждений.
Итак, первый случай - использование в запросе гет переменных.

.../script.php?param=...

Чтобы защититься от sql иньекций через адресную строку, необходимо выполнить сдедующее:
1. в запросе заключать в кавычки переменную $param, а если она целочисленного типа, то еще и применять к ней intval() (дробного - (float)$param )
2. использовать mysql_real_escape_string($param), которая прослешивает кавычки и другие спецсимволы
3. для использования в операторе LIKE нужно прослешить метасимволы поиска функцией addCslaches().

Второй случай - получение данных от пользователя, сохранение их в базе и вывод в браузер:
1. действия перед занесением в базу рассматривались выше
2. перед выводом в браузер необходимо применять к данным htmlspecialchars()
3. далее проверяем включен ли режим волшебных кавычек. если включен, то убиваем слеши в данных, поступающих от пользователя (get, post, cookie, ...).

С нетерпением жду рецензии!
 

dvp

Новичок
А я думаю, что с аргументами целого типа лучше делать (int) а не intval, ибо
You cannot use intval() on arrays or objects.
 

krafty

new Exception
2SiMM
Если я правильно понял вашу систему нумерации, то 2.3 - это 2 случай 3 пункт. В связи с этим у меня возникает вопрос:
почему? ведь на phpfaq.ru написано, что "если не получается отключить волшебные кавычки, то нужно очистить воходящие данные от слешей" - почти дословная цитата

А что такое 2.0 - это для меня загадка

2dvp - учту!
 

SiMM

Новичок
> ведь на phpfaq.ru написано, что "если не получается отключить волшебные кавычки, то нужно очистить воходящие данные от слешей"
Абсолютно верно. Однако именно благодаря этому FAQ и определяется правильная последовательность действий из 3х простых правил:
1. Убираем добавленные слэши и исключаем возможность их неожиданного добавления. До любых остальных действий. Таким образом программа уже заведомо работает без слэшей и помнить об этом никогда не надо.
2. При работе с базой используем mysql_real_escape_string. К любым данным. Что от пользователя, что полученным в результате работы скрипта.
3. При выводе данных пользователю по необходимости - htmlspecialchars.

> А что такое 2.0 - это для меня загадка
0 - это цифра перед 1. Объясняю, почему это в первую очередь, а не в последнюю - в базу могут заноситься и данные от пользователя. В этом случае они так и будут занесены со слэшами - а это и есть бессмыслица и глупость.
 

krafty

new Exception
Я понял. Просто у меня последовательность действий неправильная

-~{}~ 01.09.05 15:23:

Только что посетила мысль. А если в данных, пришедших от пользователя есть слеш, то при таком решении проблемы мы его потеряем.

Интересно вызовы
set_magic_quotes_runtime(0);
set_magic_quotes_gpc(0);
всегда работают?
Если да, то слеши можно вообще не удалять
 

Сергей123

Новичок
>> set_magic_quotes_gpc
:) где нашёл

>> при таком решении проблемы мы его потеряем
нет; подумай ещё
 

svetasmirnova

маленький монстрик
>в запросе заключать в кавычки переменную $param, а если она целочисленного типа, то еще и применять к ней intval() (дробного - (float)$param )

Надо проверять ВСЕ входные данные на соответствие ожиданиям. Приведение типов не спасёт. Пример: echo intval('string');
 

krafty

new Exception
Сергей, а ini_set() не поможет?
Я подумал ЕЩЕ: если включен режим magic quotes, то необходимо использовать stripslashes. а если в строке есть слеш: "cat\". далее в скрипт заходит "cat\\". ну а stripslashes выдает "cat"

svetasmirnova, echo intval('string') выведет 0.

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

svetasmirnova

маленький монстрик
>такое впечатление, что эту проблему давно все решили. только я один такой непонимающий остался
мудрые слова =)
Вобщем-то у тебя всё правильно, кроме того, что я показала. magic_quotes, по возможности, нужно отключать всегда. Поможет ли ini_set: см. в мануале где их можно менять.
 

krafty

new Exception
вообще у меня на хостинге чертовы кавычки отключены. но я всеже хотел сделать универсальное приложение.

Ринат, но ведь stripslashes("cat\\") возвращает "cat".
 

SiMM

Новичок
> но ведь stripslashes("cat\\") возвращает "cat".
[m]stripslashes[/m]
В конце концов, есть такой способ познания истины, как эксперимент (в данном случае - прокатит).
 

krafty

new Exception
именно путем эксперимента и узнал:
echo (stripslashes("cat\\")) //напечатает cat
этим же путем узнал, что если провернуть через форму, то все сработает:
set_magic_quotes_runtime(1);
if (isset($_POST['go']))
echo stripslashes($_POST['text']);

вводим "cat\" - выдает "cat\". сохранилось в первозданном виде!
 

Сергей123

Новичок
Ну, так чему ты удивляешься?
PHP:
echo stripslashes("cat\\");
потому и печатает cat.

А если в поле ввели cat\, (mq включены) в суперглобале получилось cat\\, а после стрипа - cat\. Ты же $_POST['ляля'] даёшь стрипу, а не строку в двойных кавычках.
 

krafty

new Exception
это я понял. спасибо огромное.

пока я беседовал с вами состряпал библиотечку:
PHP:
<?php # организация безопасного получения данных от пользователя и защита от sql иньекций

set_magic_quotes_runtime(0);
//эта функция заимствована из phpfaq.ru
function strips(&$el) { 
  if (is_array($el)) 
    foreach($el as $k=>$v) 
      strips($el[$k]); 
  else $el = stripslashes($el); 
} 
if (get_magic_quotes_gpc()) { 
  strips($_GET); 
  strips($_POST); 
  strips($_FILES); 
  strips($_COOKIE); 
  strips($_REQUEST); 
  if (isset($_SERVER['PHP_AUTH_USER'])) strips($_SERVER['PHP_AUTH_USER']); 
  if (isset($_SERVER['PHP_AUTH_PW']))   strips($_SERVER['PHP_AUTH_PW']);
}
//экранирование спецсимволов в переменных, участвующих в формировании запроса
//а также приведение типов пременных
function for_query($param,$type)
{
    switch ($type) {
      case 'int': $param=(int)$param; break;
      case 'float': $param=(float)$param; break;
    }  
    return mysql_escape_string($param);
} 
//добавление слешей к метасимволам
function for_like_expr($str)
{
    return addcslashes($str,'%_');
}
?>

//применение
mysql_query("SELECT * FROM t WHERE date1='".for_query($date1,'str')."' AND id='".for_query($id,'int')."' AND text LIKE '".for_like_expr("%$text%")."'");
-~{}~ 01.09.05 18:58:

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