Сосредоточьтесь на SQL-инъекциях, PHP и проекте Diwa

Я всегда хотел быть хакером. Уже 6 лет я пишу приложения на Php, JavaScript и Python. Во время учебы преподаватели говорили о SQL-инъекциях и о том, как их предотвратить. Но я никогда не проводил таких атак, как SQL Injection, Broken Authentication или Cross-Site Scripting. Это была недостающая часть моих знаний, и я искал возможность узнать о них больше. Поэтому, когда кто-то из моей команды недавно пришел ко мне и предложил провести исследование, я был самым счастливым человеком на Земле.

У этого поста будет продолжение. Это только начало того, как я взламываю сеть, узнаю о нарушениях безопасности и получаю массу удовольствия. В этом посте я расскажу об особом типе инъекций: SQL-инъекциях. Я расскажу об истории, объясню все тонкости, проведу атаки и расскажу, как вы можете защитить свои приложения. Мы будем использовать Php и MySQL. Если вы используете другой язык программирования, не расстраивайтесь: будет больше контента.

Теперь наденьте капюшон и запустите свой любимый плейлист электронной музыки, и давайте начнем взламывать!

Как работают SQL-инъекции

Прежде чем говорить о SQL-инъекциях, давайте сначала поговорим об инъекциях. Инъекции — одна из самых старых и наиболее распространенных атак. Инъекционные атаки — это вредоносный код, внедряемый в сеть с целью извлечения информации из баз данных. Они нацелены на веб-приложения (не только приложения Php) и могут привести к краже или потере данных. В худшем случае они могут поставить под угрозу всю вашу систему: вы больше не сможете войти в систему и получить доступ к своим службам. Другими словами, это плохо. Я имею в виду действительно очень плохо. Представьте, что вы управляете больницей, у вас есть сотни пациентов, ожидающих операции, и вы записываете их коды безопасности, адреса электронной почты и другую конфиденциальную информацию. Инъекции могут заблокировать всю вашу систему, а хакеры могут получить, продать и использовать эту информацию. Существуют различные категории инъекций, такие как SQL-инъекции, межсайтовые сценарии или CRLF-инъекции. Эта статья посвящена SQL-инъекциям.

Как происходят инъекционные атаки?

Что ж, основная причина — недостаточная проверка пользовательского ввода. Другими словами, это означает, что ваш код небезопасен со стороны разработчика и ваши запросы небезопасны. Если вы хотите их исправить, вам нужно прекратить использовать динамические запросы и защищать свой код при выполнении запроса. Вот почему мы используем подготовленные запросы в Php, потому что они защищают нас от SQL-инъекций.

Приведенный выше код взят из проекта Diwa и находится в файле model.php. Посмотрите на строку 16, здесь брешь в системе безопасности. Эта строка кода выполняет следующую инструкцию в SQL:

'SELECT * FROM users WHERE email = ‘$email’ AND password = ‘$password’;'

Цель этой строки — проверить, существует ли пользователь в базе данных, и, если это так, вернуть его. Внутри формы злоумышленник может написать 'OR '1'='1'' , это выполнит следующий запрос:

'SELECT * FROM users WHERE email = ‘$email’ AND password = ‘$password’ OR ‘`1’ = ‘1’’;'

Это допустимый оператор SQL, и поскольку '1'='1' `'1' = '1'` всегда истинно, запрос вернет все строки из таблицы пользователей. Если вы сделаете это внутри проекта Diwa, вы войдете в систему как администратор (мы сделаем это через мгновение). Но вы можете сделать больше, вы можете удалить таблицу и даже выполнить DoS-атаку (отказ в обслуживании), если таблица пользователей большая и содержит миллионы строк. Например, вы можете добавить [email protected]'; DROP TABLE users; . Он выполнит следующий код:

'SELECT * FROM users WHERE email = [email protected]'; DROP TABLE users;

Почему это работает? Потому что вы заканчиваете первый оператор SQL и сразу после него добавляете еще один. Да, я знаю, сумасшедший.

Как вы предотвращаете SQL-инъекции в Php?

Это одно практическое правило: всегда проверяйте ввод пользователя. Большинство ваших пользователей не хотят взламывать ваш сайт, в Интернете нет хакеров. Однако никогда не следует создавать операторы SQL непосредственно на основе пользовательского ввода. Есть два метода, которые вы можете использовать:

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

К счастью, большинство фреймворков Php, таких как Symfony и Laravel, используют подготовленные запросы для вас, и когда вы делаете простые запросы, вы будете использовать ORM, например Doctrine, и это будет более безопасно. Проблемы возникают, когда вы пишете необработанные запросы.

Намеренно небезопасное веб-приложение как пример

В Интернете есть множество проектов, если вы хотите узнать больше о безопасности. К счастью, на веб-сайте OWASP есть список. Там вы найдете примеры на многих разных языках программирования. По нескольким причинам я решил начать с Php и проекта Diwa:

  • Проект использует Docker и работает нестандартно. Вы клонируете его из GitHub, создаете образ докера, запускаете контейнер, и вы готовы к работе.
  • Это также просто понять. Вскоре мы рассмотрим более сложные проекты, но всегда лучше начинать с простых проектов, особенно при изучении чего-то нового.
  • Diwa написана на Php, и, как правило, это язык программирования, используемый многими. Я здесь не для того, чтобы говорить вам, плох ли Php или нет. Однако я могу сказать вам, что Php используется на 78,9% всех веб-сайтов. Это факты.
  • Изначально проект использует SQLite, но вместо этого я хотел использовать MySQL. Мне было очень просто отредактировать конфигурацию и добавить docker-compose и MySQL.

