
Команды безопасности верят, что создать продукт без уязвимостей можно, внедряя различные инструменты и практики вроде SAST, DAST и WAF. Эти практики помогают выявить уязвимости в уже написанном коде и, возможно, предотвратить их эксплуатацию.
Но исправить найденные уязвимости или сделать продукт изначально безопасным могут только те, кто делает этот продукт — сами разработчики. Поэтому важно, чтобы они умели писать безопасный код, а не жаловались на специалистов по безопасности или средства защиты, которые мешают работать.
Меня зовут Артемий Богданов, я всю жизнь занимаюсь практической безопасностью — находил уязвимости в Uber, Yahoo и ВКонтакте, занимал призовые места в конкурсах PHDays, NeoQUEST и других CTF. И сейчас я расскажу, как разработчики, аналитики и тестировщики могут попробовать себя в роли хакеров, чтобы в итоге делать свои продукты безопасными.
Почему разработчики забивают на безопасность
Как рассуждают команды безопасности?
— Если за безопасность продукта отвечают разработчики, значит, нужно научить их практикам безопасной разработки.
Обычный подход к такому обучению — это курсы и, если повезет, какая-то практика.

Но есть несколько причин, по которым такой подход не работает:
Разработчикам неинтересно проходить курсы. Особенно если они скучные и основаны на оторванной от реальности теории. Потому что это отвлекает их от реальных задач, которые они делают каждый день.
Разработчики не доверяют командам безопасности. Потому что обычно они предлагают какой-то трэш или отношения с командой безопасности в принципе не очень хорошие, между ними не налажена связь.
Разработчики могут знать, как правильно, но все равно не делать или делать по-своему. Потому что так быстрее или потому что не считают это важным.
Хакер против разработчика: 5:0
К чему приводит такое «обучение»? Вот небольшой пример, основанный на реальных событиях.
В Bug Bounty крупной компании приходит репорт от пентестера — «белого» хакера, который нашел уязвимость и сообщает о ней.
Пентестер: Ребята, у вас в коде есть XSS-уязвимость.
Разработчик: Гуглим быстрое решение — использовать функцию htmlspecialchars:

Раз это XSS, значит, нужно спецсимволы перевести в HTML-сущности.
Добавил эту функцию, теперь все безопасно, давайте в релиз!
Пентестер: Это не сработает, потому что на самом деле функция htmlspatialcharts не кодирует одинарную кавычку, а здесь значение параметра тега было указано именно в одинарных кавычках.
Разработчик: Окей, добавим специальный флаг, который преобразует одинарную кавычку в HTML-сущность.
Пентестер: Не выйдет, потому что можно использовать псевдопротокол JavaScript, если написать JavaScript и поставить двоеточие.
Разработчик: Понятно, вырежем JavaScript с помощью функции str_replace и заменим все эти вхождения.
Пентестер: Опять нет — хакер может использовать разные регистры для того, чтобы обойти такую защиту.
Разработчик: Задача понятна, решение — использовать регистронезависимую функцию замены. Добавляем одну букву, получается str_ireplace.
Ну что, теперь кажется, что все безопасно? Конечно, нет, здесь все равно осталась проблема. Хакер может воспользоваться забавным трюком и поместить внутрь одного спецслова JavaScript другое.
Когда произойдет замена, и слово вырежется, вы увидите результат. В конечном счете все равно появился валидный payload. В итоге уязвимость все еще не исправлена.

Почему разработчик тратит так много времени на исправление кода, но он не становится безопасным? Потому что не всегда намерения разработчика и специалиста по безопасности совпадают.
Как синхронизировать интересы разработчика и специалиста по безопасности
Давайте разберемся, какие задачи есть у разработки и безопасности.
Что важно разработчику:
выпустить продукт вовремя,
сделать всю нужную функциональность,
написать качественный код.
Качество кода — это то, что делает разработчика счастливым. Для разработчика недопустимо, чтобы на проде была какая-то критичная бага. Ему в этот момент некомфортно, нужно сразу все исправить.
Что важно команде безопасности:
выявить уязвимости,
устранить угрозы,
снизить риски,
обеспечить соответствие требованиям,
сделать так, чтобы код был безопасным.
Чтобы синхронизировать задачи, нужно показать разработчику, что качественный код — это безопасный код:

Когда мы покажем, что намерения разработчика и специалиста по безопасности на самом деле совпадают, у разработчика появится мотивация писать безопасный код. А мотивированные разработчики сами попросят материалы по безопасной разработке, будут их изучать и проследят, чтобы продукт был безопасным.
Для того, чтобы связать качественный и безопасный код, можно обучать разработчиков в игровом формате и пригласить их на CTF. Но есть проблема — стандартный CTF тут не подойдет.
Почему CTF для команд безопасности не подходит для разработчиков
Все хакерские CTF, которые я видел и делал сам, не очень подходят для разработчиков. Задания в них часто синтетические и очень сложные, а связи с реальной работой почти нет.

Вот пример задания из CTF для специалистов по безопасности:

Придет ли такое разработчику в JIRA в реальной жизни разработчику? Вряд ли. Опытному сеньору — не студенту и не хакеру — некогда решать странные шарады.
Как сделать CTF, интересный для разработчиков
Чтобы CTF для разработчиков был интересным и эффективным — помогал писать безопасный код, — нужно соблюсти несколько правил:
CTF должен максимально реалистично имитировать бизнес-логику приложений. Желательно, если приложение будет похожим на тот продукт, который человек разрабатывает в рамках своих стандартных рабочих задач.
Когда мы проводили первый CTF в своей команде, то специально имитировали компанию, которая создает плюс-минус похожие продукты на рынке. Конечно, они были попроще, но тем не менее ребятам было интересно.
Еще можно использовать функциональность, которая всем понятна и известна. Например, это может быть имитация реального интернет-банка.
В CTF должны быть задачи для разработчиков разного уровня. Чтобы джуниоры, мидлы и сеньоры нашли для себя интересные задания и смогли их решить.
Все задания в CTF должны подчиняться общей логике. Классно, если все задания соберутся в общий сюжет, это вызовет дополнительный интерес.
Вот пример CTF для разработчиков, который сделали мы:

CTF имитирует онлайн-банк с обратной связью и всеми стандартными операциями типа различных мультивалютных счетов, карточек, перевода денег по номеру счета и карты.
Участники CTF регистрируют аккаунт в имитированном банке, их задача — все изучить и затем выполнить задания.
Вот пример задания для джунов:

Для поиска и эксплуатации уязвимостей в любой системе очень важно провести подготовительную, исследовательскую работу.
Вы сможете найти этот флаг, если внимательно изучите окружение и исходный код системы, доступные публично или после авторизации.
В этом примере разработчик сам должен увидеть, что ему нужно делать. Единственная подсказка — название задач, они могут навести его на мысли. При этом в основе задачи — реальные проблемы окружения, которые встречаются на каждом первом проекте.
Пример задания для продвинутых разработчиков:
Вы пошли в бар рядом с банком и случайно услышали разговор соседей, из которого поняли, что клиент с номером телефона 89000001001 совершал подозрительные операции в DarkNet.
Разберитесь с этим и выясните детали, чтобы получить флаг.
В основе этой задачи — реальные кейсы утечек и то, как их используют хакеры для взлома самых защищенных приложений.
Какие результаты дает CTF для команд разработки
Мы проводили такой CTF в разных командах, в сумме в нем поучаствовало больше тысячи человек. Вот какие выводы мы сделали:
Обычные разработчики становятся киберчемпионами. Те, кто не хотел участвовать в CTF и даже не думал, что разбирается в безопасности, проникались интересом, получали флаги и занимали призовые места.
Киберчемпионы становятся связующим звеном между безопасностью и остальными членами команды. Разработчики не любят ходить к специалистам по безопасности, потому что они все время мешают им в процессах. После CTF ситуация меняется: разработчики на практике понимают ценность безопасного кода и советуются с опытными коллегами из своих же команд.
Повышается качество внутреннего багбаунти. Разработчики, которые раньше не разбирались в теме, начинают понимать, что такое уязвимости, как их находить, эксплуатировать и закрывать. Они начинают лучше искать уязвимости в ваших внутренних продуктах и сообщать о них.
Улучшается коммуникация между разными командами в компании. Люди, которые разрабатывают абсолютно разные продукты в компании, которые вообще никогда друг друга не видели и не общались, наконец-то начинают взаимодействовать.
Например, в нашем CTF для разработчиков была такая особенность: разработчики могли общаться друг с другом во время различных атак. Вот пример такого общения:

