Skip to content

Instantly share code, notes, and snippets.

Created August 30, 2017 23:06
Show Gist options
  • Save anonymous/2a329ba84ef05045ee870f4390af97a5 to your computer and use it in GitHub Desktop.
Save anonymous/2a329ba84ef05045ee870f4390af97a5 to your computer and use it in GitHub Desktop.
Sql injection как защититься

Sql injection как защититься - Защита от SQL инъекций на PHP


Sql injection как защититься



Защита от SQL-инъекций
Как защититься от «SQL injection»?
Защита от SQL инъекций
Как защититься от SQL Injection?
Sqlmap: SQL-инъекции — это просто
Форум PHP













Только полноправные пользователи могут оставлять комментарии. TM Feed Хабрахабр Geektimes Тостер Мой круг Фрилансим. Хабрахабр Публикации Пользователи Хабы Компании Песочница. К своему удивлению, я не нашёл на Хабре исчерпывающей статьи на тему защиты от инъекций. Поэтому решил написать свою. Несколько пространный дисклеймер, не имеющий прямого отношения к вопросу Давайте признаем факт: Причём повторение одних и тех же ошибок наводит на мысль, что некоторые заблуждения слишком устойчивы, и требуется не просто перечисление стандартных техник, а подробное объяснение — как они работают и в каких случаях должны применяться а в каких — нет. Статья получилась довольно длинной — в ней собраны результаты исследований за несколько лет — но самую важную информацию я постараюсь компактно изложить в самом начале, а более подробные рассуждения и иллюстрации, а так же различные курьёзы и любопытные факты привести в конце. Также я постараюсь окончательно развеять множественные заблуждения и суеверия, связанные с темой защиты от инъекций. Я не буду пытаться изображать полиглота и писать рекомендации для всех БД и языков разом. Поэтому все практические примеры и рекомендации будут даваться для этих технологий. Тем не менее, изложенные ниже теоретические принципы применимы, разумеется, для любых других языков и СУБД. Сразу отвечу на стандартное замечание про ORM, Active record и прочие query builders: Так что не будем прятать голову в песок и делать вид, что проблемы нет. Хоть я и постарался подробно осветить все нюансы, но, вполне возможно, некоторые из моих выводов могут показаться неочевидными. Я вполне допускаю, что мой контекст и контексты читателей могут различаться. И вещи, которые кажутся мне сами собой разумеющимися, не являются таковыми для некоторых читателей. В этом случае буду рад вопросам и уточнениям, которые помогут мне исправить статью, сделав её более понятной и информативной. Под спойлером результаты тестов, если не лень смотреть. Тестирование IT-систем авторов , 1,1k публикаций. Программирование 2,9k авторов , 6,5k публикаций. JavaScript 1,9k авторов , 4k публикаций. CSS авторов , 1,2k публикаций. IT-стандарты авторов , публикаций. Системное программирование авторов , публикации. HTML автора , публикаций. Разработка веб-сайтов 4,1k авторов , 9,6k публикаций. Совершенный код авторов , публикации. Разработка мобильных приложений 1k авторов , 2,8k публикаций. Добавить в закладки Не соглашусь, что топик хороший, статьи надо писать, чтобы каждый в меру своего понимания мог для себя уяснить суть статьи и вынести что-то полезное, а не от гика для гиков, которые итак это знают. Полезность в этом случае сомнительная. Вы не могли бы привести пример какого-нибудь места, которое может быть неясно? Я старался расписать максимально понятно, но мог и не преуспеть. Но всё поправимо, и я буду рад внести правки, делающие статью более понятной. Проблема коммуникации гик-новичок действительно существует — я даже отметил её во вступлении. Беда в том, что когда новички пишут для новичков — выходит ещё хуже. В общем, если можете указать на конкретные неясности в статья — я был бы благодарен. Я вот сейчас занимаюсь серьёзным проектом и решил всерьёз заняться защитой от инъекций прежде, чем выходить в продакшн. Нагуглилось тысяча всего, но ваша статья оказалась самой исчерпывающей и самой полезной. Не гикам хотелось бы готовых решений. Или прямо ткнуть в них носом, так как по тексту они не очень понятны. Лучше пример класса для работы с БД, которым, например, вы пользуетесь следующая статья не вышла еще? Это особенно актуально для проектов, где БД используется на элементарном уровне, поэтому нет людей, которые в этом отлично бы шарили, а защита все-таки нужна…. На тот момент ещё не вышла, а вот только сегодня: Сравнение с популярными движками есть в этой статье — выше приводятся примеры кода, который нам бы понадобился для PDO и Mysqli. А в новой статье есть примеры того, как это делается в моей библиотеке. А если бы еще привели сравнение с решениями, используемыми в популярных движках или фреймворках, было бы, совсем здорово. Все движки, которые я видел, обрабатывали данные при получении, а в запрос вставляли без особой обработки. Увы, судя по комментариям, так думают, похоже, многие. Похоже, убеждённость в собственном всезнайстве сослужит плохую службу тем, кому эта статья действительно могла бы помочь. Вся надежда остаётся на комментарии по существу, в ответ на которые я могу аргументированно переубеждать заблуждающихся. SQL Injection по сути это проблема недостаточно грамотных или очень ленивых программистов. Правило тут одно — проверять переданные из формы данные на валидность. К сожалению, вы неправы. В статье как раз подробно разбирается — почему. Я думаю, что проблема тут скорее в терминологии, и elve имел в виду то же самое. Но на самом деле его ошибка совсем в другом: Форматирование данных должно определяться не источником, а получателем данных. Смысл городить весь этот огород с плейсхолдерами, если он кушает производительность парсеры, массивы, пересчеты туда-сюда да еще и код усложняет? Потом еще проблемы обучения сотрудников встают, SQL едионообразен и четок в структуре, а тут у каждого свой синтаксис. Признайтесь, вы написали комментарий, не читая статью? На самом деле, всё наоборот — код прикладной значительно упрощается. Правила форматирования SQL кода, увы, совсем не единообразны. К примеру, строковые литералы надо форматировать одним способом, а числовые — совсем другим. В то время как плейсхолдеры, как раз, являются именно таким единообразным способом формирования динамических запросов. Совершенно такой же запрос будет на голом SQL, только в параметрах будут чищенные переменные. При этом он будет кушать меньше ресурсов, так как строка просто соберется используя функции языка, а не самописные функции на php для обработки конструкции. То есть, какой-то код понадобится? По поводу же ресурсов, я приведу аналогию. Но, вроде бы, необходимость использования шаблонизаторов никем не оспаривается, а накладные расходы считаются приемлемой платой за удобство и безопасность. Данные защищенный от возможных иньекций. Почему то мне сейчас вспомнились времена, когда magic quotes ещё не были ересью DEPRECATED в PHP 5. В качестве единственного средства защиты — это так и есть. Подробное объяснение, мне кажется, есть в статье, причём в нескольких местах. Не говоря уже о том, что сама по себе эта функция к защите от инъекций не имеет никакого отношения. Она служит для форматирования строк. Откуда информация о том, что PDO:: Ну, во-первых, из личного опыта, а во-вторых, исходя из принципа построения всех публичных фреймфорков, о котором говорил Расмус на конфе — максимальная перестраховка: А режим эмуляции по определению более совместим. Это отдает непониманием происходящих процессов. Сразу вспоминается анекдот про два jmp подряд, на случай, если первый не сработает. Я так понял, что Вы не знаете, но предполагаете? Ну, я бы не назвал это предположением. У меня есть опыт. Если у вас есть опровержение, я с удовольствием его выслушаю и исправлю статью. Как мне убедиться, что Вы, например, не обманываете меня? Как я могу проверить, что там true? Вы же как-то узнали? Да, прошу прощения, я не написал. Вам стоило привести этот пример в статье. Я на Хабре не раз натыкался на голословные утверждения, особенно касательно PDO, поэтому требую пруфов. Вам стоит поработать над подачей материала — очень тяжело дается Ваша статья. Хорошо было бы составить некий checklist, с которым стоило бы сверять каждую строчку кода. А то вроде бы и знаешь, а память дырявая — вот и пропустишь некоторые проверки. Так чеклист же и состоит всего из двух пунктов? Плейсхолдеры для данных и белый список для всего остального. Вы считаете, что этого недостаточно? А можете привести какую-то конкретную ситуацию, в которой данные рекомендации окажутся неприменимыми или двусмысленными? На конкретных примерах всегда лучше видно проблему. Попытаюсь составить, насколько смогу. Там больше двух, точно. Было бы очень интересно взглянуть. Возможно, речь не о динамической сборке запроса? Дело в том, что плейсхолдеры, как раз, и служат для сокращения чек-листа для этой операции. Разве что тип надо указывать. Но для родных препаредов и это не нужно. Просто в контексте данной публикации речь идет именно о БД, хотя в общем контексте вы правы. Мне всегда не хватало такого конспекта. Как думаете, может, стоит опубликовать это отдельным постом? Мне кажется — да, но рекомендовать не возьмусь. Уж очень непредсказуема реакция хабрасаообщества. Кстати, хороший вариант — посмотреть сначала на оценки комментария! В любом случае, я бы сначала поправил п 1. Чтобы гарантированно безопасно вставить данные в базы — достаточно следовать правилу 1 из статьи плейсхолдеры. В базы — да. В общем случае — вариантов больше. Вообще — давайте остановимся на этом, признав, что говорим о разных вещах, придерживаясь одного мнения: Ну не совсем одного мнения. Фильтрация — вопрос, касающийся предметной области приложения, а не особенностей работы с тем или иным хранилищем. А вообще меня очень интересует — что можно еще в этот список добавить? Какие моменты остались в нем непонятны? Список достаточно сумбурен — писал из головы, что сразу вспомнил. Может, его для более удобоваримого чтения как-то можно реорганизовать? А разве так не будет работать? Нет, в контексте эскейпинга строк — не будет. Я там как раз чуть ниже привёл под спойлером код, который это наглядно демонстрирует. В последнем случае не ругается, возвращает пустой результат. У вас получилась отличная статья. Ни одной глупости не увидел, что в наше время редкость для статей по этой теме. Вообще-то они действительно deprecated. Во-первых, это только предложение из мейл-листа. В том же листе и про выход 6. Текущая версия сейчас — 5. То есть, о таком статусе в настоящем времени говорить можно вряд ли. В-третьих, самая простая проверка показывает нам разницу: В то же время: А вот собственно и ответ. С этим я согласен, но это никак и не противоречит сказанному мной. Deprecated — это совершенно конкретный статус, который выдает конкретную ошибку при соответствующем уровне отображения. Discouraged же — некий неформальный термин, который появился в документации по этому расширению буквально на днях. Но вообще, я имел в виду не терминологию, а скорее тот факт, что расширение mysql на настолько плохо, как его изображают. И основная проблема не в нем самом, а в непонимании и неумении пользоваться. Во всяком случае, с безопасностью при корректном использовании проблем никаких нет. С тем, что сами же разработчики и хоронят, я тоже не спорю — именно это я и написал. Собственно, мне они же сами и ответили в том смысле, что просто никто не хочет заниматься поддержкой этого расширения. Что характерно, никакой другой причины там не написано. Как будто curl — новое. Я понимаю, что по комментариям читать проще, но я же обо всём этом написал: В этом смысле я предпочту старую, но проверенную. PDO — это лишний уровень абстракции, над которым всё равно надо городить свою — получается две. Функционал prepare достаточно спорный. Набор имеющихся placeholder-ов явно недостаточен — то есть, всё равно надо допиливать. Следовательно, парсер всё равно писать — а значит и основные плейсхолдеры реализовать не проблема, даже в mysql ext. Если функционал проверенный, то давайте, конечно, притащим. Не вижу никакой проблемы в проверенном функционале, если честно. Что в нём плохого? Но отказываться от хорошего только по той причине, что он был в 3 и 4 версии — это как-то странно. В принипе, я не защищаю mysql. Но нахожу аргументы запретителей весьма спорными. PDO удобно тем, что для mysql и sqlite пишешь одно и то же. Вы для sqlite что используете? Я привёл в статье два примера ошибок, исправленных совсем недавно. Это означает, во-первых, что столь серьёзные баги всплывают до сих пор, а во-вторых — они мешали массовому использованию а значит — тестированию экстеншена. Что означает довольно большую вероятность появления новых багов в будущем. Да, но curl разработчики не собираются удалить его из PHP one day, в отличие от mysql. Об этом и речь. Но курл никто из языка не выпиливает. Так что если у вас есть ссылка на вменяемое объяснение причин удаления — я был бы благодарен на самом деле. Поскольку, как я уже говорил, я не сторонник этого расширения как такового — я сторонник осмысленных и аргументированных действий вообще. Зашел сюда увидеть картинку из xkcd. Идея типизированных плейсхолдеров — рулез! Сделать у себя, что ли?: И за ссылку на библиотечку Котерова спасибо, не видел. В принципе, это можно попробовать автоматизировать но есть вероятность, что пустые массивы — не всегда ошибка…. Спасибо за поддержку, Давид! А ты правда раньше про dbSimple не слышал? Я-то знал давно, но сначала не понимал всей глубины заложенных в неё принципов, а потом уже стал сам себе учёный и начал своё писать: И я наивно надеялся на свой талант популяризатора. Но, судя по имеющемуся фидбеку, что-то мне подсказывает, что mission failed… Долго чесал репу, откуда я взял про обработку пустого массива в IN оказалось — из англоязычной версии: Котеров вообще велик, но очень уж герметичен, я на многое у него натыкаюсь только по случаю. Если эта строка прошла валидацию согласно правилам предметной области бизнес логики приложения — тогда просто приводить к целому 0 и не париться. Вот буквально в комментариях к предыдущей статье по теме я утверждал, что библиотека для сборки запросов не должна заниматься валидацией данных. Но что-то сейчас гложут меня сомнения. И если, скажем, кастить ли пустую строку в 0 — это ещё вопрос, то hello world, пожалуй или, точнее, несовпадение с "-? Надо посмотреть по коду, но, вроде бы, столь экстремальное приведение типов осознанно нигде не используется. Исключение должно было быть брошено валидатором. Смотря с какой стороны посмотреть. Для меня это абсолютно нелогично. Если array 1 генерирует в итоге IN 1 , а array 1,2 — IN 1, 2 , тогда совершенно логично, что результатом подстановки array всегда будет пустое множество, то есть FALSE. И ведь работает однако! Прям сегодня внесу изменения в либу: В смысле IN FALSE работает, как FALSE. Ну или пустой строкой. Как это связано с моими словами? Запрос вам для размышления: Добавьте к названию статьи что-то типа "… полноценный плейсхолдер". Ну а если статья претендует на звание исчерпывающей, ей лучше быть в какой-нибудь вики, чтобы народ дочерпывал то, что автор забыл зачерпнуть. Как со строками с NULL работать нельзя, потому что: Однако есть нюансы, которые выходят за рамки данной темы. А если писать плэйсхолдеры для баз, поддерживающих больше типов плюс пользовательские, всё будет ещё интереснее! Но это утяжеление синтаксиса, конечно. А какой он — правильный текст? Для вставки это NULL, тут просто. А при сравнении — что? Ну, NULL — он и есть нулл, всегда одинаковый. А что, у тебя для сравнения другие плейсхолдеры? Да, это радует, что в MySQL нет с ним таких заморочек, как, например в Oracle, который пустые строки в нуллы превращает. Во-первых, функция html specialchars , как видно из её названия, имеет отношение к HTML, а не к SQL. И в SQL она не поможет, а только навредит. Так что строки надо обрабатывать специально предназначенными для этого функциями. Во-вторых, с числами тоже могут быть проблемы я о них писал В-третьих, кроме строк и чисел есть и другие элементы запроса. В-четвёртых, самый главный вопрос состоит не в том, какими функциями форматировать части запроса, а кто это будет делать. Если отдавать форматирование данных на откуп программисту, то он когда-нибудь забудет. Поэтому идея состоит в том, что какие бы функции ни использовались — применять их должна программа , а не программист. В этом суть использования плейсхолдеров. Результат будет одним и тем же. Я согласен, что экранировать данные должна программа. Но если она этого не делает, то что уж тут остаётся? А программеру просмотреть такое несколько затруднительно, чес-слово. Да и при использовании самописных обёрток или PDO — сколько потеряется в производительности? Иногда ведь и 1мс нелишне будет…. Я не понимаю вашей приверженности функции htmlspecialchars. Если уж вы хотите руками форматировать строки, то почему не пользоваться специально предназначенной для этого функцией? Функцией, которая не портит данные? А после htmlspecialchars в базе останутся все эти html-сущности, которые там даром не нужны. Опять же, статью вы, судя по всему, не читали. Ваш способ выведет в лог нечитаемую фигню. Экранировать данные нужно в момент вывода и строго определенным форматом вывода методом а ыйл-запросы — это вывод приложения. Безопасность — это побочный эффект экранирования, его основное назначение — сохранение данных в первозданном виде. Для безопасности существует фильтрация. Пользую в проектах один из допиленных вариантов DBSimple Котерова, поверх PDO. Плейсхолдеры и белые списки из коробки идут. В общем то да, верный способ обрубить шаловливому хакеру свободу действий на корню. Понимаю, что несколько в сторону, но глаз зацепился за: А ошибки — это всегда плохо. It depends, на вскидку: Вы не совсем поняли, о чём речь. Задача класса по работе с БД — работать с БД. А не с пользователем. Хотим проверить ввод на валидность — ради бога, ДО любых манипуляций с SQL. Я же говорил об ошибках, возвращаемых сервером БД, при попытке выполнить запрос. Про сообщения об ошибках речи не было. Я говорил о самой ошибке. Которая существует независимо от способа информирования о ней. Метки лучше разделять запятой. Сейчас Вчера Неделя Простая валидация формы без JS 5,2k 8. Первая российская материнская плата массового сегмента 21,8k Интересные публикации Хабрахабр Geektimes. Как я боролся с комарами. Личный опыт и тесты на себе GT. Neuralink — Будущее, которое сложно себе представить. Вы будете его частью GT. Как запутать аналитика — 5. Linux все еще не торт. Почему нет русского Amazon, или где зарыта? Мифы, которые надо закрыть. Китай заблокирует VPN для частных лиц GT. Как пенсионный фонд сливает персональные данные GT. Разделы Публикации Хабы Компании Пользователи Песочница. Информация О сайте Правила Помощь Соглашение Конфиденциальность. Услуги Реклама Тарифы Контент Семинары.


Спортивные магазины ярославль каталог
You ve dealt with it перевод
Входное устройство частотомера своими руками
Почемуу фикуса липкие листьячто делать
Спираль внутриматочная juno gold
Формула женщины инструкция по применению
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment