Защита от SQL Injection

sobachnik

Новичок
Я прочитал всё по той ссылке, но у меня всё-таки остались кое-какие вопросы. Что в той статье рекомендуют (вкратце)? Для числовых переменных использовать intval, для строковых - если get_magic_quotes() == true , то сперва stripslashes(), потом mysql_real_escape_string(). И, по сути всё. Если полученная от пользователя переменная будет использоваться в запросе как параметр для LIKE, то опять же сперва stripslashes() (если get_magic_quotes() == true) и далее str_replace('\\','\\\\',$var) , потом всё тот же mysql_real_escape_string(), потом addCslashes($var, '_%'). Вот интересно мнение опытных профессиональных программистов - этого достаточно, чтобы быть уверенным, что всё в порядке? Больше ничего не надо?
 

Фанат

oncle terrible
Команда форума
addCslashes($var, '_%') для лайк не обязательно, а иногда наоборот - вредно. Впрочем ,и в том и в другом случае это к безопасности не имеет отношения.

-~{}~ 07.11.08 16:30:

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

sobachnik

Новичок
А если пользователь введёт запрос на поиск, в котором будет знак % или _ ??? Ну и опять-таки мой вопрос про безопасность с предыдущей странички остаётся в силе...
 

Фанат

oncle terrible
Команда форума
Я прочитал всё по той ссылке,
Отлично. проверим, как ты это прочитал. Что там написано по вопросу, достаточно ли этого, чтобы быть уверенным, что всё в порядке?
 

sobachnik

Новичок
Автор оригинала: *****
Отлично. проверим, как ты это прочитал. Что там написано по вопросу, достаточно ли этого, чтобы быть уверенным, что всё в порядке?
ГЫ... :)
Если б я там увидел, что этого достаточно (или недостаточно) я б тут по-другому вопрос задал (или не задал бы вообще)...
Просто я вот решил посмотреть, что в phpbb делается с пользовательскими данными перед отправкой sql-запроса. Сперва немного помучался с поиском, потом нашёл, офигел и решил спросить. В phpbb (применительно к $username) это выглядело так:
PHP:
<?php
... ... ...
$username = isset($HTTP_POST_VARS['username']) ?
phpbb_clean_username($HTTP_POST_VARS['username']) : '';
$sql = "SELECT user_id, username, user_password, user_active, user_level, user_login_tries,
user_last_login_try FROM " . USERS_TABLE . " WHERE username = '"
. str_replace("\\'", "''", $username) . "'";
... ... ...
function phpbb_clean_username($username)
{
  $username = substr(htmlspecialchars(str_replace("\'", "'", trim($username))), 0, 25);
  $username = phpbb_rtrim($username, "\\");
  $username = str_replace("'", "\'", $username);
  return $username;
}
function phpbb_rtrim($str, $charlist = false)
{
  if ($charlist === false)
  {
    return rtrim($str);
  }
  $php_version = explode('.', PHP_VERSION);
  // php version < 4.1.0
  if ((int) $php_version[0] < 4 || ((int) $php_version[0] == 4 && (int) $php_version[1] < 1))
  {
    while ($str{strlen($str)-1} == $charlist)
    {
      $str = substr($str, 0, strlen($str)-1);
    }
  }
  else
  {
    $str = rtrim($str, $charlist);
  }
  return $str;
}
?>
 

Фанат

oncle terrible
Команда форума
Если б я там увидел, что этого достаточно (или недостаточно)
читай снова. пока не увидишь.

офигел и решил спросить.
непонятно. если у тебя вопрос по коду phpBB, то его следует задавать наверное, на форуме поддержки этого программного продукта - почему там сделали так или иначе.
Я понимаю, у тебя вопрос по тексту фака - там написано, что фак является частью пхпклуба, и поэтому вполне резонно задавать вопрос здесь. Но к пхпББ здесь никто никакого отношения не имеет.

И вообще, какое отношение эта криворукая поделка имеет к основному вопросу?

-~{}~ 07.11.08 16:52:

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

Чтобы вставить код Html-entity, надо заменить & на &amp;amp;
 

sobachnik

Новичок
*****
Правильно понимаете, вопрос у меня действительно по тексту фака. То, что к phpbb тут никто отношения не имеет я тоже догадываюсь. А отношение этой "криворукой поделки" к основному вопросу лишь в том, что у них вот такая писанина, у Вас в факе вроде (насколько я понял) всё гораздо проще, несколько функций всего. Меня это смутило. Зачем им такая писанина нужна? Если можно обойтись
если get_magic_quotes_gpc() == true , то сперва stripslashes(), потом mysql_real_escape_string()
ну и добавить trim() ещё... :confused:

-~{}~ 07.11.08 17:17:

Вот например такое получилось исходя из того, что я уяснил из статьи.
PHP:
<?php
... ... ...
if (isset($_GET['word']) {
  if (get_magic_quotes_gpc()) {
    stripslashes($_GET['word']);
  }
  $_GET['word'] = str_replace('\\', '\\\\', $_GET['word']);
  $_GET['word'] = mysql_real_escape_string($_GET['word']);
  $search_word = addCslashes($_GET['word'], '_%');
}
$sql = "SELECT post, post_date, poster_name FROM posts WHERE post LIKE '%" . $search_word . "%'";
... ... ...
?>
Вы можете не направить сразу не перепрочтение статьи, а сказать, правильно это или нет и если не правильно, то в чём. Обеспечит ли вышенаписанное защиту от sql-инъекции и правильный поиск в базе?
 

Фанат

oncle terrible
Команда форума
Слушай, какая тебе разница? Хочешь - бери из пхпбб. хочешь - отсюда. Не нравится ни тот ни другой - найди третий какой-нибудь, про который тебе скажут, что будет работать.
Тебе надо, чтобы за этот код тебе кто-нибудь поручился? Давай я поручусь: все тебе обеспечит этот код, и от инъекций защиту, и улучшение кармы, и мир во всем мире. Теперь ты спокоен, вопросов больше нет?

-~{}~ 07.11.08 17:43:

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

-~{}~ 07.11.08 17:57:

эфемерность всего этого форумного общения меня бесит.
нет никакой разницы, с кем ты общаешься - со специалистом или с двоечником. нету критериев оценки. говорить можно все что угодно. сказали, что от инъекций можно избавиться, убивая слово UNION в запросе - сделал. Сказали, что кавычку надо заменять - сделал. сказали, что если мяса есть не будешь - тебя ждет вечная жизнь - сделал. разницы - ни-ка-кой.
 

sobachnik

Новичок
*****
Ну ладно, Вы уж извините... Если от общения со мной сложилось такое неприятное впечатление. Наверно я здесь задаю неправильные вопросы...
Я Вас понимаю. И мне тоже хочется понять, а не просто скопировать код. :) Помимо всего прочего я интересуюсь и программированием. Причём давно, ещё с начальных классов. Тогда я изучал методом научного тыка BASIC на ZX Spectrum-е... Прошло много времени. Сейчас (уже больше года) интересуюсь php, но такой темы, как sql инъекции не в одной из прочтённых и недочитаных книг не было. И мне хочется, конечно же хочется, разобраться и понять. Мне это интересно и хочется научиться делать хорошо и правильно.
Я распечатал для себя ту статью и ещё раз перечитал (правда выборочно...). Вот в разделе про SQL-инъекции где формируется оператор WHERE, используется всего одна строчка:
PHP:
if (!empty($_GET['price'])) $where .= "price = '" . mysql_real_escape_string($_GET['price']) . "'";
То есть функция mysql_real_escape_string() сделает всё что нужно для борьбы с этими самыми sql-инъекциями... Во всяком случае я это понял так из статьи, потому что это единственное, что делается в разделе sql-инъекции, когда в базу передаётся введённое пользователем значение.
Я не знаю всего, у меня нет никакого опыта в попытках кого-то взломать, соответственно я и не знаю откуда ждать нападения на мой будующий сайт. По этому для большей уверенности я спрашиваю у человека с определённым опытом в программировании, который наверняка знает точный ответ: а достаточно ли этого, чтобы быть уверенным, что всё в порядке (ну, относительно sql-инъекций)?
 

Фанат

oncle terrible
Команда форума
"нужное" делает здесь не одна функция mysql_real_escape_string(), а вся эта строчка.

В запросе надо разделять две вещи - данные и управляющие элементы.
Для данных достаточно обкавычивания+прослешивания.
То есть, без заключения в кавычки, одна mysql_real_escape_string() ничем нам не поможет. mysql_real_escape_string() ПЛЮС кавычки.
Ведь наша задача состоит в том, чтобы кусок данных в запросе не был понят базой, как управляющий. Все, что находится между кавычками, базой трактуется, как даные, если внутри этого куска экранированы слешем спецсимволы (не только кавычки).
Если мы это сделали - ну нету физической возможности впихнуть что-то вредное. Оно не сможет стать частью запроса. Это, надеюсь, понятно.
И для твоего поиска этого достаточно.

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

-~{}~ 07.11.08 19:13:

а get_magic_quotes_gpc() вообще к запросам не имеет отношения, эта проверка делается до выполнения каких-либо запросов и даже в тех скриптах, которые с БД вообще не работают.
Это совершенно разные, никак не связанные между собой вещи.
 

sobachnik

Новичок
Во!!! Ну наконец-то я услышал то что хотел! :)
Автор оригинала: *****
Все, что находится между кавычками, базой трактуется, как даные, если внутри этого куска экранированы слешем спецсимволы (не только кавычки).
Если мы это сделали - ну нету физической возможности впихнуть что-то вредное
Весь наш диалог был из-за кавычек. И я конечно и раньше делал так, что подставляемые данные находятся внутри кавычек, а сами данные экранируются (правда я экранировал с помощью addslashes()). Просто мне и в голову не приходило сказать, что я понимаю, что нужно выделить кавычками в запросе SQL переменную, а в самой переменной все кавычки (и другие спец.символы) экранировать. И в то же время я опасался, что может быть есть какой-то способ, который мне не известен, записать в эту пользовательскую переменную что-то такое, что не экранируется и отправляется в базу, и в базе может привести к неправильной работе. Потому здесь и спрашиваю, достаточно ли mysql_real_escape_string, гарантирует ли одна эта функция безопасность (если то, что ей обработано окружено кавычками с обоих сторон)? Например меня пугали таким понятием, как null-byte (и я толком не понял, что это), который вроде означает конец строки и функции php перестают обрабатывать строку после этого null-byte. И после этого null-byte можно вставить закрывающуюся кавычку (которая уже окажется не заэкранированной), потом точку с запятой, а потом любой запрос к базе сделать, например сменить пароль кому-то... Может существует ещё что-то помимо null-byte, что может сделать что-то неприятное, вот я и спросил! :) А так-то что надо в запросе SQL вручную вписать кавычку, потом экранированную пользовательскую переменную, потом снова кавычку - это понятно.
И то, что управляющие операторы не нужно брать из пришедшей формы - это я тоже уже давно уяснил, не раз читал что-то типа "не доверяйте пользовательским данным". И это мне вполне понятно. И мне бы и в голову не пришло имя поля (или таблицы) взять из запроса.
 

Фанат

oncle terrible
Команда форума
почитать в документации, какие символы экранирует mysql_real_escape_string, совсем несложно.
 
Сверху