Разрабатывать безопасный код сложно. Если бы это было легко, нам не приходилось бы постоянно исправлять и обновлять программное обеспечение. Уязвимости появляются в исходном коде по двум основным причинам:
• Низкое качество кода или наличие ошибок, которыми могут воспользоваться злоумышленники.
• Высокая сложность функционала создает возможности для его незапланированного использования.
В зависимости от языка программирования низкое качество кода влияет на продукт по-разному. В языках, которые требуют от разработчика ручного управления памятью, риск атак с использованием переполнения буфера выше, чем в языках с автоматическим управлением памятью. Другой пример – печально известные «SQL-инъекции», когда один оператор SQL может быть преобразован в несколько операторов путем подстановки в него специально подобранного значения.
Рассмотрим сайт, на котором есть функция поиска и пользователь может ввести произвольный поисковый запрос. Код, выполняющий соответствующий запрос к базе данных, может выглядеть следующим образом:
stmt = "SELECT id, email FROM table X WHERE name='" + inputFromUser + "'";
Выглядит безобидно, не правда ли? Однако, если посмотреть внимательнее, видно, что разработчик создал огромную дыру в безопасности, которая позволяет взломать или удалить всю базу данных. Каким же образом?
Что, если в поле ввода на сайте вместо слова noah ввести "2'; TRUNC X; " и отправить этот запрос в API? В результате будет собрана строка, содержащая две отдельных команды SQL, которые будут выполняться одна за другой (при условии, что библиотека для работы СУБД разрешает это, а в большинстве случаев она разрешает). Первая команда SQL выберет записи, в которых поле «имя» имеет значение 2; это не вызовет никаких проблем. Однако вторая команда, "TRUNC X", удалит все строки таблицы X. После некоторого количества проб и ошибок злоумышленник может устроить хаос в вашей базе данных.
Подумайте только: взломщику даже не нужен какой-либо доступ к сети или к базе данных – он всего лишь использует средства, предоставленные ему самой компанией и включающие удобный интерфейс для выполнения его хакерских SQL запросов.
На заре существования веб-сайтов такие атаки были обычным делом, и многие из них оставались незамеченными. И хотя подобные уязвимости теперь встречаются нечасто, разработчики все еще пишут неграмотный код, особенно те из них, кто недостаточно обучен принципам безопасной разработки и тому, что все данные, поступающие снаружи, необходимо проверять. И это только один пример. Разработка безопасного и безошибочного кода – отдельная дисциплина, и ей посвящено множество книг.
Вы можете снизить риски, обучая свою команду программистов, внедряя стандарты разработки и проводя внимательное ревью кода. Инструменты контроля качества кода (такие как SonarQube) могут выявлять некоторые типовые проблемы и постоянно совершенствуются, но никогда не заменят взгляд опытного человека.
Заметки с полей
Взлом Log4j, конец 2021 г.
В современном мире, где все переплетено и взаимосвязано, сочетание функций разных систем может создать уязвимости даже без явных ошибок разработчиков, и ничто не иллюстрирует эту проблему лучше, чем история с популярной библиотекой журналирования Log4j. Компания Tenable, специализирующаяся на кибербезопасности, назвала ее «самой большой и самой критичной уязвимостью за последнее десятилетие». Сторонний пользователь мог запустить на уязвимых машинах произвольный код путем простой записи в журнал специально сформированной строки; так работала библиотека, которая фиксировала в журналах поисковые запросы, пользовательский ввод или сообщения из чата. И этот функционал был заложен в нее разработчиками, но никто не подумал, что ее будут использовать для обработки небезопасных строк – вот непредвиденные последствия лучших намерений.
Подобные побочные эффекты возможны в любой системе, которая допускает расширение с помощью сторонних плагинов. Яркий пример – веб-браузеры, в которых плагины или дополнения обеспечивают более широкие возможности для пользователей. Однако это означает постоянное перетягивание каната между возможностями и безопасностью, потому что каждое изменение системы плагинов создает новые возможности для обхода ограничений.