Давайте начнем с локальной сборки проекта, прежде чем смотреть на внесенные мной изменения. Сделайте копию .env.example и назовите ее .env. Внутри ничего добавлять не нужно: мы воспользуемся этим в другом посте.

$ docker-compose build

Начните с выполнения следующей команды. Он создаст образ Php и установит библиотеки, включая pdo и pdo_mysql.

$ docker-compose up

Затем запустите свои контейнеры. Эта команда создает три контейнера: приложение Diwa, datadog-agent (сегодня нет необходимости смотреть на него) и базу данных MySQL. После того, как все изображения будут загружены, перейдите по адресу http://localhost:8080.

Нажмите «Настроить Diwa!» кнопка: создает таблицы базы данных и добавляет содержимое внутрь. Поздравляем, Diwa теперь работает!

Прежде чем мы приступим к атакам на Diwa, вы должны знать, что я внес несколько изменений в исходный код проекта.

Я обновил файл config.php, чтобы использовать MySQL вместо SQLite. Я также добавил библиотеки pdo внутри контейнера app. Они находятся внутри Dockerfile.

Я также исправил опечатку в строке 10, заменив $config['database']['host'] на $config['database']['server']$.
Давайте взломаем наш проект!

Время взламывать и выполнять SQL-инъекции

Во-первых, если это не так, запустите проект с помощью docker-compose с docker-compose build и docker-compose up. Посмотрите на поля ввода "Адрес электронной почты"
и "Пароль" в верхней части экрана.

Начните с нажатия на кнопку «Регистрация» и создайте учетную запись. Код приглашения: 3702. Вы можете найти его в файле config.php.

Теперь вы должны войти в систему. Если нет, значит, что-то пошло не так при начальной загрузке проекта. Предлагаю задать свои вопросы в разделе комментариев. Теперь вы можете выйти из системы и вернуться на главную страницу. Попробуйте написать неверные учетные данные и посмотрите, что произойдет. Вы должны увидеть следующее сообщение об ошибке: "Неправильный адрес электронной почты или пароль". Теперь я хочу, чтобы вы написали '-- в поле ввода электронной почты и несколько случайных символов в поле пароля.

У вас должна быть хорошая ошибка 500. Это означает, что с сервером случилось что-то плохое, что-то настолько плохое, что сервер выдает ошибку. Это также означает, что он говорит нам, что, возможно, этот веб-сайт небезопасен. Теперь мы попробуем несколько атак с хорошей шпаргалкой, которую я нашел. Посмотрите раздел «Обход экранов входа» и попробуйте написать некоторые из них. Например, следующие команды вызывают ошибку: admin'-- , 'admin'/* или 1=1-- . Этот 'or 1=1#' зарегистрирует вас как администратора. В зависимости от установленной базы данных некоторые команды будут меняться. Но здесь, чтобы быть простым, вы сначала закрываете первую часть запроса с помощью `'` и вводите всегда верную проверку. Вы также можете написать '1=1; внутри журнала, и это сработает.

И да, вы сможете просматривать список пользователей и выполнять различные действия, такие как редактирование их учетных данных, повышение роли пользователей в качестве администраторов и даже удаление их учетных записей.

Теперь мы можем взломать страницу ведения журнала, например, удалить некоторые таблицы, пользовательские таблицы. Я уже знаю кое-что, чего злоумышленник не узнает: я знаю, что таблицы имеют префикс diwa. Например, таблица пользователей diwa_users. Это хорошая практика при создании таблиц: не называйте их просто users или products. Попробуйте добавить префикс, например your-project_table , это сделает ваше приложение более безопасным. Ранее я просил вас создать учетную запись. Вот где мы собираемся его использовать. Я хочу, чтобы вы запросили свой адрес электронной почты и пароль, но перед подтверждением добавьте следующее после своего адреса электронной почты: 'DROP TABLE diwa_users; . Это должно выглядеть так. Теперь сделайте глубокий вдох и нажмите Enter.

Посмотрите на скриншот ниже. Я удалил таблицу diwa_users, больше не могу войти и зарегистрироваться.

И если вы посмотрите на базу данных, diwa_tables уже нет. Страшно, да?

Сбросьте базу данных и заново создайте учетную запись. Теперь мы собираемся перевести базу данных в спящий режим. Вместо добавления DROP TABLE добавьте AND sleep(20); в конце входа в систему и нажмите Enter. Вы заметили, что ваш запрос занимает гораздо больше времени, чем следовало бы? Это происходит потому, что выполняется команда «sleep». Имея это в виду, теперь вы должны попытаться создать бесконечный цикл и заставить базу данных попотеть! Вы можете добавить наш ответ в разделе комментариев, я скажу вам, если вы на правильном пути!

Догонять

Я очень надеюсь, что вам понравится этот контент SQL Injections. Теперь вы должны знать основы того, как выполнять атаки и предотвращать их. В настоящее время я пишу учебник о том, как настроить инструмент наблюдения, чтобы получать оповещения, когда происходят атаки. Особая благодарность Tim Steufmehl за создание этого проекта и Tambi Gumbo за отзыв.

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

Хорошего дня, народ!