Команды безопасности верят, что создать продукт без уязвимостей можно, внедряя различные инструменты и практики вроде 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 для хакеров: все красиво, что-то ломают, ничего не понятно. Источник: PHDays
Типичный CTF для хакеров: все красиво, что-то ломают, ничего не понятно. Источник: PHDays

Вот пример задания из 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 для разработчиков сложно. На самом деле это не совсем так. Да, с конкретными заданиями может понадобиться помощь, но общую логику можно проработать уже сейчас. 

Что для этого потребуется? 

  1. Соберите топ-10 проблем, уязвимостей и ошибок, которые допускают разработчики в актуальных контекстах. По нашему опыту, это могут быть XSS, IDOR, CSRF, работа с зависимостями и уязвимости округления. В больших компаниях могут быть проблемы с валидацией данных, защитой cookie, CSV-инъекциями, CSP и SQL без использования параметризированных запросов. 

  2. Посмотрите на систему обучения и курсы, которые вы даете своим разработчикам. Честно ответьте на вопросы: помогает ли это обучение решить топ-10 ваших проблем? Интересны ли эти курсы разработчикам? 

  3. Опишите требования для CTF на основе ваших уязвимостей и частых ошибок в безопасности.

  4. Разработайте задания по принципам из пункта «Как придумать интересный CTF для разработчиков». Если не хотите разрабатывать его сами, CTF можно заказать. 

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

Комментарии (3)


  1. Apoheliy
    18.09.2023 14:27
    +2

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

    Также, похоже, предложенный подход (ctf) актуален для программирования систем с подключением к внешней сети (как вариант - выходом в интернет) или доступом пользователя к операционной среде (т.е. он, образно, может вставить флешку в usb-порт).

    Для случая программирования изолированных систем что-то подобное есть?


    1. Start_X Автор
      18.09.2023 14:27

      Что вы имеете в виду под изолированными системами? Если это что-то вроде внутреннего сервиса компании, это значит, что туда входят какие-то данные, преобразовываются и выходят, значит, доступ есть (через web-интерфейс, терминал или ту же флешку), и все указанное выше актуально)


      1. Apoheliy
        18.09.2023 14:27

        Интересное предположение.

        Сеть изолирована (доступа в интернет - нет). Веба - нет, Серверов - нет. Точнее так: сервера есть, но не являются обязательными: работает как с серверами, так и без серверов (требование по устойчивости). Но веба всё равно нет (даже с серверами).

        Данные в основном входят по аналоговым проводам (телефонная лапша), типа fxo, fxs, тч. Также есть синхронные линии, типа E1. Кстати, ещё иногда есть SIP через ethernet. Но тут момент в том, что на всех этих входах нет ни аутентификации, ни авторизации. Т.е. кто смог подключиться - тот легитимный.

        И какая возможна атака?: Условный хакер ломает доверенного контрагента и через него влезает в изолированную сеть и подключается к системе по E1 или sip? И пытается что-то ... что (веб серверов - нет)?

        Что самое интересное, запрос на безопасный код - он ЕСТЬ! Реально есть! Вот прямо по названию статьи.

        Только это всё не про веб.