[Информационная безопасность, Open source, Программирование, SQL] 8 лучших практик предотвращения SQL-инъекций (перевод)
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
SQL-инъекции считаются одной из наиболее опасных уязвимостей в онлайн-приложениях. Именно поэтому о них должен знать буквально каждый работающий с базами данных специалист, а статей об SQL-инъекциях как таковых очень и очень много. К старту курса "Этичный хакер" мы решили поделиться именно этой статьёй, потому что она не только предлагает памятку по инъекциям, но и знакомит с платформой snyk.io — сканером на уязвимости, который для проектов с открытым исходным кодом можно использовать совершенно бесплатно, а значит, он будет полезен для пет-проектов многих разработчиков и читателей Хабра. По этой причине публикация попала и в хаб Программирование.Существуют различные типыатакс использованием SQL-инъекций, но, как правило, все они имеют схожую причину. Происходит конкатенация (добавление) ненадёжных данных, введённых пользователем, к строке запроса. В результате введённые пользователем данные могут изменить само первоначальное назначение данного запроса.Например, SQL-инъекции могут быть такими:
- добавление к фразе where булева оператора, который делает это условие всегда выполняющимся ' OR 1=1;
- удаление части запроса путём ввода строчных комментариев --;
- завершение исходного запроса и запуск нового запроса '; DROP TABLE USERS;
- соединение данных из нескольких таблиц с помощью оператора UNION.
В этой памятке я подробно рассмотрю 8 оптимальных методов, которые можно применять в любом приложении в целях предотвращенияатак через SQL-инъекции. Итак, давайте начнём и сделаем ваше приложение действительно защищённым от SQL-инъекций.
Загрузить памятку
- Не полагайтесь на проверку вводимых данных на стороне клиента.
- Ограничивайте полномочия пользователя базы данных.
- Используйте предварительно подготовленные опраторы и параметризацию запросов.
- Сканируйте код, чтобы обнаружить уязвимость к SQL-инъекциям
- Используйте слой ORM.
- Не полагайтесь на чёрные списки.
- Выполняйте проверку вводимых пользователем данных.
- С осторожностью используйте хранимые процедуры.
1. Не полагайтесь на проверку вводимых данных на стороне клиентаПроверка вводимых данных на стороне клиента может быть очень полезна. Благодаря ей можно предотвратить отправку в систему недопустимых данных. Однако, к сожалению, такая проверка хорошо работает только для пользователей, не имеющих злого умысла, которые намерены использовать систему строго по её прямому назначению. Выдача пользователю мгновенной подсказки о недопустимости конкретного значения — это очень полезная возможность, делающая систему более удобной для пользователей. Поэтому использование проверок вводимых данных на стороне клиента рекомендуется для повышения качества работы клиентов.Но применительно к SQL-инъекциям это не тот метод защиты, на который действительно можно положиться. Проверку вводимых данных на стороне клиента легко можно отключить, изменив некоторый код javascript, загруженный в ваш браузер. Кроме того, в архитектуре клиент-сервер очень легко выполнить простейший HTTP-вызов серверного приложения, используя в нём параметр, вызывающий SQL-инъекцию. Также это можно сделать, используя различные инструментальные средства, такие как postman, или старые добрые команды curl.Следует выполнять проверку на серверной стороне желательно как можно ближе к источнику данных. В рассматриваемом случае — там, где вы создаёте SQL-запрос. Все данные, передаваемые со стороны клиента, должны рассматриваться как потенциально опасные. Ввиду вышеизложенного возлагать надежды на проверку вводимых данных на стороне клиента в целях защиты от SQL-инъекций — плохая идея.2. Ограничивайте полномочия пользователя базы данныхКак уже было упомянуто, существует несколько типов атак с использованием SQL-инъекций. Некоторые из них более опасны, чем другие. Представьте, к примеру, что мой SQL-запрос имеет вид "SELECT * FROM USER WHERE USERID = '" + userid +"'". Инъекция " foo' OR '1'='1 " предоставит доступ ко всем пользователям, и это само по себе очень опасно. Однако инъекция " '; UPDATE message SET password = 'EVIL” приведет к ещё большим проблемам, поскольку злоумышленник в этом случае изменит все записи.Создавая пользователя в базе данных для вашего приложения, вы должны подумать о его полномочиях. Действительно ли приложению необходима возможность считывать, записывать и обновлять все базы данных? Должны ли быть у него полномочия для выполнения команд truncate и drop в отношении таблиц? Если вы сами ограничите полномочия своего приложения при работе с базой данных, то таким образом можно снизить и потенциальный вред от SQL-инъекций. Наверное, правильным будет создание для приложения нескольких пользователей базы данных и назначение им определённых ролей. Проблемы с безопасностью, как правило, вызывают эффект цепной реакции, поэтому необходимо контролировать все звенья вашей цепи, чтобы предотвратить тяжёлые последствия.3. Используйте предварительно подготовленные операторы и параметризацию запросовВо многих языках программирования специально предусмотрены функциональные возможности, помогающие предотвратить SQL-инъекции. При создании SQL-запросов вы можете использовать заранее подготовленные операторы SQL для компоновки своих запросов. Применение подготовленного оператора позволяет выполнить параметризацию запроса. Параметризация запросов — это особая техника, позволяющая формировать выполняемые операторы SQL динамически. Вы создаёте базовый вопрос с определёнными плейсхолдерами (метками-заполнителями), а затем безопасно прикрепляете переданные пользователем параметры к этим плейсхолдерам.Используя действительно подготовленный оператор и параметризованные запросы, вы заставляете саму базу данных заботиться об экранировании. Прежде всего на основе строки запроса с плейсхолдерами в ней создаётся план выполнения этого запроса. На втором шаге в базу данных передаются «ненадёжные» параметры. Но, поскольку план выполнения уже создан, эти параметры ни на что повлиять уже не могут. Это также предотвращает возможность инъекций.Пример на Java:
String query = "SELECT * FROM USERS WHERE username LIKE ?";
PreparedStatement statement = connection.prepareStatement(query);
statement.setString(1, parameter);
ResultSet result = statement.executeQuery();
Пример на Python с коннектором MySQL:
cursor = conn.cursor(prepared=True)
params = ("foo",)
cursor.execute("SELECT * FROM USERS WHERE username = %s", params)
Пример на JavaScript с mysql2:
connection.query("SELECT * FROM USERS WHERE username = ?",[
req.body.username
],function(error, results){});
//emulates a prepared statement
//OR
connection.execute("SELECT * FROM USERS WHERE username = ?",[
req.body.username
],function(error, results){});
//prepared statement
Тем не менее существует несколько способов сделать это в JavaScript при использовании, например, базы данных MySQL. Учитывайте, что при использовании функции .query() подготовленный оператор не выполняется. В этом случае подстановка параметров осуществляется на стороне клиента, то есть происходит эмуляция подготовленного оператора. Чтобы сделать настоящий подготовленный запрос к базе данных, следует использовать функцию .execute().4. Сканируйте код, чтобы обнаружить уязвимость к SQL-инъекциямПисать собственный код совсем не сложно. Но при этом нередко случаются ошибки. Для проверки кода у вас могут быть предусмотрены такие процессы, как ревью кода и парное программирование. Но является ли тот, кто проверяет ваш код или программирует в паре с вами, также и специалистом в вопросах безопасности? Сможет ли он заметить в коде ошибку, опасную с точки зрения SQL-инъекций? В любом случае будет полезно автоматически проверять собственный код на предмет потенциальных угроз безопасности, таких как SQL-инъекции.Используя такой инструмент SAST (технология статического тестирование безопасности приложений), какSnyk Code, вы можете автоматически проверять свой код и обнаруживать в нём угрозы безопасности, включая SQL-инъекции. Этот процесс можно легко автоматизировать в SDLC, например, подключив к Snyk ваш Git-репозиторий.5. Используйте слой ORMТакже необходимо рассмотреть возможность использования уровня объектно-реляционного отображения (ORM). Слой ORM преобразует данные из базы данных в объекты, а также выполняет обратное преобразование. Применение библиотеки ORM уменьшает количество явных SQL-запросов, а значит, делает приложение менее уязвимым к SQL-инъекциям.Одним из ярких примеров использования библиотек ORM является применение решений Hibernate для Java и Entity Framework для C#. Эти языки строго типизированы, а значит, в них есть возможность устанавливать соответствие между объектами и таблицами в базах данных. Таким образом, у вас есть возможность полностью отказаться от самостоятельного формирования каких-либо SQL-запросов.Тем не менее проблема всё равно возникнет, если потребуется написать свои собственные запросы. В библиотеке Hibernate для Java предусмотрен даже собственный язык написания запросов HQL (Hibernate Query Language). При создании запросов на HQL опять же нужно помнить о возможных инъекциях и использовать функцию createQuery(), которая работает аналогично подготовленным операторам.Для языка JavaScript также существуют хорошо известные библиотеки ORM, такие как sequelize. С помощью sequelize вы сможете определить, как значения будут отображаться в определённые типы в базе данных. Но давайте смотреть правде в глаза, в конечном счёте любой библиотеке ORM требуется преобразование её внутренних логических команд в операторы SQL. Мы верим, что в библиотеках экранирование параметров реализовано правильно.Чтобы быть уверенным, что в вашей библиотеке ORM нет проблем с SQL-инъекциями, необходимо выполнить её сканирование с целью выявления известных уязвимостей. Работа с некорректной, устаревшей версией библиотекsequelize илиhibernate может стать причиной больших проблем. ИспользуяSnyk Open Source для проверки своего проекта, вы сможете защититься от скрытых SQL-инъекций в применяемых библиотеках, а также от многих других потенциальных угроз.Использование Snyk совершенно бесплатноВы можете сразу приступать к работе со Snyk Open Source. Всё, что для этого нужно, — пройти регистрацию на получение бесплатного аккаунта.6. Не полагайтесь на чёрные спискиУверен, эта ситуация хорошо знакома большинству читателей, но я всё равно повторюсь. Пожалуйста, никогда не применяйте чёрные списки для используемых вами параметров. Подход с применением таких списков задаёт набор правил, определяющих уязвимые входные данные. В случае соответствия вводимых данных этим правилам запрос блокируется. Но если правила проверки окажутся недостаточно жёсткими, то введённые злоумышленником данные всё равно сработают. А если они, наоборот, будут слишком ограничивающими, то будет заблокирован ввод допустимых данных.Например, мы можем блокировать все запросы, где содержится слово OR. Возможно, в этом даже есть какой-то смысл, но на практике оказывается, что Or — это очень часто встречающееся в Израиле имя. И это означает, что множество моих коллег будут блокироваться при попытке ввода своих имён. То же самое справедливо для одиночных кавычек '. Этот символ содержится в огромном количестве имён. Подумайте о пользователях с фамилиями O’Neill и O’Donnell. А ведь есть ещё и имена, такие как Dont’a.7. Выполняйте проверку вводимых данныхДа, вы всегда, обязательно должны выполнять проверку вводимых данных! Хотя предварительно подготовленные операторы с параметризацией запросов и являются лучшей защитой против SQL-инъекций, всегда создавайте несколько уровней защиты. Подобно выдаче ограниченных полномочий пользователю базы данных, проверка ввода — это великолепный способ снизить потенциальные риски для вашего приложения в целом.Также возможны такие ситуации, когда использование предварительно подготовленных операторов оказывается невозможным. Некоторые языки программирования могут не поддерживать этот механизм, а некоторые устаревшие системы баз данных могут не поддерживать ввод данных пользователями в качестве параметров. В таких случаях проверка вводимых данных становится приемлемой альтернативой.Обязательно убедитесь, что проверка вводимых данных выполняется на основе белых списков, а не чёрных, как уже описывалось выше. Создайте правило, описывающее все разрешённые шаблоны, например с помощью регулярного выражения. Можно также использовать для этого хорошо поддерживаемую библиотеку. Используйте это правило в сочетании с предварительно подготовленными операторами с параметризацией запросов и вы обеспечите надежную защиту.8. С осторожностью используйте хранимые процедурыМногие верят, что работа с хранимыми процедурами — это хороший способ защититься от SQL-инъекций. Но это не всегда так. Подобно SQL-запросам, созданным в вашем приложении, хранимые процедуры также подвержены инъекциям со стороны злоумышленников.И, так же как и в случае с SQL-запросами, вам следует использовать в хранимой процедуре параметризованные запросы вместо добавления параметров. SQL-инъекции в хранимой процедуре достаточно легко предотвратить. Но не пытайтесь сделать это в MySQL:
DELIMITER //
CREATE PROCEDURE `FindUsers`(
IN Username VARCHAR(50)
)
BEGIN
SET @Statement = CONCAT('SELECT * FROM User WHERE username = ', Username, ' );
PREPARE stm FROM @Statement;
EXECUTE stm;
END //
DELIMITER ;
Вместо этого лучше используйте в своих хранимых процедурах параметризованные запросы:
DELIMITER //
CREATE PROCEDURE `First`(
IN Username VARCHAR(50)
)
BEGIN
PREPARE stm FROM 'SELECT * FROM User WHERE username = ?';
EXECUTE stm USING Username;
END //
DELIMITER ;
Как показано выше, к хранимым процедурам применяются те же правила, что и к коду приложения. Способы применения хранимых процедур различаются в зависимости от используемой базы данных. Убедитесь, что вы хорошо представляете себе, как хранимые процедуры реализуются в используемой вами базе, и также будьте бдительны в отношении возможных инъекций. Хоть я и уверен, что лучше всего убрать всю логику внутрь вашего приложения, но хранимые процедуры также могут быть разумным решением, если используемый вами язык программирования не поддерживает работу с предварительно подготовленными операторами.
Узнайте, как прокачаться и в других специальностях или освоить их с нуля:
Другие профессии и курсыПРОФЕССИИ
- Профессия Fullstack-разработчик на Python
- Профессия Java-разработчик
- Профессия QA-инженер на JAVA
- Профессия Frontend-разработчик
- Профессия Этичный хакер
- Профессия C++ разработчик
- Профессия Разработчик игр на Unity
- Профессия Веб-разработчик
- Профессия iOS-разработчик с нуля
- Профессия Android-разработчик с нуля
КУРСЫ
- Курс по Machine Learning
- Курс "Machine Learning и Deep Learning"
- Курс "Математика для Data Science"
- Курс "Математика и Machine Learning для Data Science"
- Курс "Python для веб-разработки"
- Курс "Алгоритмы и структуры данных"
- Курс по аналитике данных
- Курс по DevOps
===========
Источник:
habr.com
===========
===========
Автор оригинала: Brian Vermeer
===========Похожие новости:
- [Информационная безопасность, История IT, Научно-популярное] Как ИТ перестали быть скучными (перевод)
- [Программирование, Машинное обучение] Автоматизация машинного обучения
- [JavaScript, Программирование, Node.JS] RESTful backend приложение. Базовый шаблон
- [Ненормальное программирование, *nix, C, Разработка под Linux] Внутренности Linux: как /proc/self/mem пишет в недоступную для записи память (перевод)
- [Open source, Софт, Умный дом] Google запускает ОС Fuchsia
- [Информационная безопасность, Виртуализация, Облачные сервисы] VMware предупредила о критических уязвимостях в удаленном исполнении кода в vCenter
- [Информационная безопасность] Threat Intelligence по полочкам: культура обмена данными
- [Python, Программирование, SQL, Микросервисы, Flask] Чтобы первый блин не вышел комом. Советы начинающему разработчику сервиса
- [Информационная безопасность, Облачные вычисления] Колумбийский университет в Нью-Йорке заявил о разработке «устойчивой к взлому» системы облачного ПО
- [Open source, Экология, IT-компании] Microsoft, GitHub, Accenture и ThoughtWorks при поддержке Linux Foundation основали Фонд экологичного ПО
Теги для поиска: #_informatsionnaja_bezopasnost (Информационная безопасность), #_open_source, #_programmirovanie (Программирование), #_sql, #_skillfactory, #_programmirovanie (программирование), #_proverka_koda (проверка кода), #_sql, #_snyk, #_inektsii (инъекции), #_shpargalka (шпаргалка), #_pamjatka (памятка), #_revju_koda (ревью кода), #_informatsionnaja_bezopasnost (информационная безопасность), #_blog_kompanii_skillfactory (
Блог компании SkillFactory
), #_informatsionnaja_bezopasnost (
Информационная безопасность
), #_open_source, #_programmirovanie (
Программирование
), #_sql
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 10:46
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
SQL-инъекции считаются одной из наиболее опасных уязвимостей в онлайн-приложениях. Именно поэтому о них должен знать буквально каждый работающий с базами данных специалист, а статей об SQL-инъекциях как таковых очень и очень много. К старту курса "Этичный хакер" мы решили поделиться именно этой статьёй, потому что она не только предлагает памятку по инъекциям, но и знакомит с платформой snyk.io — сканером на уязвимости, который для проектов с открытым исходным кодом можно использовать совершенно бесплатно, а значит, он будет полезен для пет-проектов многих разработчиков и читателей Хабра. По этой причине публикация попала и в хаб Программирование.Существуют различные типыатакс использованием SQL-инъекций, но, как правило, все они имеют схожую причину. Происходит конкатенация (добавление) ненадёжных данных, введённых пользователем, к строке запроса. В результате введённые пользователем данные могут изменить само первоначальное назначение данного запроса.Например, SQL-инъекции могут быть такими:
Загрузить памятку
String query = "SELECT * FROM USERS WHERE username LIKE ?";
PreparedStatement statement = connection.prepareStatement(query); statement.setString(1, parameter); ResultSet result = statement.executeQuery(); cursor = conn.cursor(prepared=True)
params = ("foo",) cursor.execute("SELECT * FROM USERS WHERE username = %s", params) connection.query("SELECT * FROM USERS WHERE username = ?",[
req.body.username ],function(error, results){}); //emulates a prepared statement //OR connection.execute("SELECT * FROM USERS WHERE username = ?",[ req.body.username ],function(error, results){}); //prepared statement DELIMITER //
CREATE PROCEDURE `FindUsers`( IN Username VARCHAR(50) ) BEGIN SET @Statement = CONCAT('SELECT * FROM User WHERE username = ', Username, ' ); PREPARE stm FROM @Statement; EXECUTE stm; END // DELIMITER ; DELIMITER //
CREATE PROCEDURE `First`( IN Username VARCHAR(50) ) BEGIN PREPARE stm FROM 'SELECT * FROM User WHERE username = ?'; EXECUTE stm USING Username; END // DELIMITER ; Узнайте, как прокачаться и в других специальностях или освоить их с нуля: Другие профессии и курсыПРОФЕССИИ
=========== Источник: habr.com =========== =========== Автор оригинала: Brian Vermeer ===========Похожие новости:
Блог компании SkillFactory ), #_informatsionnaja_bezopasnost ( Информационная безопасность ), #_open_source, #_programmirovanie ( Программирование ), #_sql |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 10:46
Часовой пояс: UTC + 5