Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770
Форумы портала PHP.SU :: Версия для печати :: PDO и кавычки
Форумы портала PHP.SU » » Работа с СУБД » PDO и кавычки

Страниц (1): [1]
 

1. Patriot123 - 05 Июля, 2014 - 15:08:28 - перейти к сообщению
Есть скрипт с использованием PDO:
CODE (php):
скопировать код в буфер обмена
  1. $DBH = new PDO("mysql:host=".$db_host.";dbname=".$db_name.";charset=utf8", $db_login, $db_password);
  2. $DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
  3. $DBH->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
  4. $DBH->exec("set names utf8");
  5. $sql = "INSERT INTO comments (id, createdate, bodytext) VALUES (null, now(), :bodytext)";
  6. $STH = $DBH->prepare($sql);
  7. $params = array(':bodytext'=>'Some " text ');
  8. $STH->execute($params);


Естественно это дело все крашется из-за кавычки в передаваемом параметре.
Можно конечно сначала все это через addslashes прогнать. Но разве в PDO не предусмотрено изначально защита от кавычек\инъекций? Что за костыли такие! Через гугл нашел, что можно попробовать так:

CODE (php):
скопировать код в буфер обмена
  1. $STH->bindValue(':bodytext', 'Some " text ', PDO::PARAM_STR);


Еще не пробовал. Но переписывать кучу кода из-за этого не очень хочется. Неужели нет другого выхода?
2. LIME - 05 Июля, 2014 - 15:15:03 - перейти к сообщению
исторически пользовался для plain запросов mysqli
потом на Доктрину перелез ввиду особенностей текущей работы
но принципы те же
подготовленные запросы
http://www.php.net/manual/ru/pdo.prepare.php
если не то просто погугли подготовленные запросы для PDO
(Добавление)
стоп
так ты же и используешь препаре
уау
ты че не можешь прочитать доки и сделать так же но свое?
3. Мелкий - 05 Июля, 2014 - 16:30:55 - перейти к сообщению
Лишнее в теме потёр.

Patriot123 пишет:
Естественно это дело все крашется из-за кавычки в передаваемом параметре.

Неестественно. prepare для того и есть, чтобы чихать на все спецсимволы.
Какое исключение выплёвывается?
4. LIME - 05 Июля, 2014 - 16:36:39 - перейти к сообщению
Цитата:
"INSERT INTO comments (id, createdate, bodytext) VALUES (null, now(), :bodytext)"
Мелкий пишет:
Лишнее в теме потёр.
спасибо
чет я погорячился
Мелкий пишет:
Какое исключение выплёвывается?
из цитаты выше должно быть понятно что кривой запрос
а в потертых сообщениях я на это намекал
еслиб ТС сконценрировался на чтении ответа он бы понял
(Добавление)
хотя я возможно не знаю особенностей PDO
не?
5. Мелкий - 05 Июля, 2014 - 17:55:19 - перейти к сообщению
LIME пишет:
из цитаты выше должно быть понятно что кривой запрос

Запрос корректен.
6. teddy - 05 Июля, 2014 - 18:08:15 - перейти к сообщению
Мелкий пишет:
prepare для того и есть, чтобы чихать на все спецсимволы.

Я тут недавно наткнулся на один пост, где автор утверждает, что это далеко не всегда так.

По умолчанию PDO эмулирует подготовленные запросы, не заставляя СУБД их подготавливать(на самом деле внутри всего лишь происходит эскейпинг данных).

Для того что бы вырубить эмулирование prepare и заставить СУБД подготовить запрос, нужно изменить соответствующий атрибут.
PHP:
скопировать код в буфер обмена
  1. $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);


Очевидно, что инъекция прокатывает только при эмулированном prepare. Дело как я понял в set names

http://stackoverflow[dot]com/questio[dot][dot][dot]2202218#12202218
Вот по этой можно прочитать про инъекцию prepare в PDO. Ввиду того, что там все на Английском, мне немного трудно дался этот текст и я многое не понял. Если кто то в курсе в чем дело, прошу поделиться, на Русском Улыбка Буду благодарен.
7. Мелкий - 05 Июля, 2014 - 18:48:44 - перейти к сообщению
teddy пишет:
на самом деле внутри всего лишь происходит эскейпинг данных

Так и есть, вызывается штатный quote.
Но атаку ранее не встречал, интересно.

Вкратце, речь о том, что атака осуществляется через set names (обратите внимание, что с utf8 это не прокатывает!), а prepare только везёт попасться за компанию. Вызов SET NAMES не меняет кодировку клиента, только сервера, как эффект - экранирование срабатывает для кодировки клиента. А вот для кодировки сервера безобидные байты с точки зрения кодировки клиента превращаются в кавычку.
Через set names же кодировку ставить вообще некорректно, в DSN надо указывать charset. Но для устаревших версий PHP там была ошибка, параметр игнорировался.

Как итог - держите софт в актуальном состоянии, не пользуйтесь set names и не выпендривайтесь с невнятными кодировками, используйте юникод.
И эмуляцию препарированных запросов всё же выключайте, пусть субд ими занимается.
8. teddy - 05 Июля, 2014 - 18:58:13 - перейти к сообщению
Мелкий пишет:
обратите внимание, что с utf8 это не прокатывает

Да, я заметил в примерах.

Честно говоря прежде не отключал эмуляцию. Думаю эмуляция имеет смысл только при работе через PDO с теми СУБД, которые не поддерживают prepare.

Благодарю за участие, в целом я представлял себе ситуацию приблизительно так как Вы её описали, но были сомнения, которые рассеялись с Вашей помощью.
9. Patriot123 - 05 Июля, 2014 - 19:49:46 - перейти к сообщению
LIME пишет:
Цитата:
"INSERT INTO comments (id, createdate, bodytext) VALUES (null, now(), :bodytext)"

из цитаты выше должно быть понятно что кривой запрос
а в потертых сообщениях я на это намекал
еслиб ТС сконценрировался на чтении ответа он бы понял
(Добавление)
хотя я возможно не знаю особенностей PDO
не?


Я даже не представляю в каком месте этого запроса можно сделать ошибку? Выполнять его не пробовал и прочесть хотя бы? Элементарный инсерт!


Проблема решилась апдейтом php до версии 5.5.9. Код остался прежним.

 

Powered by ExBB FM 1.0 RC1