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


Автор: anurbol 10.5.2010, 15:12
К сожалению не нашел в нете подробно об этом.
Знаю что \  и '  а недавно заинтересовало, является ли } (фигурная скобка) опасным символом? Просто в моем движке он никак не экранируется/кодируется, а ведь есть запросы типа 
Код

SELECT * FROM table WHERE foo={$bar}

И вообще какие еще символы нужно преобразовывать?

Автор: SickFxck 10.5.2010, 15:27
Опасных символов нет вообще. Ты правда считаешь, что это вопрос "для профи"?

Автор: bars80080 10.5.2010, 15:42
любой символ - это набор байт, которые не имеют между собой никакой разницы. было бы по меньшей мере странно, если бы определённую комбинацию байт можно было бы хранить в БД, а другую нет. ущербная база получается

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

чтобы этого не происходило было введено простое правило экранирования служебных символов. (служебных, а не опасных!).
а чтобы лень программиста вообще ничем не тревожить были придуманы методы экранировки то что называется in one click, в данном случае в одну функцию. достаточно пропустить данные через mysql_real_escape_string($data); и всё заэкранируется где надо и как надо

Автор: anurbol 10.5.2010, 15:57
про mysql_real_escape_string знаю давно, но мой использует не его, а просто во всех входящих $POST данных, ' и & перерабатывает в html сущности. Просто как бы хотел поинтересоваться у профи,  является ли { опасным (служебным если хотите) символом, mysql_real_escape_string его не обрабатывает.

Добавлено через 1 минуту и 2 секунды
просто где то давно об этом прочитал мимолетом, не обратил внимание, не знаю может то было просто мнение какого нибудь дилетанта на форуме. 

Автор: LeoK 10.5.2010, 16:28
Цитата(anurbol @  10.5.2010,  15:12 Найти цитируемый пост)
 SELECT * FROM table WHERE foo='{$bar}'

В приведенном вами примере при наличии данной строки в двойных кавычках php подставит переменную и соответственно убьёт символы фигурных скобок... непонятно в чем сложности? mysql эти скобки по барабану вроде как

Автор: SickFxck 10.5.2010, 17:22
Цитата(anurbol @  10.5.2010,  15:57 Найти цитируемый пост)
про mysql_real_escape_string знаю давно, но мой использует не его, а просто во всех входящих $POST данных, ' и & перерабатывает в html сущности

— ты превращаешь код в полное дерьмо.

Автор: bars80080 10.5.2010, 20:13
Цитата(anurbol @  10.5.2010,  15:57 Найти цитируемый пост)
а просто во всех входящих $POST данных, ' и & перерабатывает в html сущности

конечно, задать вопрос - "зачем?", бессмысленно?

сам посуди - пользователь вводил некий текст, который содержал кавычки. ты его переписываешь в хтмл-сущности. ладно, для отображения в некоем хтмл-теле страницы оно сойдёт. но если был ввод шаблона поиска? или данные в последствии будут отданы в качестве ленты куда-то ещё?
к примеру, человек вводит ... ООО "ГлавСтрой" .... ты его преобразуешь в ООО &quote;Главстрой, найдёт ли пользователь поиском этот текст?


Цитата(anurbol @  10.5.2010,  15:57 Найти цитируемый пост)
про mysql_real_escape_string знаю давно

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

Автор: anurbol 10.5.2010, 21:25
Спасибо, что прояснили ситуацию, а насчет поиска, можно делать htmlspecialchars_decode и все.

Автор: SickFxck 10.5.2010, 22:49
Цитата(anurbol @  10.5.2010,  21:25 Найти цитируемый пост)
насчет поиска, можно делать htmlspecialchars_decode и все. 

— серьёзно?

Автор: bars80080 11.5.2010, 00:44
наверное, всё-таки методика розг в учебных заведениях прошлого имеет определённый смысл. ведь в данном случае уже исчерпаны все варианты без мата

и что я сегодня такой добрый?

Автор: SelenIT 11.5.2010, 01:39
anurbol, у языка SQL, как и языка HTML, есть свои правила. Которые нужно соблюдать при работе с этими языками. Нет общих правил "на все случаи жизни", которыми можно разом "заткнуть все дыры и там, и там".

Аналогия IRL: перед едой принято мыть руки с мылом, перед походом в театр принято чистить ботинки обувным кремом. Как выглядит человек, трущий руки смесью мыла с обувным кремом ("чтобы пойти в театр, а там поесть") - нелепо, правда? Но именно так выглядит со стороны "преобразование спецсимволов HTML в сущности во всех входящих данных", особенно если это позиционируется как "защита от иньекций" (к которым оно никаким боком).

