Pull to refresh

Comments 178

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

но вцелом конечно-же это клевый способ
При таком методе защиты отпадает необходимость дополнительной фильтрации входных данных, что в свою очередь снижает нагрузку.)))
Но конечно провести сравнительное тестирование обоих методов было бы интересно.
Вообще-то данные нужно фильтровать не только для INSERT, UPDATE но и для SELECT, DELETE. Так что использовать этот метод нужно при любых обращениях к БД с использованием входящих данных.

Или я не правильно Вас понял?
Использоватьнадо везде где есть входящие внешние данные, используемые внутри запроса, если их нет то тогда никчему
А с сортировкой как быть?
UFO just landed and posted this here
Думаете, base64 сильно медленнее экранирования?
Кодирование — элементарное, по сути сдвиг битов в байтах, с чего это нагрузка на процессор должна сильно возрасти?

Еще во времена DOS на дохлом-дохлом 386/40MHz UUE кодирование для фидо не представляло НИКАКОЙ сложности, выполнялось почти мгновенно для файлов размером в сотни KB.
С id все хорошо, а вот с текстовыми данными в базе не очень. Поиск по текстовым данным сделать не получится
Почему? в базе данных все хранится в нормальном виде же.
В базе всё хранится в plain-виде, работа поиска никак не изменится.
Если берём строку для поиска от пользователя — кодируем её в base64, сервер БД раскодирует.
Всё равно придётся менять код приложения, а тогда уж легче Mysqli::real_escape_string, который не будет кушать процессора сервера БД.
Будет, но не, скорее всего, так сильно, как раскодировка base64

Согласен со Змием. У меня в некоторых базах лежат достаточно солидные хэши. Конвертить туда-сюда — эхто грустно.
Это рпоисходит лишь только на уровне запроса. Единственное когда могут возрасти сильно нагрузки — это при кодировании больших объемов данных, но такое в томже вебе не сильно частое явление — обычно 255-1024 символа, по опыту личному
А по-моему метод интересный, и вполне может найти применение там где не требуется большая нагрузка, для чего-то не серьезного, чтоб сделать по-быстрому и безопасно. Для серьезных проектов придется делать по-старинке (читай по-нормальному).
Занимательное решение. При нынешних мощностях можно использовать не заморачиваясь.
Нынешние нагрузки вы не учитываете, только мощности?
Последние имеют специфику расти стабильно и расширяются без особых заморочек.
«Сейчас компьютеры такие быстрые, что это просто не важно» слышал я когда-то от горе-преподавателей и тех студентов, которые на это велись… К сожалению, такая логика будет существовать вечно, наряду с плохими дорогами.
UFO just landed and posted this here
Самый интересный и простой вариант защиты от SQL-иньекций — читать мантру «Ёлопукки Ёлопукки, переставь мне с жопы руки». Если не помогает — тогда «парашютный спорт не для вас».

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

Существует масса программистов занятых «кодингом», и зачастую они просто забывают это делать, а за всеми не уследишь, этот же способ лишает их возможности сделать такую ошибку.

Кроме того такая ошибка может вкрасться элментарно по не внимательности, пусть даже одна в большом и качественном коде ( причем даже у такого Ёлопукки как Вы :) ) — этого уже хватит.

Надо чтобы код максимально избавлялся от человескеого фактора и ошибок с ним связанных. И это правильно.

Placeholders — выход, но при сложных запросах где надо писать упоминание на множество таблиц плейс превращает более-менне понятный запрос в кашу, причем ДАЖЕ ( и ОБЫЧНО ) если вы юзаете алиасы чтобы не писать кучу переменных в плейсах.
«Существует масса программистов занятых «кодингом», и зачастую они просто забывают это делать, а за всеми не уследишь, этот же способ лишает их возможности сделать такую ошибку.»

