Javascript-форум (https://javascript.ru/forum/)
-   Серверные языки и технологии (https://javascript.ru/forum/server/)
-   -   Защита от SQL инекций (https://javascript.ru/forum/server/17763-zashhita-ot-sql-inekcijj.html)

0931454574 01.06.2011 17:38

Защита от SQL инекций
 
Добрый день.
Взгляните на код запроса пожалуйста. Достаточно ил таких проверок для устранения угрозы?
$strquery = "SELECT * FROM `topics` WHERE  `id`='%d'";
   $query =  sprintf($strquery,mysql_real_escape_string($_GET[id]));

firstchild 01.06.2011 23:13

Ё, чувак, как ты умудрился заработать такую карму(-751)?

0931454574 02.06.2011 00:30

firstchild,
Наверное такой результат потому, что я её не зарабатывал.Ё

x-yuri 02.06.2011 00:34

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

firstchild 02.06.2011 09:13

Ё, int?

$strquery = "SELECT * FROM `topics` WHERE  `id`='".(int)$_GET['id']."'";


пакажи мне чудо

x-yuri 02.06.2011 09:53

вы, конечно, можете сказать, что int'а в любом случае хватит. Но я бы сделал лучше, если тип столбца не помещается в int. Потому что это не сложно: либо is_numeric, либо filter_var('122312147483648', FILTER_SANITIZE_NUMBER_INT). Хотя возможно бд и к числу в виде строки адекватно отнесется, надо проверять

Serg_pnz 02.06.2011 09:55

Цитата:

Сообщение от x-yuri (Сообщение 107043)
В-третьих, используй фреймворки

Кстати да http://dklab.ru/lib/DbSimple/manual.html

0931454574 02.06.2011 11:04

Прекрасно.

0931454574 03.06.2011 10:03

Цитата:

Сообщение от x-yuri (Сообщение 107043)
во-первых, такое впечатление, что ты все свои знания вложил в эту строку, лишь бы как-нибудь чего-нибудь не просочилось. Это называется уличная магия. В данном случае достаточно убрать все нечисловые символы либо проверить их наличие. Во-вторых, не надо сравнивать со строковым значением, если столбец численный. В-третьих, используй фреймворки

Я так понимаю это комплимент_)_

dmitriymar 03.06.2011 11:03

Цитата:

Сообщение от 0931454574
во-первых, такое впечатление, что ты все свои знания вложил в эту строку,

не похоже это на комплимент...

x-yuri 03.06.2011 12:07

Цитата:

Сообщение от 0931454574
$query = sprintf($strquery,mysql_real_escape_string($_GET[id]));

хотя... можно и так :)

Kolyaj 03.06.2011 12:26

Лучше использовать PDO.

x-yuri 04.06.2011 04:44

а почему лучше?

Invis1ble 04.06.2011 07:28

sprintf() - изврат, зачем он здесь нужен? Конкатенация уже не катит?

И вообще, какие нах фреймворки? ) Для чисел - приведение к типу, для строк - mysql_real_escape_string() и будет вам счастье :)

ПС.
Цитата:

Лучше использовать PDO.
чем лучше? Замедлением работы скрипта?

Kolyaj 04.06.2011 07:55

Цитата:

Сообщение от x-yuri
а почему лучше?

Потому что там уже есть placeholder-ы.

Цитата:

Сообщение от Invis1ble
Замедлением работы скрипта?

С такими рассуждениями на PHP лучше вообще не писать.

x-yuri 04.06.2011 16:54

Цитата:

Сообщение от Invis1ble
sprintf() - изврат, зачем он здесь нужен? Конкатенация уже не катит?

аргументации только не хватает ;)

Цитата:

Сообщение от Invis1ble
И вообще, какие нах фреймворки? ) Для чисел - приведение к типу, для строк - mysql_real_escape_string() и будет вам счастье

тебе ссылки дать? Имеется в виду, что в фреймворках обычно есть какие-нибудь классы, которые упрощают работу с БД

Цитата:

Сообщение от Kolyaj
Потому что там уже есть placeholder-ы.

с помощью расширения mysql не намного сложнее все делается. Ну может быть понимать надо немного лучше, что ты делаешь. Кроме того, есть варианты поудобнее pdo

Invis1ble 04.06.2011 19:06

x-yuri,
Цитата:

Сообщение от x-yuri
аргументации только не хватает

Какой аргументации? помоему, все очевидно - ненужный вызов лишней функции.
Цитата:

Сообщение от x-yuri
Имеется в виду, что в фреймворках обычно есть какие-нибудь классы, которые упрощают работу с БД

