Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Безопасная валидация данных

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (2): [1] 2 »   

> Без описания
nepster
Отправлено: 14 Августа, 2013 - 14:34:11
Post Id



Частый гость


Покинул форум
Сообщений всего: 195
Дата рег-ции: Июль 2012  


Помог: 0 раз(а)




Подскажите пожалуйста, кто как работает с полученными данными, и каким образом вы делаете валидацию ?

К примеру получаем следующие пост данные:

PHP:
скопировать код в буфер обмена
  1. (
  2.     [user_id] => 256 // автор новости
  3.     [news_id] => 23 // новость, которую редактируем
  4.     [news_name] => Новость
  5.     [news_short] => Краткое описание
  6.     [news_full] => Полное описание
  7.     [news_date] => Дата публикации
  8.     [news_status] => // например от -1 до 2
  9. )


вот например есть функция
PHP:
скопировать код в буфер обмена
  1.  
  2. public function news_edit($data)
  3. {
  4.    // валидация данных
  5. }
  6.  


Собственно интересны методы какими кто обрабатывает данные, особенно через что прогонять строги, что бы защититься от sql инъекций
 
 Top
Мелкий Супермодератор
Отправлено: 14 Августа, 2013 - 14:45:00
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




nepster пишет:
защититься от sql инъекций

Препарированные запросы.
Всё. Больше от инъекций ничего делать не нужно.

Но это не является валидацией. Валидация должна заниматься вопросом "а какие данные тут должны быть?" (или же я путаю термины Закатив глазки ) Например, что такая дата реально существует, а не 31 ноября. А статус - один из допустимых.


-----
PostgreSQL DBA
 
 Top
esterio
Отправлено: 14 Августа, 2013 - 14:45:38
Post Id



Активный участник


Покинул форум
Сообщений всего: 5025
Дата рег-ции: Нояб. 2012  
Откуда: Украина, Львов


Помог: 127 раз(а)




filter_var и вся ее братва
 
 Top
nepster
Отправлено: 14 Августа, 2013 - 14:56:45
Post Id



Частый гость


Покинул форум
Сообщений всего: 195
Дата рег-ции: Июль 2012  


Помог: 0 раз(а)




Ну например я делаю так:
PHP:
скопировать код в буфер обмена
  1. public function news_edit($data)
  2. {
  3.   $user_id = (!isset($data[user_id]) OR !is_numeric($data[user_id])) ? 0 : (int)$data[user_id];
  4.   if(достать юзера из базы по $user_id)
  5.  {
  6.        return 'Пользователя нет в базе данных';
  7.  }
  8.  
  9.  
  10.   $news_id = (!isset($data[news_id]) OR !is_numeric($data[news_id])) ? 0 : (int)$data[news_id];
  11.   if(достать новость из базы)
  12.   {
  13.        return 'Новости нет в базе данных';
  14.   }
  15.  
  16.   if(достать юзера из базы по $user_id)
  17.   {
  18.        return 'Пользователя нет в базе данных';
  19.   }
  20.  
  21.   /* Тут вот интересно как защитить данные для записи
  22.   /* htmlspecialchars - это го же не достаточно*/
  23.      $data[news_name]
  24.      $data[news_short]
  25.      $data[news_full]
  26.   */
  27.  
  28.     if(!strtotime([news_date]))
  29.     {
  30.          return 'Некорректно указана дата';
  31.     }
  32.  
  33.     if(!is_numeric([news_status] ))
  34.     {
  35.          return 'Некорректно указан статус';
  36.     }
  37.  
  38.  
  39.      // записываем данные в бд
  40.  
  41. }
  42.  
 
 Top
teddy
Отправлено: 14 Августа, 2013 - 14:58:10
Post Id


Участник


Покинул форум
Сообщений всего: 1462
Дата рег-ции: Апр. 2013  


Помог: 91 раз(а)




кстати... напишу то как делаю валидацию/фильтрацию данных, может пнёт кто если что не очень хорошо.

Сначала задаю себе вопрос, "что я ожидаю получить, какие данные". Если например это целое число, то abs(intval($_POST['num']));

