romikchef: (Default)
[personal profile] romikchef
Этот вопрос для меня настолько важен, что даже пишу в этом журнале.
Вопрос, естетственно, только для тех, кто на этих галерах.


Столкнулся я с большой проблемой. Это всё связано с факом про кавычки, слеши, PHP и Mysql.
Проблема - с определением субъекта прослешивания и окавычивания.

Поясню, почему проблема большая.
Сначала в факе я писал, что достаточно таким образом обработать данные - и всё будет зашибись.
Gотом до меня дошло, что это только строковые литералы можно защитить таким образом, а остальные части запроса надо защищать по-другому.
Сейчас собрался сесть таки переписывать, и столкнулся с вопросом:
Как обобщить тип данных, который требуется прослешивать и окавычивать?
Желательно, определение должно занимать не больше одной строки. Но не в ущерб точности.
Пусть больше. Но лишь бы это было ЧЁТКОЕ, всеобъемлющее определение!
Иначе у меня и вовсе почва уходит из-под ног.
Я-то хотел разделить рекоменации по защите запросов на две части - чёткую и нечёткую.
Чёткая - прослешивание литералов. Нечёткая - всё остальное.
но если нет точного определения для первой части, то и она становится нечёткой!
А выражение "данные", как и "строковый литерал" само по себе никакого смысла не несёт.
Хотел написать "всё, связанное со значением поля", но во-перваых, это криво, а во-вторых, как быть с литералами, не имеющими отношения к полям - SELECT 'aaa';?

http://community.livejournal.com/ru_php/552359.html

Ой :)

Date: 2006-02-01 08:10 am (UTC)
From: [identity profile] bugabuga.livejournal.com
Это попытка обтанцевать prepared statements? :) При помощи которых лёгким движением руки уничтожается необходимость написания селектов как "SELECT blah from table where a='"+$a+"'" -- взамен ставится вопросик и прикрепляется переменная, содержимое которой надо использовать?
Или я что-то не так понимаю?

А так всё, введённое юзером, надо обрабатывать :) addslashes, quotemeta и пр

Re: Ой :)

Date: 2006-02-01 08:40 am (UTC)
From: [identity profile] webeaver.livejournal.com
Нет, это попытка ЧЕТКО сформулировать, ЧТО именно нужно обрабатывать через addslashes и т.п.
А КАК, плейсхолдерами или чем то еще - это уже дело техники

Re: Ой :)

Date: 2006-02-01 02:19 pm (UTC)
From: [identity profile] mderk.livejournal.com
Слешить надо параметры. Или я неправильно понял вопрос?

Date: 2006-02-01 03:41 pm (UTC)
From: [identity profile] mderk.livejournal.com
я тебя тоже :)
Оговорюсь сначала, что, по-моему, в любом случае слешение не вредит. Если у тебя число, то в нем кавычек быть не может, если в названии поля у тебя кавычка, то весь запрос пойдет лесом.
Теперь про параметры.

Я вижу это так:
1. Есть некий литерал, который представляет собой SQL-запрос или его часть. Это - константа. Ее слешить не надо. Если тот, кто писал эту часть, вбил туда лишние кавычки, то это уже проблема безопасности несколько другого порядка.
2. Параметры можно определять по-разному, в зависимости от семантики SQL или нет - это уже другой вопрос. Чтобы ответить на твой вопрос, я бы определил "параметры для слешения" - это те данные, которые приехали из внешнего источника, например, через переменные _GET или _POST, или через строки, выбранные из базы данных, прочитанные из файла и т.п. В некоторых языках (perl, ruby) этим данным в самом начале даже прилепляется ярлык "порченых" (tainted). Этот ярлык прилепляется и ко всем данным, в формировании которых поучаствовали эти порченые данные. При этом, при определенных настройках паранойи языка, порченые данные нельзя засунуть в драйвер базы данных в виде запроса. Поэтому любые параметры, приехавшие снаружи, надо "отпорчивать".
Т.о., если у тебя 10 родилось внутри программы, и ты не брал его из значения $_GET['offset'], то это - не порченный параметр, можно не слешить. То же самое и с name.
Ну, и если ты не можешь достаточно достоверно определить источник параметра, то его надо слешить.