Я так понял, что ТС не использует никаких фреймворков, что же ему делать? Ради "удобства" (что спорно) составления запросов добавить к своему коду в 100500 раз больше мертвого кода, 99.99% которого он никогда не использует?
Цитата:

Сообщение от x-yuri
Ну может быть понимать надо немного лучше, что ты делаешь

Вот это золотые слова.

Invis1ble 04.06.2011 19:11

Kolyaj,
Цитата:

С такими рассуждениями на PHP лучше вообще не писать.
Ну да, ну да. А раз мы пишем на php, значит можно написать "надстройку", а потом еще одну, ну и снизить производительность в итоге раз в 50. Зато "удобно" ! :)

Gozar 04.06.2011 22:47

Invis1ble,
кэширование, не?!

Invis1ble 04.06.2011 22:51

Причем здесь кеширование, я пишу о том, что можно обойтись штатными функциями вместо использования всяких модных фреймворков.
Ну тут конечно же каждому свое.

Gozar 04.06.2011 23:40

PDO внештатное?
кэширование не повышает производительность, снимая нагрузку?

Invis1ble 05.06.2011 04:12

Зачем лепить ООП там, где можно запросто обойтись без него?

x-yuri 06.06.2011 01:49

Цитата:

Сообщение от Invis1ble
Какой аргументации? помоему, все очевидно - ненужный вызов лишней функции.

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

Цитата:

Сообщение от Invis1ble
Я так понял, что ТС не использует никаких фреймворков, что же ему делать? Ради "удобства" (что спорно) составления запросов добавить к своему коду в 100500 раз больше мертвого кода, 99.99% которого он никогда не использует?

Что делать? По-моему, все очевидно - использовать ;) Если же фреймворк окажется мертвым кодом, то тут дело в: 1) ДНК, 2) фреймворке, 3) задаче. Последний пункт случается редко, так что остается одно из двух :)

Цитата:

Сообщение от Invis1ble
Ну да, ну да. А раз мы пишем на php, значит можно написать "надстройку", а потом еще одну, ну и снизить производительность в итоге раз в 50. Зато "удобно" !

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

Цитата:

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

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

Цитата:

Сообщение от Invis1ble
Зачем лепить ООП там, где можно запросто обойтись без него?

мы обсуждаем сферическую задачу в вакууме и вы всерьез рассчитываете попасть пальцем куда-либо, кроме как в небо, с обобщениями типа "1. Не используйте ООП. 2. Если все же надо, см. пункт 1"?

Invis1ble 06.06.2011 01:59

Я никого не призываю не использовать ООП, а лишь спрашиваю, чем использование ОО-подхода выгодней в данной конкретной ситуации.
Возможно я предвзято отношусь к нему и изменю свою точку зрения, если вы укажите объективные доводы в пользу него.

x-yuri 06.06.2011 10:53

ситуация не очень конкретна. Если речь идет о том, чем лучше pdo по сравнению с mysql: 1) с ним нельзя наткнуться на проблемы перобразования в int или, кстати, sprintf("%d...), 2) поддержка исключений, 3) однообразный интерфейс для работы с разными БД - не надо для каждой БД учить ее собственный интерфейс, 4) может еще чего, транзакции, например, там есть. Насколько они важны, в каждом конкретном случае решается отдельно. Минусы PDO - немножко более сложный интерфейс. А разницу в производительности, я уверен, вы не заметите. К тому же, у mysql по сути тоже ООП-интерфейс, просто сделан он без использования "настоящих" объектов.

Если же речь идет и о других библиотеках, то у DbSimple мне, кстати, описание (зачем еще одна библиотека) понравилось, но сам не пользовался. Кроме того, есть всякие билдеры, которые упрощают поддержку кода.

Invis1ble 06.06.2011 18:47

Спасибо конечно за развернутый ответ, но я имел ввиду именно "Защиту от SQL инекций". Т.е. как я понял, ТС пишет код в процедурном стиле, какой смысл ему создавать отдельный объект и защищаться от инъекций с средствами PDO? Конечно, если бы у него все было в ОО-стиле, то да, смысл может и был бы (чисто ради соблюдения общего стиля кода).

x-yuri 07.06.2011 07:00

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

А то что pdo построено на классах... какая разница? Mysql (расширение) тоже неявно построено на классах. И если язык позволяет использовать ООП, почему его не использовать? В моем понимании, ООП - это продолжение и синтаксический сахар для процедурного программирования. Т.е. не имея возможности использовать соответствующие синтаксические конструкции, ты все равно прийдешь к чему-то классоподобному. Другими словами, ООП способствует несколько другому, более удобному взгляду на программу. Наверное, как когда-то появление функций/процедур/подпрограмм поспособствовало. Хотя при этом оно может провоцировать возникновение ненужных слоев абстракции, или не всегда нужных. Но где ты видел палку об одном конце?

Invis1ble 07.06.2011 19:59

Цитата:

Сообщение от x-yuri
Т.е. это проще, потому что нужно меньше знать, и это проще, потому что часть служебной логики спрятана в pdo, следовательно легче просмотривать код.

Довольно спорное утверждение...
Ну да ладно, твою точку зрения понял, выводы сделал. Спасибо за разъяснения.

evgh 07.06.2011 22:42

вы не заметили что ответ на вопрос был дан ещё на первой странице и дальнейшее обсуждение автору тему не надо?

из мухи сделали слона :-E

x-yuri 08.06.2011 09:31

Цитата:

Сообщение от Invis1ble
Т.е. это проще, потому что нужно меньше знать, и это проще, потому что часть служебной логики спрятана в pdo, следовательно легче просмотривать код.

Цитата:

Сообщение от Invis1ble
Довольно спорное утверждение...

Повторюсь, на всякий случай, идея в том, что когда ты прячешь реализацию с целью показать намерения, становится меньше деталей. Следовательно это проще воспринимать. И не надо знать реализацию. А в чем спорность?

Цитата:

Сообщение от evgh
вы не заметили что ответ на вопрос был дан ещё на первой странице и дальнейшее обсуждение автору тему не надо?

с чего ты взял, что автору оно не надо? Да и даже если автору не надо, может еще кому-нибудь пригодится

Invis1ble 09.06.2011 02:11

Спорность в том "что нужно меньше знать, и это проще". Спорно потому, что это основывается на субъективном опыте. Кому-то проще, кому-то - наоборот.

0931454574 10.06.2011 11:29

x-yuri,
Invis1ble,
evgh,
Следил за Вашими прениями, но в действительности предложеного мной варианта должно быть достаточно) Кстати может есть рекомендации по хорошему ресурсу о безопасности?

x-yuri 10.06.2011 12:45

Цитата:

Сообщение от Invis1ble
Спорность в том "что нужно меньше знать, и это проще". Спорно потому, что это основывается на субъективном опыте. Кому-то проще, кому-то - наоборот.

Мой субъективный опыт подсказывает, что человек не может удерживать в голове слишком много информации. Поэтому ему свойственно прятать детали, обращаясь к ним по мере необходимости. Так появились функции, классы, объекты, предложения, абзацы, главы и модель OSI. А о каком субъективном опыте говоришь ты?

Цитата:

Сообщение от 0931454574
но в действительности предложеного мной варианта должно быть достаточно)

...пока значения находятся в пределах php-типа int

Invis1ble 10.06.2011 23:08

x-yuri,
Я говорю о том, что когда я вижу некий метод мне нужно либо уже знать его, либо лезть в кишки и узнавать, либо штудировать мануалы. Вы ведь не используете вслепую чьи-то наработки? И так как фреймворков и библиотек великое множество - то такое упрятывание деталей мне не то что не помагает, а наоборот мешает. Вместо того чтобы знать одну единственную функцию mysql_real_escape_string() и быть счастливым.

ПС. Вот приходит мне щас письмо на почту по подписке на одном ресурсе: [PHP Classes] Added a new class: Basic SQL Injection Protection
И спрашивается, нафига мне их класс? По сути, ради одной функции? :)
Вы скажете, нет, там с помощью него можно еще корованы грабить! Предположим, это очень полезная для меня функция и я всегда мечтал это сделать, но чтобы убедиться в том, что этот класс действительно умеет грабить корованы, а не какую-то бяку - мне все равно надо лезть в кишки и изучать :)

Хорошо, что в письме сразу идет описание:
Цитата:

Detailed description:This class can cleanup harmful text from request parameters.

It can check a given parameter value of $_GET, $_POST or $_REQUEST super-global variables and remove certain types of text values that are usually used to perform SQL injection attacks.
Какое счастье!!! Вместо того, чтобы экранировать кавычки и т.п. он это все удаляет! =)
В топку такой класс....

ППС.
Цитата:

Сообщение от x-yuri
человек не может удерживать в голове слишком много информации.

И где в итоге приходится больше помнить? Помнить одну функцию mysql_real_escape_string() или помня код (или по крайней мере названия) 100500 методов из различных чудо-библиотек, чтобы уверенно ориентироваться в чужом коде?

Довольно сумбурно выразился, но надеюсь моя основная мысль ясна.

dmitriymar 11.06.2011 00:19

Цитата:

Сообщение от Invis1ble
mysql_real_escape_string()

дак её одной мало для защиты от инъекций ....

Invis1ble 11.06.2011 00:30

ну приведение к типам еще, в корне ситуация все равно не меняется. Или я чего-то не знаю oO ?

x-yuri 12.06.2011 17:30

Цитата:

Сообщение от Invis1ble
Я говорю о том, что когда я вижу некий метод мне нужно либо уже знать его, либо лезть в кишки и узнавать, либо штудировать мануалы. Вы ведь не используете вслепую чьи-то наработки?

...либо понять как он работает по названию, сигнатуре, по аналогии с другим методом/фреймворком, из примера

Цитата:

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

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

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

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

Цитата:

Сообщение от Invis1ble
И где в итоге приходится больше помнить? Помнить одну функцию mysql_real_escape_string() или помня код (или по крайней мере названия) 100500 методов из различных чудо-библиотек, чтобы уверенно ориентироваться в чужом коде?

помнить как использовать проще, чем помнить как написать с нуля. Но я не говорил "помнить". Я говорил "удерживать в голове". Это означает, что нельзя написать что-то достаточно сложное, не используя функции, методы, классы. Создавая функцию, ты прячешь ее реализацию за ее именем. Если нужно постоянно смотреть в реализацию, возможно, ты неудачно определился с обязанностями функции, ее именем или еще чем-нибудь. В общем, не удалась функция. Ты ведь используешь функции?

хотя я так понял, дело именно в чужом коде. Может тебе приходилось слишком много заниматься поддержкой кода, написанного на каком-нибудь неоправданно сложном для задачи фреймворке?

а в случае с экранированием разница действительно незначительна. Но ведь если расширение

Gozar 13.06.2011 19:05

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

Выборка всех полей из таблицы в json с применением PDO:

$r = $pdo->query($sql)->fetchAll(PDO::FETCH_ASSOC);
echo json_encode($r);


и теперь без:

$arr = array();
$s = mysql_query($sql);
while($r = mysql_fetch_assoc($s)){
   $arr[] = '{ "id": "'.$r['id'].'", "title": "'.$r['title'].'", "content":"'.$r['content'].'"}';
} //здесь опущено экранирование переносов строк в content и title
echo '['.implode(",",$arr).']';


или вот так:

function mysql2json($mysql_result,$name) {
$result = array($name => array());
while ($row = mysql_fetch_assoc($mysql_result))
$result[$name][] = $row;
return json_encode($result);
}


или вот так:

function mysql2json($mysql_result,$name){
     $json="{\n\"$name\": [\n";
     $field_names = array();
     $fields = mysql_num_fields($mysql_result);
     for($x=0;$x<$fields;$x++){
          $field_name = mysql_fetch_field($mysql_result, $x);
          if($field_name){
               $field_names[$x]=$field_name->name;
          }
     }
     $rows = mysql_num_rows($mysql_result);
     for($x=0;$x<$rows;$x++){
          $row = mysql_fetch_array($mysql_result);
          $json.="{\n";
          for($y=0;$y<count($field_names);$y++) {
               $json.="\"$field_names[$y]\" :	\"$row[$y]\"";
               if($y==count($field_names)-1){
                    $json.="\n";
               }
               else{
                    $json.=",\n";
               }
          }
          if($x==$rows-1){
               $json.="\n}\n";
          }
          else{
               $json.="\n},\n";
          }
     }
     $json.="]\n};";
     return($json);
}

x-yuri 14.06.2011 19:03

вообще-то это не честный пример. Должно быть как-то так:
$r = mysql_query($sql);
$rows = array();
while ($row = mysql_fetch_assoc($r))
    $rows[] = $row;
echo json_encode($rows);

Gozar 14.06.2011 19:43

Цитата:

Сообщение от x-yuri (Сообщение 108697)
вообще-то это не честный пример. Должно быть как-то так:
$r = mysql_query($sql);
$rows = array();
while ($row = mysql_fetch_assoc($r))
    $rows[] = $row;
echo json_encode($rows);

согласен, но ведь и json_encode() не всегда было, ведь если не учить ничего нового, так и json_encode вроде не нужно.
а выровнять в одну строку? :) и я против опускания {}
echo json_encode($pdo->query($sql)->fetchAll(PDO::FETCH_ASSOC));


Часовой пояс GMT +3, время: 19:38.