Настоятельная просьба внимательно и вдумчиво прочитать http://phpfaq.ru/slashes. От начала до конца.

Автор: anurbol 11.5.2010, 14:27
Цитата

Спасибо, что прояснили ситуацию, а насчет поиска, можно делать htmlspecialchars_decode и все. 


о боже, какой я идиот... простите я видимо очень спать хотел и как то ляпнул не то  smile 

Конечно обидно, то что вы пишете, но все же моя цель - получить помощь а не спорить поэтому собственно прошу у вас помощи поправить в моем движке то что нужно. Дело в том что движок не мой, движок платный.


В файле header.php (который подключается к абсолютно всем файлам) 
есть следующяя обработка
Код

$_POST = security($_POST);
$_GET = security($_GET);
$_COOKIE = security($_COOKIE);



Ну а вот собственно сама функция.

Код

// THIS FUNCTION STRIPSLASHES AND ENCODES HTML ENTITIES FOR SECURITY PURPOSES
// INPUT: $value REPRESENTING A STRING OR ARRAY TO CLEAN
// OUTPUT: THE ARRAY OR STRING WITH HTML CHARACTERS ENCODED

function security($value)
{
    if( is_array($value) )
  {
      $value = array_map('security', $value);
    }
  else
  {
      if( !get_magic_quotes_gpc() )
    {
        $value = htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
      }
    else
    {
        $value = htmlspecialchars(stripslashes($value), ENT_QUOTES, 'UTF-8');
      }
      $value = str_replace("\\", "\\\\", $value);
    }
    return $value;
}



Так вот, встает вопрос, неужели этого недостаточно, и все равно надо использовать mysql_real_escape_string() ? 
Раньше кстати я и обрабатывал все данные с ее помощью, а числовые с помощью intval или даже round(floatval($var),4)

Но тогда я не видел что у меня в хедере есть функция security(), а когда увидел, решил нигде не обрабатывать с помощью mysql_real_escape_string. 

Помогите!! Где я не прав??

Добавлено через 13 минут и 14 секунд
может просто 
Код

if( !get_magic_quotes_gpc() )
    {
        $value = htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
      }
    else
    {
        $value = htmlspecialchars(stripslashes($value), ENT_QUOTES, 'UTF-8');
      }
      $value = str_replace("\\", "\\\\", $value);


переделать в
 
Код

в mysql_real_escape_string($value); 
 
и все??

Автор: bars80080 11.5.2010, 14:55
эта функция написана человеком не понимающим смысла обработки данных для вставки в БД. к сожалению, таких на пхп большинство, а то что они пишут большие проекты - ничего не значит.
единственное, что имеет смысл делать на входе - инициализировать необходимые переменные, причём только те, что нужны

то есть в примитивном идеале, обработка выглядит так:

Код

function init_var($arr, $type = 'string') {
    foreach($arr as $v) {
        switch($type) {
            case 'string': $_REQUEST[$v] = (isset($_REQUEST[$v])) ? $_REQUEST[$v].'' : ''; break;
            case 'int': $_REQUEST[$v] = (isset($_REQUEST[$v])) ? intval($_REQUEST[$v]) : 0; break;
            case 'float': $_REQUEST[$v] = (isset($_REQUEST[$v])) ? float($_REQUEST[$v]) : 0; break;
            case 'bool': $_REQUEST[$v] = (empty($_REQUEST[$v])) ? false : true; break;
        }
    }
    // можно очищенные значения пихать не обратно в $_REQUEST, а в некий массив и возвращать этой функцией
}


всё, ничего больше на входе с переменными происходить не должно. в итоге ты точно будешь знать, что у тебя есть переменная $_REQUEST['some_var'], которая не будет случайно отсутствовать в коде или иметь не ожидаемый тип

а вставка данных в БД - это уже совсем другая история, и обычно она делается точно также. то есть не всё подряд прогоняется в непонятные кодировки, а автоматизируется необходимый процесс обработки:

Код

$fields = array(
    array('name', $_REQUEST['name'], 1),
    array('age', $_REQUEST['age'], 0),
);
$r = writeRow('insert', 'mytable', $field);

    function writeRow($type, $table, $arField, $hvost = '') {
        
        if($type != 'insert' && $type != 'update') { return false; }
        $c = count($arField);
        $fields = array(); $values = array();
        if($type == 'insert') {
            
            $sql = 'INSERT INTO `'.$table.'` ';
            for($i = 0; $i < $c; $i++) {
                
                $fields[$i] = '`'.$arField[$i][0].'`';
                $values[$i] = mysql_real_escape_string($arField[$i][1]);
                
                if(!empty($arField[$i][2])) { $values[$i] = '"'.$values[$i].'"'; }
            }
            if(empty($fields) || empty($values)) { return false; }
            $sql .= '('.implode(', ', $fields).') VALUES ('.implode(', ', $values).') '.$hvost;
        }
        else {
            
            $sql = 'UPDATE `'.$table.'` SET ';
            for($i = 0; $i < $c; $i++) {
                $value = mysql_real_escape_string($arField[$i][1]);
                
                if(!empty($arField[$i][2])) { $value = '"'.$value.'"'; }
                $fields[$i] = '`'.$arField[$i][0].'`='.$value;
            }
            if(empty($fields)) { return false; }
            $sql .= implode(', ', $fields).' '.$hvost;
        }
        $r = mysql_query($sql);
        
        return $r;
    }

в итоге ни одного лишнего действия, и ни капли искажения данных, но с полным соблюдением безопасности

Автор: SelenIT 11.5.2010, 15:30
Цитата(anurbol @  11.5.2010,  14:27 Найти цитируемый пост)
Где я не прав??

1) В нежелании разобраться, что делает и для чего нужна ф-ция mysql_real_escape_string, а что и для чего - htmlspecialchars;
2) В нежелании внимательно прочитать http://phpfaq.ru/slashes.

Автор: LeoK 11.5.2010, 16:26
Цитата(bars80080 @  11.5.2010,  14:55 Найти цитируемый пост)
$fields = array(    array('name', $_REQUEST['name'], 1),    array('age', $_REQUEST['age'], 0),);

ну в вашем случае я бы еще исключил $_REQUEST в пользу $_GET $_POST

Автор: bars80080 11.5.2010, 19:05
Цитата(LeoK @  11.5.2010,  16:26 Найти цитируемый пост)
ну в вашем случае я бы еще исключил $_REQUEST в пользу $_GET $_POST 

я написал самый простой вариант. просто в $_REQUEST сводятся все остальные массивы

Автор: Muerto 10.7.2010, 11:42
mysql_real_escape_string супер не надежный
*Sorry for english, not at home...
if you have a website where you echo the $data from you fetched from your DB,
you will have a problem!
For example:
try to send something like 
Код

<script>alert("fasdfadf");</script>

you will do 
Код

INSERT INTO tb_bla (txt) VALUES ('.mysql_real_escape_string($_POST["data"]).');


You won't get any errors, just and alert message if you dare to echo it
Код

<?select * from ... fetch_array echo $fetched["txt"];?>

result: popup message = alert...
cause of this you need a filters, you cant work only with mysql_real_escape_string, I personaly don tsee any point in this function...
maybe to filter key words...

Автор: enoff 10.7.2010, 11:56
Цитата(Muerto @  10.7.2010,  11:42 Найти цитируемый пост)
mysql_real_escape_string супер не надежный

и в каком месте он ненадежный?
Добавление в базу данных проходит без ошибок, а вывод в браузер уже другая история - http://php.net/htmlspecialchars

Автор: Muerto 10.7.2010, 13:39
и ты допустим в скрипте блога будеш каждый раз фильтровать by htmlspecialchars?
если вы поиска боитесь лучше запрос поиска пропустите через ту же функцию, имхо так умней
а intval / (int) как фильтр чисел, оч плох what if my passport number is 4743756475647?

Автор: enoff 10.7.2010, 13:51
Цитата(Muerto @  10.7.2010,  13:39 Найти цитируемый пост)
и ты допустим в скрипте блога будеш каждый раз фильтровать by htmlspecialchars?

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

Цитата(Muerto @  10.7.2010,  13:39 Найти цитируемый пост)
what if my passport number is 4743756475647?

вы где живете?

http://php.net/ctype_digit, регулярные выражения не помогут?

Автор: bars80080 10.7.2010, 16:42
Цитата(Muerto @  10.7.2010,  13:39 Найти цитируемый пост)
и ты допустим в скрипте блога будеш каждый раз фильтровать by htmlspecialchars?


Цитата(enoff @  10.7.2010,  13:51 Найти цитируемый пост)
да буду.

или, если мне важна скорость, но не имеет значения объём БД, буду хранить два варианта. оригинал для правок и преобразованную версию для отдачи пользователю


Цитата(Muerto @  10.7.2010,  13:39 Найти цитируемый пост)
если вы поиска боитесь лучше запрос поиска пропустите через ту же функцию, имхо так умней

