За последние 24 часа нас посетили 17553 программиста и 1613 роботов. Сейчас ищут 1862 программиста ...

Проверка подставляемых переменных при SQL запросе

Тема в разделе "PHP и базы данных", создана пользователем Dendead, 29 июл 2014.

  1. Dendead

    Dendead Новичок

    С нами с:
    29 июл 2014
    Сообщения:
    9
    Симпатии:
    0
    Доброго времени суток. У меня есть запрос в БД вида:

    Код (Text):
    1. public function updateDataString($table, $name, $param) {
    2.             $mysqli = $this->bd_connect->mysqli;
    3.            
    4.             $stmt = $mysqli->stmt_init( );
    5.             if (($stmt->prepare("UPDATE {$table} SET {$name}=? WHERE id = ?") === FALSE)
    6.                 or ($stmt->bind_param('si', $param, $this->id) === FALSE)
    7.                 or ($stmt->execute( ) === FALSE)
    8.                 or ($stmt->close( ) === FALSE)
    9.             ) {
    10.                 die('Select Error (' . $stmt->errno . ') ' . $stmt->error);
    11.             }
    12.         }
    Я знаю, что нужно проверять все вводимые пользователем данные при добавлении их в БД. В данном случае я самостоятельно, в коде, через аргументы функции updateDataString( ) задаю названия таблиц и колонок для UPDATE. Подскажите пожалуйста, есть ли смысл проводить какие-либо манипуляции и с этими данными?
     
  2. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.115
    Симпатии:
    1.244
    Адрес:
    там-сям
    если фактические параметры зависят от пользовательского ввода, то нужно что-то с этим делать )))

    К.О.
     
  3. Dendead

    Dendead Новичок

    С нами с:
    29 июл 2014
    Сообщения:
    9
    Симпатии:
    0
    То есть добавлять названия таблиц и полей таким образом допустимо?
     
  4. VLK

    VLK Старожил

    С нами с:
    15 дек 2013
    Сообщения:
    3.010
    Симпатии:
    58
    да, есть, их как минимум надо экранировать - real_escape_string, любы данные приходящие со стороны надо как минимум экранировать.

    И еще на мой взгляд (далеко не профессиональный) код какой то мутный, он должен быть попроще.
     
  5. Dendead

    Dendead Новичок

    С нами с:
    29 июл 2014
    Сообщения:
    9
    Симпатии:
    0
    А как проще можно записать такого вида запрос?
    Я проверяю каждую операцию на выполнение.

    Эти данные я самостоятельно указываю в коде. То есть пользователи к ним не причастны. Изначально вопрос стоял в этом.
     
  6. VLK

    VLK Старожил

    С нами с:
    15 дек 2013
    Сообщения:
    3.010
    Симпатии:
    58
    Код (PHP):
    1. function q($array) { 
    2.     // в функцию я бы передавал в виде ассоциативного массива
    3.     // $array = array( 'table' => '', 'name' => '' );
    4.     
    5.     $db = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME); 
    6.     // тут соответственно не каждый раз подключать, а $db вынести и использовать как глобальное значение
    7.     // или как статическую переменную класса
    8.  
    9.     if ($db->connect_errno) {
    10.         die('<h2>Error! Not connect with data base!</h2>');
    11.     }
    12.     
    13.     foreach ( $array as $key => $value ) {
    14.         $array[$key] = $db->real_escape_string($array[$key]); // экранирование
    15.     }
    16.     
    17.     $result = $db->query("UPDATE `{$array['table']}` SET {$array['name']}=? WHERE id = ?");
    18.     
    19.     // а потом проверять что получили
    20.     
    21. } 
    примерно как то так, хотя не видя всего и учитывая ночь код мягко сказать не полный и не конечный.

    данные приходящие со стороны всегда экранируй, данные приходящие от себя можно не экранировать, но желательно все же экранировать - для порядка.
     
  7. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.115
    Симпатии:
    1.244
    Адрес:
    там-сям
    Армянское радио отвечает:

    Какой внезапный вывод ) Ты понимаешь что такое фактические параметры?
    Твоя реализация перекладывает ответственность за безопасность на ту часть кода, в которой будет происходить вызов функции. А по-хорошему та часть кода должна воспринимать твою функцию как "черный ящик" и ничего про mysql знать не обязана! Иначе вообще не стоило писать свою обертку над query, я так думаю.

    Добавлено спустя 100500 минут:
    Прикол в том, что эти имена проблематично заэкранировать через mysqli_real_escape_string. Экранирование помогает в местах, окруженных кавычками. Доказывать лень, можете сами поэкспериментировать и убедиться. Как плейсхолдеры имена таблиц/полей тоже никак не оформить!

    Достойный выход — гарантировать, что они придут из безопасного места. Что-то вроде "белых списков".
     
  8. Dendead

    Dendead Новичок

    С нами с:
    29 июл 2014
    Сообщения:
    9
    Симпатии:
    0
    http://habrahabr.ru/post/148701/
    Нашёл на хабре статью.

    Я только учусь. Не пинайте сильно.

    То есть, например, создаю массив с допустимыми именами полей и таблиц и при вызове функции, проверяю их в updateDataString перед запросом. Всё верно?
     
  9. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.115
    Симпатии:
    1.244
    Адрес:
    там-сям
    статья хорошая. успехов!
     
  10. VLK

    VLK Старожил

    С нами с:
    15 дек 2013
    Сообщения:
    3.010
    Симпатии:
    58
    названия таблиц и названия полей экранировать не надо, а вот значения полей надо. Перед запросом.