Date: 2006-02-01 04:56 pm (UTC)
From: [identity profile] mderk.livejournal.com
"обкавычить" ты имеешь в виду заключить в кавычки? Я думал мы про слеши ...

Объяснить просто. Имена полей, таблиц, инструкций (ключевые слова), знаки препинания в SQL не являются параметрами. Параметрами могут быть только данные. Например, если ты компилируешь запрос в prepare, ты не можешь оставить плейсхолдеры для полей - только для их значений. Вот и все. Все остальное - параметры (не уверен до конца насчет параметров LIMIT, т.к. это - нестандартная SQL-конструкция, но это частный случай).
Ну а насчет обкавычивания именно параметров, это тоже не очень хорошая идея. Если она в данное время работает на MySQL с любым типом данных, это не гарантирует, что оно будет работать где-то еще, даже, возможно, в будущих версиях MySQL. SQL, все же, строго типизированный язык сам по себе, и неявные преобразования типов в большинстве случаев - скорее прихоть разработчиков.

Date: 2006-02-02 11:09 am (UTC)
From: [identity profile] mderk.livejournal.com
Я могу сформулировать так:
1. Есть конструкции языка SQL - наименования объектов, ключевые слова, операторы. Эти нельзя ни кавычить, ни слешить, эти - как ёжики, с ними надо осторожно.
2. Все остальное - параметры (данные). По возможности нужно использовать механизм передачи параметров через плейсхолдеры, если это поддерживается базой. Тогда ничего слешить и кавычить не надо, об этом позаботится библиотека доступа к базе, в соответствие с ожидаемым типом параметра (она знает, какому типу принадлежит какой-то параметр, даже если ты сам этого не знаешь, т.к. у нее есть метаданные). Если такого механизма нет, то надо кавычить и слешить все параметры в расчете на то, что она (как MySQL, например) сама разберется с типами и сделает неявное приведение типа, если понадобится.

Date: 2006-02-01 10:56 am (UTC)
From: [identity profile] svetasmirnova.livejournal.com
Почему-то решила ответить в том топике =)

Date: 2006-02-01 07:36 pm (UTC)
From: [identity profile] tony2001.livejournal.com
линк в тему:
http://ilia.ws/archives/103-mysql_real_escape_string-versus-Prepared-Statements.html

Date: 2006-02-02 11:15 am (UTC)
From: [identity profile] mderk.livejournal.com
Ага. Ну когда же PHP начнет работать с Unicode по человечески? Или Деррик до сих пор не знает, what the fuck is BOM? :))

Date: 2006-02-02 11:18 am (UTC)
From: [identity profile] tony2001.livejournal.com
мм? а где тут проблемы PHP, покажи мне пальцем, плз?

>Или Деррик до сих пор не знает, what the fuck is BOM? :))
вот зе фак из БОМ и при чем тут ОН?

Date: 2006-02-02 12:22 pm (UTC)
From: [identity profile] mderk.livejournal.com
Ссылка, которую ты запостил, говорит о том, что PHP (ну или его встроенная и широко известная функция) не понимает разницы между символом и байтом. Ну это уже общее место в PHP. mbstring_* - это не поддержка Unicode, а костыль.

А BOM - вот он какой. История вопроса: как-то в баги запостили, что PHP неправильно обрабатывает файлы в UTF8 (создаваемые в Unicode-enabled редакторах) и отправляет BOM на вывод, вследствие чего проблемы с headers already sent. После чего пришел DR и сказал - какого хрена PHP вообще должен иметь дело с чем-то, что не ASCII? What the fuck is BOM? Как дети.

Date: 2006-02-02 12:31 pm (UTC)
From: [identity profile] tony2001.livejournal.com
>PHP (ну или его встроенная и широко известная функция) не понимает разницы между символом и байтом.

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

>как-то в баги запостили, что PHP неправильно обрабатывает файлы в UTF8
>(создаваемые в Unicode-enabled редакторах) и отправляет BOM на вывод, вследствие чего проблемы с headers already sent.

было, помню.
bogus однозначно.

>После чего пришел DR и сказал - какого хрена PHP вообще должен иметь дело с чем-то, что не ASCII?
>What the fuck is BOM? Как дети.

да всё просто: если ваш тупой редактор молча добавляет лишние символы в начало кода - это проблема редактора.
сегодня BOM, завтра BOOM, послезавтра BADABOOM, все это не проблемы интерпретатора.
жалуйтесь в Mikeysoft, что их Нотепад - кривой. пускай фиксят.

Date: 2006-02-02 12:40 pm (UTC)
From: [identity profile] mderk.livejournal.com
Ну вообще там речь сначала шла об addslashes, а он никакого отношения к mysql не имеет.

А про BOM - это не тупой редактор, это стандарт такой. UTF-кодированная строка может приехать и не от редактора.
И если PHP не в состоянии с этим разобраться, то он этот стандарт не поддерживает, вот о чем и речь. О чем спорить?

Date: 2006-02-02 12:52 pm (UTC)
From: [identity profile] tony2001.livejournal.com
да нет, вроде речь шла о mysql_real_escape_string(), которая даже в заголовке статьи стоит.
а addslashes() и не могла знать о юникоде, т.к. поддержка юникода - в PHP6.

>А про BOM - это не тупой редактор, это стандарт такой.
мм? у меня, например, ни один редактор не добавляет BOM.
хотя локаль юникодная. что я делаю не так?
плюс, насколько мне известно, Нотепад - единственный виндовый редактор, который добавляет BOM во все файлы, создатели всех остальных думали головой.

Date: 2006-02-02 01:03 pm (UTC)
From: [identity profile] mderk.livejournal.com
А, ну вот, PHP6. Мог бы с самого начала сказать.

Кстати, известно когда будет ли возможность узнать имя класса изнутри статического вызова (типа get_class(self))? Ну и другие вкусности с разыменованием имени класса перед вызовом статического метода/переменной? Костыли писать замучался.

Date: 2006-02-02 01:10 pm (UTC)
From: [identity profile] tony2001.livejournal.com
>Кстати, известно когда будет ли возможность узнать имя класса изнутри статического вызова (типа get_class(self))?
это статический вызов, неоткуда брать такую информацию.

>Ну и другие вкусности с разыменованием имени класса перед вызовом статического метода/переменной?
не понял.
$class::method(), что-ли?
используй Reflection API.

>Костыли писать замучался.
ну так пришли патч.

Date: 2006-02-02 01:56 pm (UTC)
From: [identity profile] mderk.livejournal.com
> это статический вызов, неоткуда брать такую информацию.
Ах, вот даже как. Супер.
А если self::method(), то откуда оно такую информацию берет? :)

> не понял.
> $class::method(), что-ли?

Да хоть $class::getAnythingBySomething($somethng)::method(). Какая разница?
Конечно, для методов у нас есть call_user_function, и вызвав ее положенное количество раз, мы что-нибудь поимеем.
$anything = call_user_func($class, 'getAnythingBySomething', $something);
$whatWeNeed = call_user_func($anything, 'method');

А как быть с членами класса?
> используй Reflection API.
Так ...
$prop = new ReflectionProperty($class, 'aProperty');
print $prop->getValue(new $class());

Это всё, конечно, гораздо удобнее и красивее, чем $class::method() и $class::$var. Не говоря уже о том, что:
(new ReflectionProperty($class, 'aProperty'))->getValue(new $class())
просто не работает,
а new $class кроме всего прочего вызывает еще и конструктор.
Ну, в-общем, очень удобный Reflection API, что и говорить.

Profile

romikchef: (Default)
(P) All pun intended

December 2025

S M T W T F S
 123456
789 10111213
14151617181920
21222324252627
28293031   

Style Credit

Page generated Dec. 25th, 2025 09:31 am
Powered by Dreamwidth Studios

Expand Cut Tags

No cut tags