В этом примере один участник CTF атакует другого. Он использует уязвимость, с помощью которой можно украсть деньги. При этом в эксплойте зашифровано приятное поздравление о том, что было забавно вместе проходить этот CTF и соревноваться за первое место.

Что же в этом особенного? Человек, который отправил такой payload знал, что получатель заходит в свой личный аккаунт в банке только через cURL, просто потому что боится, что его взломают и заберут все деньги. Поэтому он отправил такой payload, который показывает поздравление только при открытии через cURL. А если открыть тот же самый payload из браузера, то он просто украдет все ваши деньги, сменит пароль от аккаунта, и вы останетесь ни с чем.
С чего начать подготовку к CTF в своей команде
Может показаться, что организовать CTF для разработчиков сложно. На самом деле это не совсем так. Да, с конкретными заданиями может понадобиться помощь, но общую логику можно проработать уже сейчас.
Что для этого потребуется?
Соберите топ-10 проблем, уязвимостей и ошибок, которые допускают разработчики в актуальных контекстах. По нашему опыту, это могут быть XSS, IDOR, CSRF, работа с зависимостями и уязвимости округления. В больших компаниях могут быть проблемы с валидацией данных, защитой cookie, CSV-инъекциями, CSP и SQL без использования параметризированных запросов.
Посмотрите на систему обучения и курсы, которые вы даете своим разработчикам. Честно ответьте на вопросы: помогает ли это обучение решить топ-10 ваших проблем? Интересны ли эти курсы разработчикам?
Опишите требования для CTF на основе ваших уязвимостей и частых ошибок в безопасности.
Разработайте задания по принципам из пункта «Как придумать интересный CTF для разработчиков». Если не хотите разрабатывать его сами, CTF можно заказать.
Такой CTF заинтересует разработчика больше, чем скучные задачки, и после конкурса он начнет думать, как писать безопасный код на своей работе.

Apoheliy
Подумал, что статья по утечки памяти, статические анализаторы, выстраивание процессов разработки чтобы был безопасный код.
Также, похоже, предложенный подход (ctf) актуален для программирования систем с подключением к внешней сети (как вариант - выходом в интернет) или доступом пользователя к операционной среде (т.е. он, образно, может вставить флешку в usb-порт).
Для случая программирования изолированных систем что-то подобное есть?
Start_X Автор
Что вы имеете в виду под изолированными системами? Если это что-то вроде внутреннего сервиса компании, это значит, что туда входят какие-то данные, преобразовываются и выходят, значит, доступ есть (через web-интерфейс, терминал или ту же флешку), и все указанное выше актуально)
Apoheliy
Интересное предположение.
Сеть изолирована (доступа в интернет - нет). Веба - нет, Серверов - нет. Точнее так: сервера есть, но не являются обязательными: работает как с серверами, так и без серверов (требование по устойчивости). Но веба всё равно нет (даже с серверами).
Данные в основном входят по аналоговым проводам (телефонная лапша), типа fxo, fxs, тч. Также есть синхронные линии, типа E1. Кстати, ещё иногда есть SIP через ethernet. Но тут момент в том, что на всех этих входах нет ни аутентификации, ни авторизации. Т.е. кто смог подключиться - тот легитимный.
И какая возможна атака?: Условный хакер ломает доверенного контрагента и через него влезает в изолированную сеть и подключается к системе по E1 или sip? И пытается что-то ... что (веб серверов - нет)?
Что самое интересное, запрос на безопасный код - он ЕСТЬ! Реально есть! Вот прямо по названию статьи.
Только это всё не про веб.