SQL Injection - вопрос безопасности

igortik

Новичок
SQL Injection - вопрос безопасности

Во-первых, начну с того, что досконально ознакомился с экранированием и сопутствующими статьями.

Все мои запросы в базу выглядят примерно так: SELECT * FROM `table` WHERE page='$page';

Чтобы защитить $page я использовал следующий механизм:
PHP:
$pages = array("значение 1","значение 2"); // и т.д.
$key=array_search($_GET['page'],$pages);
$result=$pages[$key];
if($page != $result) {die($message);}
Вопрос по этой части:

Теоретически это должно полностью исключить возможность задать неестественное значение переменной $page.

- Достаточно ли для полной защиты от инъекции чере запрос SELECT * FROM `table` WHERE page='$page'; использовать:
PHP:
if (!$_GET['page']) {$page="main";} else {$page.= mysql_real_escape_string($_GET['page']);}
или все же надо использовать условие с массивом, описанное выше?

Значения ID , которые посылаются скрипту из браузера обрабатываются так:

PHP:
$id = $_GET['id'];
$id = (int)$id;
- Насколько эффективен такой метод?

Что касается попытки поменять значение переменной ID еще поставил такую защиту:

PHP:
if (is_numeric($_GET['id']) or $_GET['id'] == "") {} else {die($message);}
Что касается форм, которые отправляют в базу информацию посетителя:

Перед тем, как выполнить запрос: INSERT INTO `table` (text) VALUES ('$text'); я обрабатываю переменную $text таким образом:

PHP:
if (strlen($text) <= 1000)
{
$text = mysql_real_escape_string($text);
mysql_query("INSERT INTO `table` (text) VALUES ('$text')");
}
Есть ли у Вас какие-то замечания и практические советы по защите БД?

P.S. Знаю, что тема ни раз поднималась, но хотелось бы еще раз освежить в памяти все моменты.
 

zerkms

TDD infected
Команда форума
$page.= mysql_real_escape_string($_GET['page'])
ты понимаешь, чем = отличается от .= ??
Что касается попытки поменять значение переменной ID еще поставил такую защиту:


if (is_numeric($_GET['id']) or $_GET['id'] == "") {} else {die($message);}
числа проще принудительно кастовать к нужному типу и не проверять ничего
Чтобы защитить $page я использовал следующий механизм:

$pages = array("значение 1","значение 2"); // и т.д.
$key=array_search($_GET['page'],$pages);
$result=$pages[$key];
if($page != $result) {die($message);}
абсурд
просто экранируй и всё

ps: и это, привыкай программировать с error_reporting(E_ALL)
 

Фанат

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

Ты знаешь такую поговорку - "у семи нянек дитя без глазу"?
Не понимая ПРОСТЫХ правил составления запросов, ты мечешься с десятком каких-то самопальных проверок.
почему ты не делаешь, как написано в статье по ссылке?
 

voituk

прозревший
$pages = array("значение 1","значение 2"); // и т.д.
$key=array_search($_GET['page'],$pages);
$result=$pages[$key];
if($page != $result) {die($message);}
/me в ужасе!
Не делай так! Я так не делаю и жив-здоров - и ты так не делай.
 

igortik

Новичок
Спасибо всем, стоит переосмыслить прочитанное.

P.S. но ограничение на размер входящих текстовых данных ставить нужно? (не касается SQLi)
 

Фанат

oncle terrible
Команда форума
voituk
ну, ужасаться не стоит. он просто перепутал данные с элементами запроса. которые именно так и защищаются - массивом. имена полей, например.
 

asterisk

Новичок
размер входящих текстовых данных ставить нужно?
только в том случае если это требует логика приложения.

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

igortik

Новичок
Автор оригинала: asterisk
только в том случае если это требует логика приложения.

Например при приеме данных из формы строки ФИО проверять длину строки выглядит избыточной функцией, а вот например при получении строки номера кредитной карты можно и уведомить пользователя что введено не верное количество символов. Сам бывает ошибаюсь при вводе номера кредитки вставляя спейсы между блоками номеров, в этом случае получение предупреждения о неверном количестве символов спасает от блокировки креды после 3 неверных попыток ввода номера.
я полагаю, что от этого можно защититься так:

PHP:
$creditcard = str_replace("&nbsp;","",$creditcard);
либо, в полю формы задать size="16" :)

P.S. А вот я имел ввиду, если мне через форму будут слать текст размером в n-мегабайт и постоянно делать рефреш страницы.. я яэтот случай имею ввиду :rolleyes:
 

baev

‹°°¬•
Команда форума
я полагаю, что от этого можно защититься так:


$creditcard = str_replace("&amp;nbsp;","",$creditcard);
— Вы полагаете в правильном направлении, только...
...откуда там
Код:
&amp;nbsp;
возьмётся?
 

Vladson

Сильнобухер
Re: SQL Injection - вопрос безопасности

Автор оригинала: igortik
PHP:
$pages = array("значение 1","значение 2"); // и т.д.
$key=array_search($_GET['page'],$pages);
$result=$pages[$key];
if($page != $result) {die($message);}
Яркий пример того как хорошую идею можно "опошлить" с помощью кривой реализации.
 

WoZ

Новичок
Автор оригинала: igortik
я полагаю, что от этого можно защититься так:

PHP:
$creditcard = str_replace("&nbsp;","",$creditcard);
либо, в полю формы задать size="16" :)
вот доверять только size'у поля фомы никогда нельзя. это запросто обойти. надо на серверной стороне контролировать.

так проверки карт не делаются. а вдруг он буквы введет? либо intval, но более правильно будет регуляркой проверять все критические входные данные
 

Фанат

oncle terrible
Команда форума
WoZ
У тебя в голове много правильных слов, но вот применение найти им правильное у тебя получается с трудом.
если ограничение на длину поля с номером карточки будет обойдено юзером - это проблемы юзера.

У тебя какой вопрос был? Безопасность базы данных или конкретные проверки в конкретном приложении?
Если первый, то и занимайся первым. А частными вопросами - сколько цифр можно вводить в поле с номером телефона - тему не засоряй.
 

igortik

Новичок
Автор оригинала: baev

...откуда там
Код:
&amp;nbsp;
возьмётся?
хотел сказать - пробел, не то ввел :(

-~{}~ 16.10.07 21:12:

Автор оригинала: Vladson
Яркий пример того как хорошую идею можно "опошлить" с помощью кривой реализации.
осмелюсь не согласиться, спорить тоже не буду, т.к. я дааалеко не профи, но пока что эту проверку не убрал, она даже помогла мне реализовать редирект, если вдруг пользователь неверно ввел строку в url.. - идет редирект на главную и в целях безопасности не помешает, мой сайт не большой и нагрузки особой этот скрипт не создает.

п.с. ушел читать литературу

-~{}~ 16.10.07 21:19:

Позвольте подвести итоги.

1) Если я все верно понял, то все входящие извне данные необходимо экранировать,
пользуясь
PHP:
mysql_real_escape_string
?
2) Все нечисловые переменные, которые скрипт получает через $_GET также необходимо экранировать?
3) Всем числовым переменным необходимо до ввода запроса определять тип, т.е., к примеру, $id = (int)$id;
4) Правильно составлять SQL запросы, пример:

PHP:
$string = mysql_real_escape_string($_GET['string']);
INSERT INTO `table` WHERE `type`='$string';
...
Есть ли еще практические замечания по этому вопросу?
Очень хочется узнать что-то новое, может ссылки на статьи...
Буду благодарен.
 

Wicked

Новичок
1) Если я все верно понял, то все входящие извне данные необходимо экранировать,
пользуясь
mysql_real_escape_string
?
2) Все нечисловые переменные, которые скрипт получает через $_GET также необходимо экранировать?
Неправильно. Экранировать нужно все нечисловые данные, которые попадают в запрос. Неважно, какого они происхождения: пришедшие снаружи, вычисленные, или взятые из базы.
 

igortik

Новичок
Автор оригинала: Wicked
Неправильно. Экранировать нужно все нечисловые данные, которые попадают в запрос. Неважно, какого они происхождения: пришедшие снаружи, вычисленные, или взятые из базы.
Спасибо.

mysql_real_escape_string подойдет лучше всего в этом?
stripslashes ушли на второй план?

-~{}~ 16.10.07 21:31:

Спасибо, прочел. О чем написал в первом сообщении :)
 

Фанат

oncle terrible
Команда форума
igortik
А можно я тебе вопросы позадаю?
Если я все верно понял, то все входящие извне данные необходимо экранировать,
почему? желательно развернутый ответ.
Все нечисловые переменные, которые скрипт получает через $_GET также необходимо экранировать
чем отличаются "все входящие" от "переменных, которые скрипт получает через $_GET"?
mysql_real_escape_string подойдет лучше всего в этом?
stripslashes ушли на второй план?
не будем обращать вниание на то, что ты перепулат с addslashes. Но скажи - ты уверен, что в том тексте, который ты уже прочитал, нет ответа на этот вопрос? В каком месте там написано неясно?
 
Сверху