Comments 60
От всего перечисленного спасёт банальнейший PDO. Он сам всё проверит и экранирует как надо.
А от XSS спасёт банальнейшее принудительное экранирование всех выводимых переменных, которое есть в любом нормальном шаблонизаторе. Ну и jevix и аналоги, если html всё-таки нужен.
2nd order injection means data has been cycled through the database once before being included in a query, and is much harder to pull off. AFAIK, you almost never see real 2nd order attacks, as it is usually easier for attackers to social-engineer their way in.
You can accomplish a 2nd order injection attack when you can cause a value to be stored in a database that is later used as a literal in a query. As an example, let's say you enter the following information as your new username when creating an account on a web site (assuming MySQL DB for this question):
' + (SELECT UserName + '_' + Password FROM Users LIMIT 1) + '
А теперь по-русски и с полным примером вместо непонятного огрызка, пожалуйста
Так и думал, что меня заминусуют, но я так ничего и не понял. Кто будет в здравом уме писать такой запрос, который приведён в этом огрызке? Злоумышленник его написать не сможет, потому что PDO всё заэкранирует, а программисту такое писать зачем?
Это копипаста из дурацкого ответа на стаковерфлоу. Как это часто бывает, человек написал, будучи совершенно не в теме, а потом это растащили по всему интернету. В исходной формулировке там действительно было совершенно идиотское утверждение, что "подготовленные запросы защищают только от инъекций первого порядка".
К счастью, тех пор тот ответ подправили, и он звучит теперь нормально, хотя и в стиле капитана Очевидность:
Да, подготовленные запросы защищают от инъекций, но только если используются для всех запросов в приложении. Если же это не так, то ждите инъекции второго порядка.
^(тут_условие)$
, или использовать менее параноинальный вариант, но использовать группу.Или прописать пару правил для args и location в nginx, или просто собрать последный с naxsi и снова поколдовать.
Плюсом идет ускорение работы с БД.
https://www.google.ru/search?q=sql+bind+variable
Если уж про PHP, то:
http://php.net/manual/ru/mysqli.prepare.php
http://php.net/manual/ru/function.pg-prepare.php
http://php.net/manual/ru/function.oci-parse.php
и т.д. для остальных баз.
Ускорение работы с БД получается только при отправке нескольких запросов с одной структурой, но разными параметрами.
Если же запросы все разные, то работа с БД замедляется: вместо одного запроса к БД нужно сделать два (prepare + execute).
Суть в том, что некоторые языки созданы, чтобы умирать. И даже хотя у этих языков есть режимы, в которых они не умирают — основной режим все же подразумевает смерть после каждого запроса. И потому у пишущих на таких языках нет никакого общего пула для запросов, который можно было бы подготовить на этапе инициализации приложения. Даже пула соединений — и того нет.
Вот и пытаются экономить на числе prepare-запросов...
Врочем, если какой-то язык программирования технически не поддерживает prepared statement, то вероятно это именно случай когда умирает сам язык программирования, а не его процессы.
The server maintains caches for prepared statements and stored programs on a per-session basis. Statements cached for one session are not accessible to other sessions. When a session ends, the server discards any statements cached for it.
То есть от кучи запросов от ORM вида:
SELECT * FROM sometable WHERE id = ?
Будет повторное использование и может быть даже польза =)
В целом согласен с вашим утверждением.
Тщательно проверять входящие данные.Использовать плейсхолдеры, про которые в статье почему-то не написано.
Если собираются данные в SQL вопрос типа такого:
'SELECT * from `table` where `id`="' + Экранирование( param ) + '"'
Где Экранирование заменяет
\, \0, \n, \r, ', ", \x1a
на соответствующее со слэшем
\\, \\0, \\n, \\r, \\', \\", \\Z
Возможна ли инъекция?
И если да — то каким образом?
Заранее благодарю за ответ.
Ну зачем, зачем так делать в двадцать первом веке? Чем вам параметризованные запросы не угодили?
А не затруднит все-таки ответить на вопрос?
Мне интересны именно способы атаки на такой вектор защиты — вот и все, ну и, судя по ответам, атаку не возможно провести :)
Для начала, уточните с какой СУБД работаете.
Для MariaDB/MySQL ваша функция эквивалентна mysql_real_escape_string, о чем вам уже написали ниже пока я забывал этот сделать :), поэтому напрямую SQL-инъекцию тут не засунуть.
И "уязвимость" такого подхода тоже общая с mysql_real_escape_string — очень просто забыть вызвать эту функцию. Более того: нет способа автоматически узнать, не забыл ли ваш коллега вызвать функцию экранирования. Но при должной аккуратности такой способ вполне пригоден для использования.
Допустим, по вашей постановке задачи я решу, что ваша функция «Экранирование», это что-то типа
preg_replace("/'/", "\\'", $param);
а $param — это $_GET['id'].
Подходит мое предположение под описание в вашей задаче? Подходит.
Так это на самом деле? Не уверен.
Вот и не отвечает вам никто. В вопросе конкретики не хватает, а ванговать не все умеют.
даже не хочется время терять на гадание
Странно, а зачем гадать, если можно просто уточнить? Ведь это совсем не сложно и при этом очень часто бывает так, что то, что одному очевидно, другому совсем непонятно.
И это вполне нормально :)
Без проблем, если на PHP, то пусть будет так (regexp использовать избыточно):
function screen( $s ) {
return str_replace(
array( '\\', "\0", "\n", "\r", "'", '"', "\x1a" ),
array( '\\\\', '\\0', '\\n', '\\r', "\\'", '\\"', '\\Z' ),
$s
) ;
}
Естественно, считаем что кодировки все настроены правильно.
Аргумент — пусть будет что-то из $_REQUEST / $_GET / $_POST.
Ну и заранее благодарю за ответ и за время, потраченное на мой коммент.
На самом деле первоначально в PHP плейсходеры делались внутри драйвера именно через функцию, и как правильно здесь заметили — это исходник mysql_real_escape_string.
И мне тоже не видится абсолютно никакого способа сделать здесь инъекцию — но всегда было интересно — может быть это просто я не вижу :)
Поглядел исходники mysql_real_escape_string — она ровно тем же самым и занимается)
Не надо ничего "проверять". Надо правильно работать с базой данных: использовать prepared statements, а где это не подходит — правильно форматировать SQL-запрос с учетом синтаксиса SQL.
Если бы хабр "проверял", вы бы не смогли запостить эту статью.
Мне кажется — из нативных тут в первую очередь плейсхолдеры, приведение типов, здравый смысл грамотный алгоритм обработки запросов. При чем тут хтмл, (в статье то про sql инъекци) слегка неясно. Да и хтмл — он и в Африке хтмл, тот кто парсит его регекспами такие статьи не читает.
В основном в банках, процессингах и так далее. Там такой агрессивный черный список не помешает (с реальными данными не пересечется), а от уязвимости в очередном апдейте софта от вендора, который решил сэкономить и нанял индусов на апворке, может спасти.
Вроде бы web application firewall даже обязателен по PCI-DSS, но тут не эксперт, могу и ошибаться.
Пришла идея в голову
Использовать белый список при работе с символьной обработкой
И черный список слов, состоящих из белых символов
Т.е., допустим, можно передавать только буквы латинского алфавита. И в черный список добавить все зарегистрированные слова(SELECT и т.д.)
Во-первых, у такой защиты будет очень ограниченная область применения, так как она даже ваш же комментарий не пропустит. Во-вторых, все слова в чёрный список не подобавляешь, а даже если и подобавляешь, то в какой-нибудь новой версии MySQL появятся ещё слова, которые все забудут добавить. В-третьих, ну блин есть экранирование, PDO, prepared statements, нечего велосипеды городить
Заголовок можно оставить.
В каком году PDO появился, 2004-2005? Вот настолько лет рассуждения автора отстали от жизни.
Ладно, пусть не PHP, хотя автор выбрал для примеров его, пусть другой язык. Но и там слой абстракции работы с бд будет уметь биндинг данных, чтобы не городить этих велосипедов.
Такая некомпетентность в корп. блоге. Хабр… Рука-лицо…
Вот только PDO обойти невозможно.
Всё ещё жду способов обхода PDO.)
А так — это не современная статья по защите от инъекций, а просто набор хитрых способов обхода «защитных костылей».
Ну и способ сразу заносится в копилку.
Равно как и сайт.
А уж услышав что есть возможность еще на этапе инициализации приложения перекачать все sql-запросы на сервер базы данных, проверить их там на ошибки и т.п., вообще у многих срывает крышу, так как для многих это вообще не вписывается в их картину мира.
Но самое интересное становится когда приложение, наконец, научится работать с prepared statement. Во время запуска начинает иной раз десятки секунд (если запросов десятки тысяч) перекачивать свои sql-запросы на сервер базы данных. И ты ошалевшим разрабам объясняешь, что этим мы перенесли значительную нагрузку с онлайн-режима работы приложения в офлайн. Из кода приложения можно убрать кучу обработчиков исключений по синтаксическим ошибкам в SQLзапросам. Что тоже снижает нагрузку.
После запуска обновления владельцам проекта говоришь, что вместо 10 выделенных серверов теперь можно оставить 3. Они теперь справляются с нагрузкой.
Но самое приятное получать зарплату 3-6 месяцев просто объясняя разрабам что такое prepared statement и рассказывая о всех плюшках.
/? Id = 1 + union + select + 1,2,3 / *
Насколько я понял — это строка является целевой для исполнения. Но исполнения кем/чем?
Просто я не понимаю целевого значения /? и /* в конце строки… как это работает?
Методы обхода защитных средств веб-приложений при эксплуатации SQL-инъекций