Вот именно поэтому base64 и беспомощен — забудет ли кодер поставить плейс, или же забудет поставить base64 — никакой разницы, кроме нагрузки и беспомощности base нет
если использовать враппер, как предлагает оригинальный автор — без бейза небудет работать
Если использовать обертку — то и экранирование спец.символов сделать не проблема.
Почему это именно placeholders превращают сложный запрос в кашу?
В кашу запрос превращает именно человеческий фактор.
А плейсхолдеры помогут:
а) непозволить этому «человеческому фактору» забыть передать параметр (или передать его криво)
б) «скомпиллировать» запрос (применимо к полноценным БД/языкам программирования) и сэкономить на повторяющихся вызовах с изменением параметров
Пункт Б кстати укладывает аргументацию base64 в абсолютный нокаут :)
Поддерживаю. Для СУБД, если не использовать плейсхолдеры, каждый запрос будет уникальным. Добавление плейсхолдеров парой может дать очень существенный прирост производительности.
потому что в лейсах обычно запрос строится по принципу:

«select # from #2 where # and # and # order by #», #, #, #…

А теперь представим что он у нас сложно подчиненный, количество and во where меняется, как и кол-во order полей.

не сильно удобно
А тут уже поможет простое понимание чистого кода при форматировании запроса

SELECT
    a.field,
    b.field,
    c.field
FROM table_a a
    INNER JOIN table_b b
        ON b.b_id = a.f_b_id
    LEFT JOIN table_c c
        ON c.c_id = b.f_c_id
WHERE
    (
        a.cond = ?          /* 1 */
        OR (
            b.cond = ?      /* 2 */
            AND c.cond = ?  /* 3 */
        )
    )
    AND c.list IN (?)       /* 4 */

Perl:

$dbh->do(
    $query,
    undef,
    $var1,      /* 1 */
    $var2,      /* 2 */
    $var3,      /* 3 */
    $listref4   /* 4 */
);
эм… ну по мне так не сильно читаемый код получается, уж извините. Понятный и поддающийся разбору — да, но читаемость невысокая.
зато комментарии помогают помимо всего прочего отслеживать запросы к базе!
Ну и тем более — чем же не читаемый? Вместо /*1*/ ничто не мешает поставить имя переменной

Тут парсер немного пробелы побил — но попробуйте написать в любимом редакторе и не успеете оглянуться как привыкнете)
Хороший код — это код который можно читать без комментариев. Если не согласны, тогда почему бы не писать переменные:

$k, $er, $kd, $n? а код пусть будет линейным, нах нам все эти удобства когда есть комментарии?
Есть естественно исключения, — чтобы прочитать сложный SQL-запрос без комментариев, надо знать хотя бы структуру БД. Соответственно, вывод только один — что если проект имеет сложные SQL — комментарии там будут хорошим тоном минимум. И не только референсы на параметры, но и краткое описание того, что он выбирает, — даже если поля очевидные.
Очень сложные SQL запросы, причина по которой нужно пересмотреть текущую архитектуру.
не знаю как в perl, но в .net и даже в php есть именованные плейсхолдеры.
А теперь напишите этот же запрос вместе с base64. Неужели лучше?
ИМХО для сложных полиморфных запросов используются своеобразные «билдеры» и задача билдера следить за тем, чтобы все было на месте.

Что-то типа:
sql = select('*')->from('table1')->join('table2')->on(...)->where('table1.fied', requestvar.table1.field)->and('table2.field', requestvar.table2.field)->…

Как такой билдер соберет запрос (с плейсхолдерами и последующей передачей значений или сразу все сам правильно заескейпит) — вопрос уже риторический.

В случае же набора статических запросов, плейсхолдеры показывают себя с лучшей стороны.
А для таких случаев придумана инкапсуляция )
Поясню: если уж собираем SQL какой-то оберткой, ничто не мешает задавать параметры вместе с плейсхолдером. В итоге параметры будут правильно связано, даже если структура запроса зависит от некоторых условий.
MQ(«select ?»,$tableName," from ?",$othertable", where ?",$a," and ?",$b) и так далее.
потом идем по аргеументам и по простейшим правилам собираем нормальный SQL и нормальный массив холдеров.

вариант2

вариант2:
MQPa(«select #1 FROM #2 WHERE val=#3»,array(1=>'table',2=>'othertable',3=>'helloword');
эмм?
Что вы имеете ввиду под «простым квоттингом»?
Ничем не лучше, если грамотно применять квотинг. Но ошибки бывают — а то бы не было атак. Преимущество base64, что если оно такое пришло от клиента, а разбазить где-нибудь забыли — то сразу выплывет при самой элементарной отладке. А текст будет работать и с дырой.
Так, вы навели меня на один вопрос. Как base64 encoded строка будет подставлятся в запрос?
отлично! после этого коммента можно закрывать обсуждение. данные в base64_decode точно так же перед использованием нужно проэкранировать.
Типа «select...where id=base64_decode('». base64_encode($_GET['id']). "')";

Прелесть, в общем.
А использовать prepared statements (подготовленные запросы)?
При условии, что вся работа с базой ведется из одного места (скажем, фреймворка), то довольно легко реализуемый метод.
Конечно, не все БД их поддерживают, но для MySQL вполне себе выход.
Вот именно. Что только не придумают, лишь бы не использовать Prepared Statement!
Не ново, не серьезно, и в конце концов, если уж так делать то проще просто в HEX'е передавать — быстрее будет преобразовываться.
А вот и не быстрее, как практика показала. На мелких — может быть и будет сомнительный выйгрыш, а на хайлоаде будет мясное мясо.
Пруф, пожалуйста. Очень сомневаюсь, что изменение типа(обычный каст) будет дольше чем кодирование. Хотя хз, что у вас за субда.
Из личной практики на форковой нагруженной модели с xtraDB, пример не могу показать — СБ не дремлет, — но тюнили очень долго и от хекса отказались в итоге.
Ну, видимо, это проблема исключительно xtraDB.
Врядли, — xtraDB — это мегаутюненный InnoDB

Хотя, может конечно и от задачи зависеть конкретной. Возможно, что на MyISAM и только на селектах работало бы чётче.
Как хранится тут не причем, это же функции. И вообще что-то я не нашел встроенной функции в MySQL для base64.
Проверил выполнение кодировки в hex и обратно:
«select test_hex(100000) from dual» выполнился за 2.3 секунды на слабеньком железе, где
CREATE FUNCTION `TEST_HEX`(i INTEGER(11))
    RETURNS int(11)
BEGIN
  DECLARE v TEXT;
  WHILE i > 0 DO
    SELECT UNHEX(HEX('a123')) into v from dual;
    SET i = i - 1;
  END WHILE;
  RETURN v;
END;

Плохой пример
на мелкой табле конечно будет хорошо работать

А если БД на 500 гигов и таблицы по 10-200 гигов?:)
Как я уже говорил — размер базы и таблицы значения не имеет. Имеет значение лишь кол-во вызовов. И уж собственная хранимка для декодирования base64 однозначно будет выполняться медленнее встроенной функции преобразования.
Как же не имеет когда имеет? А вставки? Да даже выборки по индексам — а если без индекса?
Я говорю сейчас только про MySQL, — но не думаю, что это игнорируется в том же постгре.
Да причем тут выборки/вставки? Сравниваем функции, причем встроенные функции и пользовательские, причем алгоритм base64 никак не быстрее простого изменения типа.
Чтобы отпали последние вопросы по поводу размеров: как и когда выполняются функции?
Функциям вообще насрать на индексы — вы вообще путаете совершенно разные вещи.

PS. и какой знаток баз данных еще и минусует?
А если хочется ну совсем уж извратиться «гениальностью», то можно вообще в базе все только в blob'aх хранить — совсем ничего не надо будет ничего «защищать».
скорость? поиск? склеивание?
С бэйсом, бред полный. И объясните теперь мне как он спасет от XSS? Пользователь будет читать текст в бэйсе? И чем он лучше обратных слэшей? А SQL-запросы мониторить как?

На счет Дена Каминский и его кореша Кевина Митника ничего хорошего сказать не могу. Эти герои при всем своем знании ИТ безопасности недавно сели в глубокую и грязную лужу.

Лог прилагается:
lists.grok.org.uk/pipermail/full-disclosure/2009-July/069965.html
От XSS он спасет когда данные на клинета бегут в бейзе и там раскручиваются. таким образом
var a=«abc»;alert(5);b=«7»
превратится в a=«base64string»;
и не выполнится.
както так
Ага, это в JS

Учитывая, что base так же как-то должен разбираться, логично что в коде страницы есть и соответствующие функции.

А потом xss формируется с base64_decode в адресной строке или в запросе или ещё где.
Ну понятно что «универсального соладата» нельзя сделать :)
Для JS — универсальный солдат это приведение типа и регулярки на проверки варчаров.
Для SQL — плейсхолдеры или тоже приведение типов или собственные проверки на корректность
В таком случае считайте это «просто одним из вариантов» реализации плейсхолдеров :)
UFO just landed and posted this here
в базе как раз данные храняться в нормальном виде, одного уже не внимательно читающего тут заминусовали)
UFO just landed and posted this here
В общем я почти согласен, но способ имеет право на жизнь в каких-то конктерных случаях, сам я использую фреймворк, но не всегда его можно использовать, зачастую приходится возиться и со старым корявым кодом заказчика да много ситуаций. Что касается написания кучи лишнего кода, то тут тоже не согласен живем же в век ООП можно все упростить) Но опять же все применимо только к каким-то конкретным ситуациям…
UFO just landed and posted this here
> Нет необходимости как-то экранировать или изменять входные данные. Достаточно закодировать их в base64 и передать в запросе.

Я завис.
Ну типа плейсхолдеры или экранирование хотя бы через addslashes — это муторно и не клёво, а писать id=base64_decode('" . base64_encode($input) . "'); — клёво и супер.
Этот баян долетел и до хабра. В двух словах — они изобрели плейсхолдеры (с)
Не совсем, плейсхолдер сам следит за недопустимыми значениями, так? экранирует их если есть необходимость, если нет — оставляет «as is», он же занимется сборкой — т.е. расставлением кавычек и т.д.
Например, если пх знает что в mysql в стринге не должно быть кавычек он их заэкранит, гипотетически возможно появление следуюещго — находят что какаято последовательность символов позволяет реализовать какую любо угрозу — если пх выпущен ДО этого — оно про это не знает и ничего не делает соовтетвенно.

Здесь же данные идут «в контейнере» — от такой ситуции ты застрахован.
хм… а я вот искренне считал, что плейсы работают как-то так.

SET @a = 'как-я то строка';
SELECT * FROM foo WHERE bar LIKE @a;

при этом оно НЕ и в страшном сне не должно заниматся экранированием и прочей хренью.
Или где-то в спеках есть обратная инфа?..
а «как-я то строка» в виде чего у вас представляется? в виде пришедшего параметра? :)
Пример не совсем удачен, вот тут www.w3.org/TR/webdatabase/ написано лучше.
4.2 Parsing and processing SQL statements
NOTE: Binding the ? placeholders is done at the literal level, not as string concatenations, so this provides a way to dynamically insert parameters into a statement without risk of a SQL injection attack.

Не понимаю, в чем преимущество? Что не забывать экранировать, что не забывать кодировать-декодировать. Первое даже проще.
Феерический ужас. А что, везде декодировать base64 это действительно проще, чем починить код, подверженный SQL injection?
потому что так написано:
> в подстановке в SQL-запросах всех данных в base64-представлении

Т.е. гениальность этого метода состоит в том, чтобы поменять все SQL запросы?
ну простите, все разжовывать у меня времени нет. имеется ввиду «внешние данные», или если будет удобно «данные в которых может быть возможность угрозы», по моему это вполне понятно из статьи? нет?
То есть старую схему «просмотреть все данные в которых может быть возможность угрозы» и заэкспейпить или переделать на PreparedStatement заменяем на совершенно новую «просмотреть все данные в которых может быть возможность угрозы и закодировать все входные параметры как base64»? Это, безусловно, прорыв.
Снижение скорости работы, необходимость переписывать все поисковые алгоритмы, капитальное снижение скорости поиска, увеличение базы как минимум на 1/4. В топку такой метод.
У меня складывается впечталение, что ВЫ, дорогие господа, дочитали только фразу про base64, ничего дальше не прочли, не поняли, но зато написали коммент :/
Ага, не вкурили господа, верняк.
Но все равно, типичный образчик хреносозидательства в чистом виде.
Я уж молчу (потому как не помню) про кеширование запросов (как оно там без плейса отработает — одному Аллаху ведомо).
Избавляться от инъекций надо фильтрацией переменных, а не кодирование/хэширование/медитированием. Кодирование в base64 для того, чтобы база тут же раскодировала — откровенная глупость. Во-первых, это долго. Во-вторых, это не так функция, для которой создавался SQL.
Это лишь один из вариантов, никто не писал «делайте именно так».
А когда есть варианты — это гораздо лучше, когда их нет, не так ли? :)
Разве что этот вариант заведомо бредовый, т.к. снижает производительность, читабельность, создает проблемы с кешированием.
Любая проверка входящих данных все это делает, с кэшированием не согласен — пофиг абсолютно что в качестве ключа для md5 (например) использовать.

Объем данных растет на 30% это да большой минус, согласен
Проверка входящих данных:
1. работает, как правило, быстрее
2. дает возможность обрабатывать ошибки входных данных и информировать о них пользователя
3. читабельнее
Вы что, до сих пор все запросы руками вбиваете? У меня нет слов… base64… ААААААААаааааа!!!!11!!11
А при чем тут вбивание руками? Указанный способ — пример упрощения валидации входящих данных.
Это не упрощение валидации входных данных, тут валидации нет вообще в принципе. Валидацию делает ORM. Если ORM вам не подходит, то пользуйтесь плейсхолдерами — технологии обкатаны индустрией в течении десятков лет. Зачем такой идиотский велосипед с квадратными колёсами?
К сожалению, не все знают, что такое ORM, и не все пользуются placeholder'ами. PHP же :)
Значит надо на хабр написать статью про ORM, плейсхолдеры, препареды и обьяснить, почему использовать нужно именно их. А за этот base64 Дэну надо дать по голове.
Ждем новых статей
Вот ха это я только всеми руками за.
Кармы нет, а так у меня в запасе есть парочка статей на тему HTML5 + CSS3 и на тему хардкорной оптимизации JS в случаях, когда это действительно нужно.
А вы что, не оптимизируете вручную запросы в узких местах на хай-лоаде?
И как оптимизация влияет на использование prepared и placeholders? Там где нужен ORM во всей красе — там ORM, там где не нужен — placeholders или prepared, смотря что вам привычней. Вариантов много для любых нужд. base64 и hiload — это вы знатно пошутили.
Это ответ на ваш бредовый комментарий про то, что якобы вбивать все запросы руками — это не по-джедайски.
Да, не по-джедайски. Ибо вы сначала находите узкое место в проекте и только тогда его оптимизируете. А не сразу начинаете всё долбить руками. И не всегда оптимизация — это вбить запрос руками. Иногда достаточно хорошо знать используемое вами решение для его оптимизации. Например, я использую ActiveRecord из Ruby On Rails, зачастую достаточно правильно настроить модели, чтобы они делали постройку запросов по другим правилам.
А что, кто-то вообще использует активрекорд в хайлоаде? Я имею в виду реальный хайлоад, а не «сайт под ключ за месяц».
Используют, почему нет? А что ещё использовать? Ассемблер? :) Кому что удобнее, то и используют. Ну или взять Hibernate — там тоже есть что покрутить без лазанья в дебри SQL. Да, иногда приходится писать и руками. Но в любом случае только тогда, когда уже всё готово и работает.
Часто писать руками не «удобнее», а это единственный приемлемый вариант.

SQL сам по себе достаточно высокоуровневый, чтобы его использование не создавало больших трудностей. А вот активрекорд при больших нагрузках создает гораздо больше проблем, чем решает.

Почему С++ уже на протяжении 20 лет остается основным языком во множестве отраслей, хотя есть миллион гораздо более гибких, удобных и мощных языков? Здесь та же ситуация.
UFO just landed and posted this here
Потому, что на нём написаны тонны кода, который и были бы рады выкинуть, да слишком дорого переписать.

Вовсе не поэтому. Попробуйте написать нормальный графический движок на чем угодно кроме С++ и поймете.

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


Смотря какая задача ставится. Если написать сайт заказчику за месяц — да. Если выдерживать несколько сотен запросов динамики в секунду при расчете на одну машину — вряд ли.
UFO just landed and posted this here
Графические движки на яве и питоне? Вы явно не владеете вопросом.

Возьмите к примеру андроид. Там изначально сделали только поддержку явы. После того как разработчики игр толпами стали испытывать жесточайший баттхерт при попытке начать что-то писать под эту платформу, там срочно допилили NDK с поддержкой С++, и только после этого стали появляться нормальные игры. Вы правильно сказали, других языков с такой широкой поддержкой платформами нет. Только вот теперь подумайте почему.

На С++ пишут из-за возможности непосредственной оптимизации, управления памятью и контролем над ресурсами, а не «ради портирования на консоли». В яве одна только невозможность прямого освобождения памяти и постоянных затыков с GC осложняет в десятки раз написание определенных вещей типа игр на ней. Я уж не говорю про постоянные оверхеды на вызов методов, ресолвинга объектов и т.д.

Ну расскажите же мне, каким образом вы обгоните ОРМ когда он генерирует код полностью аналогичный тому что вы бы написали руками? Или написаный руками код магическим образом ускоряет выборки по первичному ключу, например?

Разумеется, речь идет не про эффективность выполнения запроса, а про затраты на его генерацию и обслуживание объектной модели. Я думал, это самоочевидно.

UFO just landed and posted this here
Что значит «действительно считаю»? Мы что, о живописи тут говорим? Я это знаю, а не считаю, как бы не первый день в индустрии и исследовал множество тест-кейсов. Объектная модель жрет память в совершенно неприемлемом для нагруженных проектов количестве.

До тех пор пока решаемая вами задачи GPU-bound совершенно всё равно на чём написано приложение.

Ерунду написали. Видеочип решает лишь низкоуровневые задачи. Написание даже простейшего движка не сводится лишь к задаче рендеринга. Нужно хранить огромное количество структурированной информации и очень, очень быстро манипулировать ею. А в яве даже нельзя безболезненно сделать простейшую операцию вроде «создать N партиклов и через 500мс их прибить», обязательно проснется GC и будет убивать эти N объектов, тормозя весь тред и создавая лаги.

В общем, не вижу смысла продолжать далее этот спор, у вас явно не хватает широкой компетенции.
UFO just landed and posted this here
Практически все современные игры содержат в себе только капельки C++, который служит не более, чем прямым доступом к ресурсам ОС. Сюрприз! Уже Quake первый был целиком скриптованный. Да и Duke Nukem был, правда не до такой степени. Глядите исходники кваки — они легко доступны. А ScummVM? Там, правда, не 3D, но сишки там тоже почти нет.

А MMO игр с явой внутри вообще навалом. Да, опять же всё обёрнуто в небольшой C++, но вся суть игры — ява.
Да-да, именно так. C выступает низкоуровневой прослойкой. Вся логика первой кваки заскриптована на QuakeC en.wikipedia.org/wiki/QuakeC, да будет вам известно. Скриптовано абсолютно всё — физика, AI, поведение оружия и вся игровая логика. Если лень качать исходники, то читайте английскую Wiki — там больше информации.
Причем тут логика игры? Мы говорим о графическом движке (о том, что вы почему-то называете «прослойкой»). Именно он является основной частью проекта при разработке игры. На логику тратится от силы 5% общих человекочасов.

Первостепенное достижение всех игр от id Software вообще и Джона Кармака в частности заключается именно в разработке движков. Скриптовый язык для логики может написать любой студент. Приводя аналогию в вебе, это все равно что сравнивать разработку API для сервиса и разработку самого сервиса.

Вы вообще хоть как-нибудь с геймдевом связаны? Есть ощущение, что я говорю о живописи с незрячим. Судя по всему, вы с вопросом знакомы лишь поверхностно, на уровне кастомизации игр и написании модов.
Хехе, community.livejournal.com/ru_mysql/165835.html:
Каков шанс sql-injection, если в запросе все текстовые поля передаются в 16-ричном виде?
например:
INSERT INTO news VALUES (NULL, '2007-05-03', 1, 0x74657374, 'ru')

как я был к этому близок 3 года назад :)
«SELECT * from mytable where textfield=base64_decode('Q29vbEhhY2tlcnM=')»
Вы привели хороший пример, я даже скажу так — идеальный.
А покажите теперь как этот запрос будет строится для пришедших данных. Не важно на каком языке.
как простейший вариант:

$a = base64_encode($_GET['data'])
$sql = 'SELECT… '.$a.' ......';

нет, $sql = 'SELECT… base64_decode("$a") ...'
заметьте, что base64_decode() вписан внутри запроса и выполняется на стороне сервера

хотя автор предлагает более простой способ, что-то вроде
$sql = base64_wrap_sql('SELECT… ^^$_GET[data] ...')
Ээээ. Я просто не написал все. Я имел в виду

$a = base64_encode($_GET['data'])
$sql = 'SELECT… base64_decode('.$a.') ......';

Это как раз то, что предлагает автор :)
1) пишется обычный запрос с плейсхолдерами
«SELECT * from mytable where textfield=?»
2) переписывается код проставления плейсхолдеров. тот код, где переменная эскейпилась (и при необходимости оборачивалась в кавычки), заменяется на код, который енкодит значение и возвращает такую конструкцию base64_decode(ЗАЕНКОДЕНОЕ_ЗНАЧЕНИЕ_В_КАВЫЧКАХ)

другого вменяемого варианта не представляю… смысла тоже
Вот ведь люди. А то, что параметризованные запросы лучше кэшируются, заведомо защищены от инъекций и так далее — это им пофиг?
это надо же объяснить толпам горе-РНР-программистов, которые даже не знают, что такое параметризованные запросы (а РНР всеми силами старался и старается, чтобы они и не узнали)
Ну понятно. Как всегда, кто-то борется со своей ущербностью.
не надо устраивать тут холивары. тут все зависит от человека а не от языка
От языка тоже.

1. В РНР placeholder'ы и параметризованые запросы появились достаточно поздно
2. функции mysql_escape_string и mysql_real_escape_string своими названиями символизируют
3. В РНР на данный момент есть три, а на подходе — четвертый, способ подсоединения к MySQL. Из этих способов в одном работают параметризованые запросы, в другом нет. В одном работают именованные placeholder'ы, в другом — нет и т.п.

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

А бардак обычно начинается изза человека а не изза языка.
> А бардак обычно начинается изза человека а не изза языка.

Если язык и среда не предлагают иных средств, кроме бардака, то увы.

Например из-за пункта 3 приходится или:
— использовать повсеместно генерацию запросов с банальной конкатенацией строк и mysql_real_escape_string
— или продавливать апгрейд РНР/компиляцию соответствующих расширений у клиента, а то и насиловать девелоперов переходом на другие ОСи (потому что mysqli, емнип, не работает под МакОСью).

Это ли не бардак?

При том реальных усилий по уменьшению бардака никто, на самом деле, не предпринимает. Потому что legacy, потому что у самих разработчиков РНР достаточно сильный бардак в головах и т.п.
Ну не знаю, я PHP-программист, а все равно узнал про параметризованные запросы и успешно ими пользовался. Не увидел никаких сопротивлений со стороны PHP.
Если вы именно про «горе-РНР-программистов», то скажу что это скорее всего относится к горе-*-программистам…
Я не говорил, что РНР сопротивляется. Он способствует разведению бардака.

Вопрос на засыпку: зачем в РНР три способа подключения к MySQL с разными возможностями (пункт 3 из моего сообщения)? И что делать, если один из этих способов не работает на target системе?
Пару лет назаз, когда я только начинал изучать PHP я предложил такой же метод защиты на форуме CMS 2z-project. Тогда с меня только посмеялись и сказали, что так нагрузка значительно возрастет. Наверное, не таким уже и дураком я тогда был :)
И здесь половина комментаторов смеётся над автором.
> Наверное, не таким уже и дураком я тогда был :)

Вы хотите чтоб над вами опять посмеялись?
Как я уже сказал, тогда я только начинал учить PHP. Сейчас я бы никогда не использовал такое в проекте, т.к. осознаю все минусы такого подхода, но то, что кто-то другой предложил подобное + еще кто-то поддержал говорит о том, что я по крайней мере не один такой.
Все равно не понимаю ваших рассуждений. Если сейчас вы понимаете что это неэффективный подход, который, разве что, в рамку повесить на память, то тогда к чему «Наверное, не таким уже и дураком я тогда был». Вам трудно признать, что это была дурная идея? Я на своей практике столько глупостей делал и я этого не стесняюсь. От каких-то глупостей уходил сам, от каких-то глупостей помогали уйти.
А то что кому-то пришла такая же идея и ее кто-то поддержал, не значит что идея стоящая. Люди просто не знают что такое плейсхолдеры или не смогли с ними подружиться.
Ой, у меня deja vu. По-моему теме уже месяца полтора.

Вообще, прежде чем комментировать или критиковать, обязательно посмотрите слайды Interpolique:
www.scribd.com/doc/33001026/Interpolique

Там всё рассматривается гораздо глубже, нежели описано в статье, например вопросы сессий в web, и в общем type safety в программировании.
Тем не менее, приводимые самим автором примеры (особенно в части SQL-инжекта) — это зло само по себе, безо всякой безопасности.
Посмотрел я слайды. Вот, где он ошибается:

«How do we communicate across all these languages? Strings»

PS Кстати, пусть он попробует так же защититься от инжекта в случае, когда надо собирать SQL-запрос (т.е., с самим языком, а не значениями; или хотя бы имя колонки передать). А что, универсальный же способ, нет?
Да этот конкретный метод я вряд ли защищаю, но сам взгляд на вопрос с правильной стороны. Type safety между языками — вот то о чём стоит подумать.

А в чём ошибка утверждения о «Strings»?
В том, что коммуникация между языками идет через формализованный интерфейс. Он может быть стринговым, а может быть и не быть таковым. Например, в .net код можно генерить текстовым шаблоном, а можно — объектным деревом.

То же и при взаимодействии с SQL — если какой-то дурак хочет потерять type safety, он конкатенирует стринги и напрямую собирает запрос. Но в реальности это не единственный способ, есть датапровайдеры, интерфейсы доступа и миллион других вещей, которые избавляют нас от прямой сборки строкового кода на другом языке.
Тут вы безусловно правы, да.

Автор, мне кажется, имел ввиду в этом утверждении то что за границу языка, так или иначе, выходит String. На следующем слайде он формулирует задачу: «The challenge: Maintaining type safety across language boundaries», а затем, упоминает, к примеру, те же параметризованные запросы.

Просто решение что он предлагает, в определённом смысле, костыль. Действительно, зачем, если есть множество готовых безопасных интерфейсов коммуникации?
Это очень спорный вопрос, на самом деле, что выходит за границу языка. Например, в случае с доступом в БД за границу вызывающего языка выходит отдельно команда (стринг), отдельно типизованные объекты значений (не важно, типизованы они средствами COM, или java, или .net).

То есть проблема сохранения типов есть. Но говорить при этом, что все передается стрингом — неверно.
Спасибо за объяснение. Да, действительно весьма спорный вопрос. Теперь я смог взглянуть иначе.
Камински просто уперся в то, что «программисты не хотят передавать параметры». Ну и дураки, что не хотят, учить надо. Можно, на крайний случай, предоставлять синтаксический сахар в языке, который будет автоматически распарсивать конструкцию на неизменную + параметры.

Но, как мы все понимаем, никакого отношения к защите это уже не имеет.
Поиск и добавление ладно, а на выводе данных из базы экранировать-то таки как-то придется ;) А раз придется, то экономнее это сделать еще на инсерте.
Да в любом случае и до и после надо обрабатывать. «filter input, escape output», ведь так?
UFO just landed and posted this here
=)))))))) Ппц жесть. А может лучше base64_encode заменить на escape_string??
Совершенно не оценил восторгов автора, поэтому пошел читать оригинал. Вроде, вот что они предлагают:

Было: «INSERT posts SET author = {$_POST['author'}»
Стало: eval(b(«INSERT posts SET author = {^^_POST['author']}»));

И это, якобы, лучше плейсхолдеров. Есть мнение, что просто кто-то перестарался с употреблением веществ</em.
Или я прилетел из будущего, или вышел из комы, но по-моему этот древнейший боян уже давно на хабре был обсосан? Удалили чтоль? Помню обсуждали параллельно с лором www.linux.org.ru/forum/talks/5014295
Согласен, на ЛОРе это обсосали со всех сторон. Помню даже в Радио-Т обсуждали больше месяца назад (#192).
Вместо того чтобы учить программистов писать защищенный код, предлагается решение навроде Magic Quotes в PHP.
Да, да. Один в один прям.
>Очень интересный вариант защиты от SQL-инъекций и XSS

от XSS не поможет
Ну вы наши что вспомнить. Это во-первых, боян. А во вторых, костыль.
О каком base64 который встраивается в бд идёт речь, если та часть веб программистов для которых изобретенна данная вещь, неудостаиваються поставить mysql_real_escape_string и поставить ковычки, или intval()…
UFO just landed and posted this here
UFO just landed and posted this here
Sign up to leave a comment.

Articles