слово "умней" не очень подходит для совершения делов без понимания чего ты хочешь добиться и чего делают те или иные функции


Цитата(Muerto @  10.7.2010,  13:39 Найти цитируемый пост)
а intval / (int) как фильтр чисел, оч плох what if my passport number is 4743756475647? 

intval хорош, если ты хочешь привести число к формату int(11), оно для этого и существует. если ты хочешь привести число к другому формату, то есть другие функции

Автор: skyboy 10.7.2010, 16:54
если настолько важна скорость, что htmlspecialchars стало узким местом, то уже давно должна быть реализована кеширование сформированных кусков страницы целиком. ибо на фоне работы с базой данных, файлами, сетью, htmlspecialchars - совсем незаметное проишествие.

Автор: Muerto 11.7.2010, 00:09
я тестировал mysql_real_escape_string и уже писал чем закончилось дело...
но все же -
как его стоит использовать?
Код

select * from tb_users where username='mysql_real_escape_string ($_POST["uname"])'
      ?
а почему нет аналога mysql_real_escape_string  но просто функция? которую я смогу применять без открытого подключения?
и ещё:
предположим я хочу хранить адреса!
http://mysql.com/?r=3&b=6&v=7
after htmlspecialchars 
http://mysql.com/?r=3&amp;b=6&amp;v=7
и такое браузер не поймет если перейдем на ссылку!
а если не фильтровать то нам хсс инджекшен запихнут!

Автор: bars80080 11.7.2010, 01:21
Цитата(Muerto @  11.7.2010,  00:09 Найти цитируемый пост)
тестировал mysql_real_escape_string и уже писал чем закончилось дело...

как-то не так использовал.

Код

$field = mysql_real_escape_string($_POST['field']);
$sql = 'select * from tb_users where username="'.$field.'"';



Цитата(Muerto @  11.7.2010,  00:09 Найти цитируемый пост)
а почему нет аналога mysql_real_escape_string  но просто функция? которую я смогу применять без открытого подключения?

а смысл её применять, если ты не собираешься вставлять данные в БД

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

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

Цитата(Muerto @  11.7.2010,  00:09 Найти цитируемый пост)
предположим я хочу хранить адреса!
http://mysql.com/?r=3&b=6&v=7
after htmlspecialchars 
http://mysql.com/?r=3&amp;b=6&amp;v=7
и такое браузер не поймет если перейдем на ссылку!
а если не фильтровать то нам хсс инджекшен запихнут! 

а пример с xss можно?

Автор: Muerto 11.7.2010, 02:18
а пример с xss можно? 
вот так можно наращивать себе тиц:
есть сайт к примеру
http://blabla.ru
там есть поиск
http://blabla.ru/search.php?q=

q - this is our query for the search...

so now - >

http://blabla.ru/search.php?q=&quot;&lt;a href='http://mysql.com/?r=3&b=6&v=7'>mysite</a>
и в определенных условиях получаем 

иногда то цтхо искали показывается в форме поиска сверху...
и выходит что будет форма пустой и слева ссылка на ваш сайт, теперь осталось на свой сайт поместить ссылку:
http://blabla.ru/search.php?q=&quot;&lt;a href='http://mysql.com/?r=3&b=6&v=7'>mysite</a>

и получаем от того сайта линк бэк...

 у меня дома даже где то список таких сайтов был... спецом выискивал...

Автор: skyboy 11.7.2010, 11:50
сначала "хранишь адреса"
Цитата(Muerto @  10.7.2010,  23:09 Найти цитируемый пост)
предположим я хочу хранить адреса!
http://mysql.com/?r=3&b=6&v=7
after htmlspecialchars 
http://mysql.com/?r=3&amp;b=6&amp;v=7

потом вдруг речь начинает идти о строке поиска:
Цитата(Muerto @  11.7.2010,  01:18 Найти цитируемый пост)
иногда то цтхо искали показывается в форме поиска сверху...
и выходит что будет форма пустой и слева ссылка на ваш сайт, теперь осталось на свой сайт поместить ссылку:

чем в таком случае "мешает" htmlspecialchars - непонятно. после будет выведен как раз просто текст 
"<a href='http://mysql.com/?r=3&b=6&v=7'>mysite</a>
а вообще, браузер вполне нормально работает с адресами, в которых вместо "&" находится "&amp;"
более того, на структуру типа 
Код

<a href="http://site.com?a=b&c=d">link</a>

ругается валидатор, потому что 
Цитата

general entity "c" not defined and no default entity

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