Если строка, то $db->real_escape_string($_POST['str']);
тоже самое и с $_GET параметрами

ну и для мыла filter_var

Если нужен конкретный шаблон входящих данных, использую preg_match с модификатором u

Ну а дальше уже по необходимости... типа if(strlen($var) < 3) {$error_str = "error";}

(Отредактировано автором: 14 Августа, 2013 - 15:02:35)

 
 Top
EuGen Администратор
Отправлено: 14 Августа, 2013 - 15:08:56
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




teddy пишет:
Если например это целое число, то abs(intval($_POST['num']));

Отрицательное число - тоже целое. Так что проверка соответствует утверждению "ожидается неотрицательное целое число".
teddy пишет:
Если строка, то $db->real_escape_string($_POST['str']);

Любая строка предполагается к обработке в запросах? Вряд ли, поэтому обрабатывать следует только непосредственно перед вставкой данных в строку запроса (выше написали лучший способ - подготовленные запросы, prepared statements)


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
teddy
Отправлено: 14 Августа, 2013 - 15:30:58
Post Id


Участник


Покинул форум
Сообщений всего: 1462
Дата рег-ции: Апр. 2013  


Помог: 91 раз(а)




EuGen пишет:
Отрицательное число - тоже целое. Так что проверка соответствует утверждению "ожидается неотрицательное целое число".

Да, согласен. Я просто не так выразился

EuGen пишет:
Любая строка предполагается к обработке в запросах?

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

PHP:
скопировать код в буфер обмена
  1. if($_SERVER["REQUEST_METHOD"] == "POST"){
  2.    
  3. $name = $db->real_escape_string(trim($_POST['name']));
  4. $num = abs(intval($_POST['num']));
  5.  
  6. //или например
  7. if(!intval($_POST['num'])){
  8.    
  9.     echo "Это не число!";
  10. }
  11.  
  12. }
  13.  

По разному делаю, в зависимости от того, что именно мне нужно в результате

(Отредактировано автором: 14 Августа, 2013 - 15:32:32)

 
 Top
esterio
Отправлено: 14 Августа, 2013 - 15:38:39
Post Id



Активный участник


Покинул форум
Сообщений всего: 5025
Дата рег-ции: Нояб. 2012  
Откуда: Украина, Львов


Помог: 127 раз(а)





nepster
Кажысь Вам неоднократно писали про скобкы
nepster пишет:
isset($data['user_id']
 
 Top
nepster
Отправлено: 14 Августа, 2013 - 17:06:59
Post Id



Частый гость


Покинул форум
Сообщений всего: 195
Дата рег-ции: Июль 2012  


Помог: 0 раз(а)




Цитата:
Кажысь Вам неоднократно писали про скобкы


это как просто пример, брал данные из распечатанного pint_r массива.


такой вопрос, тоесть мой вариант кучи if приемлемый ?
 
 Top
esterio
Отправлено: 14 Августа, 2013 - 17:14:34
Post Id



Активный участник


Покинул форум
Сообщений всего: 5025
Дата рег-ции: Нояб. 2012  
Откуда: Украина, Львов


Помог: 127 раз(а)




nepster
Я выше говорил что стараюсь пользоваться функционалом даной функции
http://php.net/manual/en/functio...-input-array.php

Тоесть у меня получаеться конфиг-массив. И уже в контроллере я просто указиваю етот массив, и на выходе получаю отфильтрованые данные(число включая диапазон, емейл, регуляркы для болле сложных и т.д.)
 
 Top
nepster
Отправлено: 14 Августа, 2013 - 17:16:16
Post Id



Частый гость


Покинул форум
Сообщений всего: 195
Дата рег-ции: Июль 2012  


Помог: 0 раз(а)




а как тогда отловить код ошибки ?
 
 Top
esterio
Отправлено: 14 Августа, 2013 - 17:26:16
Post Id



Активный участник


Покинул форум
Сообщений всего: 5025
Дата рег-ции: Нояб. 2012  
Откуда: Украина, Львов


Помог: 127 раз(а)




ну а почитать сложно
Цитата:
Значение массива будет FALSE, если фильтрация завершилась неудачей, или NULL, если переменная не определена
 
 Top
teddy
Отправлено: 15 Августа, 2013 - 14:53:11
Post Id


Участник


Покинул форум
Сообщений всего: 1462
Дата рег-ции: Апр. 2013  


Помог: 91 раз(а)




Мелкий пишет:
Препарированные запросы.

А можно подробнее про это? Я не пользуюсь подготовленными запросами, поэтому хотелось бы получить ответ на несколько вопросов. Есть например такой код

PHP:
скопировать код в буфер обмена
  1. $db = new mysqli("localhost", "root", "", "DBname");
  2. $stmt = $db->prepare("INSERT INTO `test` (`s_field`, `i_field`, `i_field`) VALUES(?, ?, ?)");
  3. $stmt->bind_param("sii", $sField, $iField0, $iField1);
  4. $sField = "text";
  5. $iField0 = 123;
  6. $iField1 = 456;
  7. $stmt->execute();
  8.  

Чем отличается такой запрос от обычного? Ведь все равно в запрос подставится то что будет в переменных.

Или тут сначала выполнится запрос, а потом уже подставятся значения? Не совсем понятно честно говоря... Если так, то логика не совсем ясна... Или может просто мы говорим: "Приготовься выполнить этот запрос и только этот, и если прилетит что то левое, то принимай это как обычные данные и не в коем случае не подставляй в запрос"

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

(Отредактировано автором: 15 Августа, 2013 - 14:56:04)

 
 Top
LIME
Отправлено: 15 Августа, 2013 - 15:02:56
Post Id


Активный участник


Покинул форум
Сообщений всего: 10732
Дата рег-ции: Нояб. 2010  


Помог: 322 раз(а)




мне вот тоже интересно почему подготовленные лучше?
ведь это как минимум 2 запроса вместо 1го(для одиночного запроса конечно)
какой такой случай инъекции возможен при использовании real_escape_string от которого спасет препарирование?
(Добавление)
teddy пишет:
Чем отличается такой запрос от обычного? Ведь все равно в запрос подставится то что будет в переменных.
тем что сначала в бд улетает запрос с плейсхолдерами
а затем летят отдельно данные и подставляются в запрос(в транслированный уже план запроса)
в этом случае данные рассматриваются как данные и не парсятся на предмет управляющих символов
(Добавление)
выгодно для циклов одинаковых запросов
(Добавление)
teddy пишет:
может пнёт кто если что не очень хорошо.
незнаю пнет ли это тебя но я вот как-то так сделал
PHP:
скопировать код в буфер обмена
  1. $post = ['id' => ['filter' => 257, 'flags' => FILTER_REQUIRE_SCALAR, 'options' => ['min_range' => 1]], 'col' => 513, 'val' => 513];
  2.         if (!in_array(FALSE, $post = filter_input_array(0, $post), 1)) {
  3.             $post['val'] = (is_int($post['val']))? : '"' . $post['val'] . '"';
  4.             $result = DB::query('UPDATE apartment SET `' . $post['col'] . '`=' . $post['val'] . ' WHERE id=' . $post['id']);
  5.             echo 'ok';
  6.         }

вместо циферь в пост можешь сначала проставить человеческие константы чтоб понятней было

(Отредактировано автором: 15 Августа, 2013 - 15:04:57)

 
 Top
teddy
Отправлено: 15 Августа, 2013 - 15:34:51
Post Id


Участник


Покинул форум
Сообщений всего: 1462
Дата рег-ции: Апр. 2013  


Помог: 91 раз(а)




LIME пишет:
тем что сначала в бд улетает запрос с плейсхолдерами
а затем летят отдельно данные и подставляются в запрос(в транслированный уже план запроса) в этом случае данные рассматриваются как данные и не парсятся на предмет управляющих символов

Спасибо

LIME пишет:
человеческие константы чтоб понятней было

Почитал в мануале, приблизительно разобрался, но как по мне мудрено как то... мне проще явно привести к типу одной строкой а потом уже писать различные условия для валидации если это требуется...
 
 Top
Страниц (2): [1] 2 »
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Вопросы новичков »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB