Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Базы Данных > Сортировка БД и защита от SQL Injections


Автор: Aliance 25.5.2006, 01:35
Необходимо реализовать сортировку БД, через get данные. Так же нужно учитывать безопастность, тем самым обрубив возможность для SQL Injections. Вот мой код:
Код

$sort = mysql_real_escape_string($_GET['sort']);
$field = mysql_real_escape_string($_GET['field']);

if (!empty($sort) && !empty($field)) {
   $sql = "SELECT * FROM `таблица` ORDER BY `{$field}` {$sort}";
} else {
   $sql = "SELECT * FROM `таблица` ORDER BY `id` ASC";
}

$result = mysql_query($sql) or die('Ошибка подключения к БД');


URL domen.com/index.php?m=staff&sort=asc&field=nick - все работает.
URL domen.com/index.php?m=staff&sort=asc&field=nick' - выводит Ошибка подключения к БД. Но, если я не ошибаюсь, функция mysql_real_escape_string должна обрубать все недозволенные символы?! 

Автор: vasac 25.5.2006, 09:42
Aliance, mysql_real_escape_string() не обрубает символы - она их экранирует.
Т.е. здесь сортировка пойдет все равно nick'.
Будет тоже самое, что написать:
domen.com/index.php?m=staff&sort=XXX&field=kakayato_laga
т.е. ничего не будет.
 

Автор: Vaulter 25.5.2006, 10:44
Aliance, 
Код

$result = mysql_query($sql) or die('Ошибка подключения к БД: '.mysql_error());

и тайное станет явным 

Автор: Aliance 25.5.2006, 14:19
Цитата(Vaulter @  25.5.2006,  11:44 Найти цитируемый пост)
и тайное станет явным

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

так в целом мой код правильный, injection не пройдет? 

Автор: vasac 25.5.2006, 14:24
Цитата

вот этого как раз делать нельзя, иначе злоумышленник получит информацию

Так не на нормальном же сайте делать, а у себя при разработке.

А что делает mysql_real_escape_string() с различными символами можно узнать достаточно просто:
Код

print mysql_real_escape_string( $query );
 

Автор: -=Ustas=- 25.5.2006, 18:04
Цитата(Aliance @  25.5.2006,  14:19 Найти цитируемый пост)
так в целом мой код правильный, injection не пройдет?

Я бы не стал передавать открыто поля таблицы. 

Автор: Opik 25.5.2006, 21:20
Aliance, 
mysql_escape_string предназначена не для того.
У тебя неправильный подход. 
сделай лучше что то типо того:
Код

switch($_GET['orderby'])
{ 
    case 1: $oder = 'ORDER BY test ASC'; break;
    case 2...
}
$query = mysql_query("SELECT ...".$order);

и уже ссылки типа:
script.php?orderby=1 

Автор: Aliance 25.5.2006, 22:58
ИМХО это извращение smile Да и я читал много о том, что mysql_escape_string нужно использовать каждый раз, когда данные от пользователя вставляются в sql запрос. Но доверился твоему опыту и сделал как ты посоветовал.

Вот что получилось:
Код

$sort = intval($_GET['sort']);

switch($sort) { 
   case 1:
      $sql = 'SELECT * FROM `таблица` ORDER BY `поле` DESC';
      break;
   case 2:
      $sql = 'SELECT * FROM `таблица` ORDER BY `поле` ASC';
      break;
   case 3:
      $sql = 'SELECT * FROM `таблица` ORDER BY `поле` DESC';
      break;
   case 4:
      $sql = 'SELECT * FROM `таблица` ORDER BY `поле` ASC';
      break;
   case 5:
      $sql = 'SELECT * FROM `таблица` ORDER BY `поле` DESC';
      break;
   case 6:
      $sql = 'SELECT * FROM `таблица` ORDER BY `поле` ASC';
      break;
   default:
      $sql = 'SELECT * FROM `таблица` ORDER BY `поле` ASC';
      break;
}

$result = mysql_query($sql) or die('Ошибка подключения к БД');


Добавлено @ 23:00 
Цитата(-=Ustas=- @  25.5.2006,  19:04 Найти цитируемый пост)
Я бы не стал передавать открыто поля таблицы. 

а чего тут такого? поле id есть в 90% таблиц, либо его вариации smile да и если у меня есть имена пользователей, не тружно догадаться, что поле называется name, login или nick smile 

Автор: -=Ustas=- 26.5.2006, 08:58
Цитата(Aliance @  25.5.2006,  22:58 Найти цитируемый пост)
а чего тут такого? 

Да в общем-то ничего, это конечно дело твое, можешь и кода чуть-чуть выложить на страничку ;)

Цитата(Aliance @  25.5.2006,  22:58 Найти цитируемый пост)
Вот что получилось:

ИМХО, это по-моему слишком громаздко, я бы на твоем месте сделал бы следующим образом:
Код

<?php

$field = array();
$field[0] = 'id';
$field[1] = 'title';
$field[2] = 'sort';
$field[3] = 'content';
$field[4] = 'other';

$sort  = intval($_GET['sort']);
$order = (array_key_exists($sort, $filed)) ? $field[$sort] : $field[0];
$sql = 'SELECT * FROM `таблица` ORDER BY `'.$order.'` DESC';

?>
 

Автор: vasac 26.5.2006, 10:00
Цитата

а чего тут такого?

Конкретно в данном примере м.б. и ничего особенного. Только SQL-инъекции, с которыми вы так усиленно боретесь, происходят именно от того, что в запрос вставляются данные непосредственно полученные от пользователя.
 

Автор: -=Ustas=- 26.5.2006, 10:04
Цитата(vasac @  26.5.2006,  10:00 Найти цитируемый пост)
Конкретно в данном примере м.б. и ничего особенного. Только SQL-инъекции, с которыми вы так усиленно боретесь, происходят именно от того, что в запрос вставляются данные непосредственно полученные от пользователя.

Солидарен smile 

Автор: jsse 26.5.2006, 11:13
Правильный подход к решению у -=Ustas=- с помощью массива,
тогда не возникнет проблемы с неправильным названием поля,
но если требуется удалить ненужные символы можно поступить так:

Код

$sort = preg_replace("([^a-zA-Z0-9])", "", $_GET['sort']);
$field = preg_replace("([^a-zA-Z0-9])", "", $_GET['field']);


т.е. оставить только те символы, которые будут присутствовать в названии поля таблицы. 

Автор: Aliance 26.5.2006, 14:26
jsse, не вижу в этом необходимости - данные, передаваемые в адресе строки - числа. Функции intval() должно хватить smile

vasac, я решал задачу не в целом, а под данный конкретный пример smile


-=Ustas=-, мне нужно делать и desc и asc сортировку. Тогда уж нужно твой вариант переписать так, чтобы была матрица?! 

Автор: -=Ustas=- 26.5.2006, 14:51
Хм... зачем еще матрица, по аналогии с полями:
Код

<?php

$field = array();
$field[0] = 'id';
$field[1] = 'title';
$field[2] = 'sort';
$field[3] = 'content';
$field[4] = 'other';

$sort  = intval($_GET['sort']);
$type  = (intval($_GET['order'])) ? 'DESC' : 'ASC';
// т.е. _GET['order'] если 1, то DESC, если 0 то ASC
$order = (array_key_exists($sort, $filed)) ? $field[$sort] : $field[0];
$sql = 'SELECT * FROM `таблица` ORDER BY `'.$order.'` '.$type;

?>
 

Автор: Aliance 26.5.2006, 20:38
Цитата(-=Ustas=- @  26.5.2006,  15:51 Найти цитируемый пост)
$type  = (intval($_GET['order'])) ? 'DESC' : 'ASC';

а если $_GET['order'] будет установлено в ghdghdt какую-нибудь? 

Автор: -=Ustas=- 26.5.2006, 20:49
Цитата(Aliance @  26.5.2006,  20:38 Найти цитируемый пост)
а если $_GET['order'] будет установлено в ghdghdt какую-нибудь?  

intval() преобразует строку в нолик и по этому в результате окажется ASC ;) 

Автор: Aliance 27.5.2006, 00:07
Ясно, тогда просто отлично. Спасибо за неоднократную помощь ;) 

Автор: -=Ustas=- 27.5.2006, 08:25
Цитата(Aliance @  27.5.2006,  00:07 Найти цитируемый пост)
Ясно, тогда просто отлично. 

Это я к примеру привел, незабудь еще проверку на существование сделать, чтобы в случае их отсутствия был дефолт и не вылизили NOTICE:
Код

$sort = (isset($_GET['sort'])) ? intval($_GET['sort']) : 0;
$type = (isset($_GET['order'])) ? intval($_GET['order']) : 0;
$type = ($type) ? 'DESC' : 'ASC';
 

Автор: Aliance 27.5.2006, 13:05
Вот такой код не работает:
Код

$sort = (isset($_GET['sort'])) ? intval($_GET['sort']) : 0;
$type = (isset($_GET['order'])) ? intval($_GET['order']) : 0;
$type = ($type) ? 'DESC' : 'ASC';

$field = array();
$field[0] = 'id';
$field[1] = 'line';
$field[2] = 'nick';
$field[3] = 'city';

$order = (array_key_exists($sort, $field)) ? $field[$sort] : $field[0];
$sql = 'SELECT * FROM `таблица` ORDER BY `'.$order.'` '.$type;


И еще, нужно чтобыработало при всех данный Url:
www.domen.com/index.php?m=staff
www.domen.com/index.php?m=staff&sort=0&order=0
www.domen.com/index.php?m=staff&sort=0
www.domen.com/index.php?m=staff&order=0 

Автор: -=Ustas=- 27.5.2006, 13:18
Ну как это не работает, щас проверял: при sort=0&order=0 получается:
Код

SELECT * FROM `таблица` ORDER BY `id` ASC

при sort=2&order=1
Код

SELECT * FROM `таблица` ORDER BY `nick` DESC

Что собсна и требовалось доказать. 
Вообще без параметров, идет по дефолту:
Код

SELECT * FROM `таблица` ORDER BY `id` ASC
 

Автор: Aliance 27.5.2006, 13:36
Ошибка была в 12ой строчке smile Забыл заменить название таблицы  smile  

Автор: -=Ustas=- 27.5.2006, 13:42
 smile  Бывает... 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)