В данной статье нам хотелось бы поделиться своим опытом внедрения нашей команды пентестеров в цикл разработки большого проекта «МойОфис». Найти материал подобной тематики с реальными кейсами на русском языке практически невозможно. Всем, кого интересует модные направления пентестов, теория, практика, методики, тулзы и реально найденные уязвимости в контексте безопасной разработки, — добро пожаловать под кат. Статья изобилует полезными ссылками на теоретические и практические материалы. Но давайте по порядку.
Дисклеймер:
Статья состоит из двух частей. Первая часть — организационная, которая определяет проблему, рассказывает в целом о подходах к тестам на проникновение и о наших путях решения поставленных задач (наверняка содержит информацию, которая многим известна). Вторая — более техническая, с описанием используемых тулзов и найденных уязвимостей.
Если ты, %username%, любишь технические детали, можешь переходить ко второй части.
И, конечно же, не забудь свой чай с печеньками.
Собираем и распределяем
Некоторое представление подходов к пентестам
Начать стоит с небольшого вступления, описывающего подходы к пентестам и их особенности. Основываясь на нашем опыте, охватывающем различные компании разнообразного профиля, оптимальным видится следующее деление.
Разовый тест на проникновение
Классический вариант, при котором какая-либо организация (включая банки и компании государственного сектора) приходит к компании, занимающейся предоставлением услуг тестов на проникновение, и выдает скоуп адресов пентестерам. После проведения работ команда-исполнитель дает рекомендации по исправлению уязвимостей.
Виды работ:
- Аудит безопасности внешнего периметра
- Аудит безопасности внутреннего периметра
- Физическая безопасность
- Мобильные приложения
- Анализ кода
- Социальная инженерия
- И вообще все, что вы сможете придумать (но увлекаться сильно не стоит)
В безопасности, как и в любом сложном процессе, нет “серебряной пули” — никакое средство само по себе не даст полной уверенности в защищенности системы, будь то антивирусное ПО, системы обнаружения вторжений и т.п. То же можно сказать и о тестах на проникновение, в которых нет универсальных подходов, поскольку у каждого из них есть свои минусы и плюсы.
Разовый тест на проникновение эффективен для оценки общего состояния безопасности — пентестеры проводят моделирование ситуации, в которой злоумышленник с ограниченными финансами и в сжатые сроки пытается проникнуть в систему, и какой ущерб он может нанести компании заказчика.
Тест на проникновение с повторением N раз в год
Подход повторяет “единоразовый пентест”, либо его отдельные части. В данном случае аудит защищенности производиться несколько раз в год. Виды работ такие же, как и в первом подходе.
После первого аудита с оценкой общих проблем в безопасности данный подход дает возможность держать себя в курсе применимых исправлений к найденным уязвимостям при прошлых аудитах, появившихся проблем при применении исправлений (да, и такое бывает) и по результатам следующих проверок.
Данный вариант позволяет проводить более тщательное изучение периметра компании аудиторами за счет их повышенной осведомленности о сервисах по результатам прошлых тестов на проникновение.
Багбаунти на аутсорсе
Суть данного подхода — в создании своей багбаунти-программы на открытой/закрытой основе, ведение которой осуществляется силами сторонней организации. Такая команда привлекает к своей работе пентестеров на постоянных условиях и производит выплаты за каждую уязвимость в отдельности. Это хорошая возможность дополнительного дохода для исследователей. Примером использования такого подхода является американская компания SYNACK.
Возникает резонный вопрос: “Чем это отличается от HackerOne?” Основное отличие — в количестве исследователей и их скиллах. Для попадания в программу нужно пройти собеседование и тестовое задание, как при устройстве на работу в оффенсив-компанию. Следовательно, получается меньше участников, но выше общий уровень скиллов (и отсутствие всем известных нам персонажей, которые любят кидать отчеты сканеров).
Виды работ (в рамках данного подхода):
- Аудит безопасности внешнего периметра
- Мобильные приложения
- Бинарные исследования
Подход предполагает постоянное штудирование своих сервисов десятками человеческих “сканеров”, мотивированных вознаграждениями за уязвимости. Он позволяет обеспечить большее покрытие при проведении работ.
Несмотря вышеозначенные преимущества, у подхода есть и свои недостатки:
- Ограниченный спектр работ в сравнении с классическим подходом к пентесту. Этот недостаток является следствием удаленной работы всех исследователей и популярности направлений в безопасности.
- Зависимость результатов работы от выплат. Большое количество исследователей не гарантирует вовлеченность абсолютно каждого, размер вознаграждений оказывает сильное влияние на популярность программы.
- Сложность в планировании бюджета — типичная проблема для любой багбаунти-программы.
Работы по анализу защищенности на постоянной основе
Именно этот подход рассматривается подробно в нашей статье. Суть его — в постоянном исследовании разрабатываемых продуктов от релиза к релизу.
Список видов работ в данном случае несколько шире по сравнению с описанными выше подходами. Он включает в себя:
- Аудит безопасности внешнего периметра
- Аудит безопасности внутреннего периметра
- Мобильные приложения
- Десктопные приложения
- Hardering (безопасная конфигурации серверов)
- Обучение разработчиков
Что касается таких пунктов, как Десктопные приложения и Hardering, то задача не в поиске бинарных уязвимостей (если говорить о десктопах) и не в тотальном закручивании гаек (в случае с Hardering). Главное — это взгляд на систему с пентестерской стороны.
Особенность подхода состоит в том, что он максимально близок к работе безопасников на местах в компаниях, которые создают защиту изнутри, а именно:
- Высокая осведомленность о работе (за счет доступа к документации и собственного эмпирического опыта при исследовании конкретного продукта) и разработке внутренних сервисов (возможность влиять на процесс разработки и непосредственно наблюдать за сроками).
- Доступ к исходным кодам разрабатываемых продуктов.
- Возможность участвовать в построении архитектуры. Это позволяет находить уязвимости до написания кода. Например, CSRF-токены. Иногда бывает, что люди просто забывают о такой важной и простой вещи, как токены. Если данная проблема вскроется после выката релиза, её исправление может стать дорогостоящим и трудоемким делом (хотя все, конечно же, зависит от размера системы).
- Высокая актуальность исследуемых продуктов. При выпуске нового релиза или изменений парочки важных строк кода, влияющих на безопасность напрямую, мы сразу можем получить внесенные изменения и начинаем во всю их тестировать.
В итоге получается, что работы проводятся уже не черным, а всеми нами любимом белым ящиком.
Важно отметить, что данный подход помогает решать и такую проблему, как нехватка собственных ресурсов (секьюрити-специалистов) компании для анализа безопасности приложений. Многие исследователи предпочитают оффенсив-компании для работы из-за наличия постоянного опыта в разных направлениях ИБ, привлечение их на аутсорсе позволяет компенсировать нехватку ресурсов.
Немного про SDLC и его друга SecureSDLC
SDLC
Начнем с определений. SDLC — это основа разработки, которая определяет процесс, используемый организациями для создания приложения с момента зарождения идеи до выхода в эксплуатацию.
На данный момент существует большое количество моделей SDLC, самые известные из них — Waterfall, Iterative, Agile (подробнее о них можно почитать тут). Все они имеют свои достоинства и недостатки, каждая из них весьма вариативна в использовании; все зависит от размера проекта, бюджета, объема человеческих ресурсов и других особенностей. Их всех объединяет наличие шести ключевых этапов:
- Планирование — один из основных шагов, на котором происходит определение решаемой проблемы, подсчет ресурсов и издержек, поиск альтернативных путей решения и т.д.
- Анализ — разработка требований, осуществление технико-экономического обоснования и прочего,
что мы так не любим. - Дизайн. На данном этапе происходит построение архитектуры, выделение компонентов, модулей, интерфейсов и т.п.
- Разработка и внедрение — самый большой и важный этап, именно здесь происходит написание кода, конфигурация и настройка железной части проекта, если таковая существует.
- Тестирование и интеграция — здесь мы проводим проверку того, насколько результаты соответствуют поставленным задачам.
- Поддержка системы. Проведение контроля актуальности разработанной системы. Сюда входит как замена оборудования, так и обновление различных программных компонентов.
SecureSDLC
SecureSDLC — тот же SDLC, но с приставкой Secure. Просто добавляешь приставку, и все становится безопасным (нет). Суть всего этого весьма проста: как видно на прекрасной картинке из Интернета, к каждому из этапов разработки добавляются действия, связанные с безопасностью (расчеты рисков, статический\динамический анализ кода, фаззинг, обучение и т.п.).
В классической реализаций SDLC проверка безопасности ограничивалась стадией тестирования, если вообще проводились.
Расширенная реализация нацелена на:
- Постоянный мониторинг исправления существующих/обнаруженных уязвимостей.
- Уменьшение стоимости исправления уязвимостей благодаря нахождению их на более ранних этапах разработки.
- Повышение качества разработки за счет глубокого анализа приложений; работы в части обучения в области безопасности самих разработчиков.
На чем же всё базируется?
В настоящее время имеется большое количество компаний, практикующих безопасную разработку. Например, такие крупные и известные, как Microsoft, Cisco, Dell. Сегодня любой уважающий себя вендор следит за безопасностью своих решений (но не всегда это получается). Абсолютно у каждого производителя есть свой подход, который формируется, исходя из внутренних особенностей разработки.
В качестве скелета при построении своей безопасной разработки многие используют общепринятые в мире практики:
- Open Security Assurance Maturity Model (OpenSAMM) от OWASP
- Microsoft Security Development Lifecycle (SDL). Process Guidance.
На очередной картинке из Интернета можно увидеть соответствие бизнес-функций и практик безопасности.
Условия задачи
В настоящее время мы ведем большой проект (подробности и особенности — далее), работая по двум большим направлениям: “пентест” разрабатываемых продуктов и бинарные исследования. В данной статье мы сосредоточимся на пентестерской части.
Изначально наш процесс поиска уязвимостей в данном проекте прошел этапы от разового пентеста до пентестов с повторением несколько раз в год — как сервисов внешнего периметра, так и разрабатываемых продуктов. Данные подходы, по нашему мнению, показали себя не так эффективно, в отличие от проектов по анализу защищенности на постоянной основе.
Что же не устроило нас в классических подходах? У разового пентеста есть некоторые недостатки:
- Большое количество отчетности по факту проведения работ. Если вы видели хоть раз пентестерский отчет, то знаете, что он огромен, и занимает в среднем сотню страниц. Его создание требует привлечения человеческих и временных ресурсов. Вместо поиска уязвимости исследователь занимается подготовкой отчетности.
- Недостаточно слаженное взаимодействие с разработчиками. Последние могут начать реагировать на найденные проблемы только после окончания пентеста. При этом у них часто есть понимание критичности найденных уязвимостей и путей их исправления, которое может отличаться от пентестерского.
- Низкая осведомленность пентестеров о внутренних особенностях исследуемых систем. Поскольку исследователь не является сотрудником компании, безопасность которой он анализирует, он не может знать всех особенностей процесса разработки, у него банально отсутствует доступ к документации и к исходникам.
- Ротация аудиторов. Из-за наличия других разовых или постоянных проектов может сложиться такая ситуация, что проектом занимается не тот пентестер, который исследовал его в прошлый раз. Из-за этого падает общая осведомленность о сервисах, которые уже были изучены в рамках прошлого теста на проникновение.
По причине низкой осведомленности аудиторов о внутренних особенностях разрабатываемых продуктов и отсутствия какого-либо разделения по компонентам (для пентестера продукты имеют вид определенного скоупа адресов, пакетов мобильных приложений или бинарей десктопных приложений), список продуктов выглядит как книжная полка с большим количеством книг, на корешках которых отсутствуют названия — глаза разбегаются от обилия сервисов.
Из-за этого появляется проблема выделения времени — оно выделяется на весь проект в целом, и какому-то компоненту может быть уделено меньше внимания. Ресурсы распределяются неэффективно, и это не подходит для глубокого изучения продуктов. Поэтому было принято решение разделять продукты на условные компоненты.
Собираем список продуктов
В нашем случаем мы работаем с компанией «Новые облачные технологии» над их продуктом «МойОфис», который представляет собой платформу совместного редактирования документов, хранения файлов, почтовую систему, мессенджер. Для всего этого существуют как мобильные, так и десктопные версии.
Перед началом работ над таким обширным продуктом, как «МойОфис», необходимо выделить основные его модули и части (даже с виду неделимые), чтобы не получилось той самой книжной полки. Это необходимо и для лучшего понимания внутренних процессов приложений и распределения ресурсов команды.
У нас это получилось таким образом:
- Web — это настоящее SPA приложение, только js/css/html файлы. Сервисы, которые входят в этот компонент: Почта, Календарь, Контакты, Диск, Редактор документов, Панель управления администратора, Logos (мессенджер).
- Мобильные приложения — по три приложения (Редактор Документов, Почтовый Клиент, Logos — мессенджер) под каждую из платформ — iOS, Android, Tizen (да-да, не удивляйтесь).
- Десктопные приложения (Документы, Почта, Мессенджер) под три платформы — Linux, OS X, Windows.
- Серверное API, доступное публично.
- Внутренние сервисы, которые общаются друг с другом (Redis, Swift и другие).
Все это вместе предоставляет большой интерес для исследователя: как возможность изучить какие-то доселе невиданные технологии, так и прокачаться больше в уже изученной теме.
Планирование спринтов
Чтобы “бесшовно” встроиться в процесс разработки такого продукта, нам необходимо адаптироваться к его глобальным циклам планирования, в нашем случае — релизным циклам. Релиз новых версий «МойОфис» происходит каждые три месяца. Поэтому мы живем спринтами как раз по три месяца. Что же такое спринт в нашем понимании?
Спринт для нас — это ячейка времени, в рамках которой мы стараемся максимально распланировать наши работы. Внутри большого спринта у нас есть более мелкая единица измерения — слот, который равен одной неделе. Мы берем продукты, доступные нам, смотрим циклы и сроки изменений в них, и в необходимой последовательности ставим аудиты этих продуктов в график нашего спринта, разбивая по слотам.
Естественно, мы понимаем, что планирование сроков в разработке, мягко говоря, получается очень плохо, потому ожидаем законного вопроса: “А если сроки едут, что делаете?”
Тут на помощь приходит старая игра детства — “пятнашки”. Помните, там была пустая ячейка, через которую можно было двигать другие фишки, и тем самым менять порядок, не выходя за рамки коробки? В нашем случае, коробка — это и есть такой “спринт”.
Количество пустых слотов решено было увеличить, поскольку есть разные “внеплановые” работы, ресерчи сторонних решений, используемых в разрабатываемых продуктах, а также иные работы, которые могут относиться к проекту. Тем самым, мы мобильны в планировании, а пустые слоты заполнить всегда можно.
Пример одного из спринтов (первое число — номер недели спринта):
- Веб-приложения компонентов (Почта, Контакты, Календарь)
- Веб-приложения компонентов (Почта, Контакты, Календарь)
- Нативные мобильные приложения для Android, iOS, Tizen
- Нативные мобильные приложения для Android, iOS, Tizen
- Сервер аутентификации; Бекенд веб-приложений
- Бекенд файлового сервера, Веб-панель и API администратора
- Веб-панель редактора документов, Бекенд редакторов
- Десктопный клиент для файлового сервера
- Десктопный клиента для почты, календаря, контактов, документов
- Мессенджеры для Web, MacOS, Win, Linux и их API
- Misc
- Misc
- Misc
Misc — это как раз те свободные слоты, их наличие очень важно. Как можно заметить, на некоторые, довольно большие части (как Веб, где проверяется и API-часть), мы закладываем больше времени (10 рабочих дней). Также в Misc попадают дополнительные исследования и совместная проработка security-ориентированной архитектуры совместно со специалистами заказчика.
Команда аудиторов
Для такого проекта с нашей стороны было очень важным подобрать команду, которая обладает экспертизой сразу во всех интересующих направлениях (все, безусловно, универсалы, но каждый в чем-то разбирается больше, например, в анализе мобильных приложений). В итоге, получилось три человека, работающих фуллтайм над проектом и находящихся в постоянном контакте с заказчиком.
Исходя из наличия экспертизы у каждого в каком-либо направлении, внутри команды происходит шаринг опыта между аудиторами. Даже при условии ротации аудиторов с другими командами опыт остается внутри, ведь в случае необходимости заменяется только один человек. “Новичок” в течении недели узнает организационные особенности работы и по истечении первого спринта приобретает полную картину и понимание взаимодействия большого количества компонентов друг с другом.
Стенды
В своих тестах мы используем полную копию того, что поставляется клиентам, со всеми свежайшими обновлениями. Забегая вперед, скажем, что мы посчитали довольно важным развернуть полностью весь «МойОфис» с нуля и понять каждый шаг, где, что и как деплоится и настраивается, попутно пытаясь сравнить это с документацией. Учитывая, что наша специализация — далеко не системное администрирование, это была сложная задача для “падавана юного”.
Отчетность
Поскольку мы — большие любители багбаунти и такие же не любители писать отчеты и генерировать официальные тексты, было решено отойти от отчетности, присущей классическим тестам на проникновение, и перенять опыт у багбаунти-программ.
В своем подходе мы используем JIRA для создания тикетов (разработчики и тестировщики пользуются этим, почему бы нам тоже не начать это делать), где есть абсолютно стандартные поля, как на HackerOne:
- Название
- Тип тикета
- Критичность уязвимости
- В каких компонентах проявляется
- Описание уязвимости — действия для повторения
При таком донесении информации абсолютно любой человек поймет, насколько эта уязвимость критична, даже без какой-либо квалификации в безопасности или вообще в IT.
Анализ защищенности. Немножко практики
Дисклеймер: мы стараемся делать статьи так, чтобы из статьи каждый смог вынести для себя что-то новое и интересное. Так, из первой части менеджер или тимлид команды может наверняка почерпнуть тактику ведения проектов, тогда как из второй кое-что может пригодится исследователям ИБ и разработчикам.
Выглядит так, что вводная часть раскрыта. Давайте перейдем непосредственно к самому анализу защищенности (ура-ура, технические подробности).
Одна из интересных составляющих работы для опытного пентестера — это использование модных и современных технологий. Давайте посмотрим на них. Прежде чем начать, мы, конечно же, посмотрели Веб, попутно регистрируясь с именами:
‘“><svg onload=alert(1)>{{7*7}}
Позаливали файлы, поотправляли почту, поставили мобильные приложения и в целом осмотрелись вокруг, как все работает.
После мы пошли к тимлидам разработки и вместе засели над схемой серверной архитектуры на большом листе А1, который с трудом умещается на стене кабинета. Сюда мы ее не вставим, но в целом все довольно стандартно и круто:
- Пользователю доступны два порта (80 и 443). Все, что за ними, считается кластером и доверенной зоной.
- Кластер — это может быть неограниченное количество серверных машин (в нашей инсталляции — 2), на которых работает целый пучок микросервисов (java, go, c++ — ядерная часть редактора, базы данных, SWIFT и другие).
- Часть сервисов ставится из RPM-пакетов, часть — docker-контейнеры (что дает дополнительную изоляцию, это особенно важно при работе с конвертацией документов).
Web
Клиентская часть — это AngularJS и полноценное SPA без явных костылей со стороны серверного API (таких как “а вот тут отдадим формочку с бекенда!”).
Серверная часть — по-разному, в качестве фронта используется nginx, за ним множество java/golang сервисов, которые обрабатывают клиентские запросы.
Анализировать SPA-приложения очень круто и довольно удобно, с точки зрения запросов-ответов все логично и складно. Поиск уязвимостей в самом SPA, конечно же, довольно сложная задача.
Burp Suite
Да, тут нет секрета, мы, как и многие, используем Burp (никакого Larry Lau, только лицензия) и его модули для поиска разного рода уязвимостей (инъекции, IDOR, SSTI и другие). Без этого инструмента вообще никак.
Также его могут применять разработчики, чтобы проверить результат после исправления уязвимости, вместо того, чтобы просить нас и растягивать весь этот процесс. Для этого будет достаточно бесплатной версии и двух вкладок Proxy и Repeater.
Также мы используем пучок кастомных скриптов, рассмотрим один из них.
Как вы уже знаете, среди продуктов, исследуемых нами, есть почта. Одной из мощнейших атак здесь может быть XSS в письмах. Причем все еще осложняется тем, что в письмах можно использовать HTML для создания красивых писем в фирменных стилях, а не просто plaintext. Перед разработчиком стоит задача сделать возможность использования HTML так, чтобы отправитель не мог внедрить свой JavaScript.
В security-мире есть исследователь Mario Heiderich @0x6D6172696F (.mario), который много времени посвятил поиску XSS в разных крупных сервисах вроде Google, участвовал в создании библиотеки DOMPurify для безопасной подстановки unsafe html сразу в DOM (подробнее о ней будет рассказано ниже). А главное — он опубликовал для нее автотесты, которые используют различные хитрости и тонкости работы браузеров и HTML5. Идеальное решение для тестирования почтового сервиса на возможность внедрения JS.
> Ссылка на демо и тесты
> И не забудьте о специальных векторах для HTML5
Что мы сделали? Мы взяли эти тесты (+ дописали некоторые свои из секретных закромов) и отослали на IMAP-сервер своим скриптом на Python в десять строчек, ибо обычно HTML нельзя отправлять из Веб-клиента, а только напрямую на почтовый сервер, попутно открывая письма в браузере. Исполнился JS? Заводим тикет.
Наверняка все знают, что можно обнаружить открытие письма пользователем с помощью картинки (тег img) в письме, но и другие теги могут позволить нам это сделать. Тут нам опять поможет репозиторий Cure53. С его помощью можно обнаружить теги, которые сливают информацию о пользователях.
Ограничение схем для некоторых тегов, например, почему нельзя использовать file:/// для тех же "img src" (подробно по ссылке от ValdikSS), были сразу учтены при разработке.
Следующая проблема — это вложения. Обязательно нужно тестировать вложения разных форматов с XSS-нагрузкой, их можно взять тут. Этим мы проверим, как сервер хранит и отдает вложенные файлы в письмах.
Мобильные приложения
Все приложения под каждую из платформ являются классическими нативными приложениями.
Для исследования iOS и Android используются оба подхода: автоматизированный и ручной. Для Tizen — только ручной. Про автоматизированный — в снятии “низко висящих фруктов” здесь очень помогает MobSF.
Он позволяет автоматически собрать типичные проблемы, сделать ревью ресиверов, сервисов и т.п. вещей в Android и даже осуществляет некоторое подобие анализа исходного кода (после декомпиляции). Также проверяет флаги (Stack smashing protection, PIE ...) при компиляции.
Ручной анализ — Android (+root), iOS + jailbreak (на данный момент мы используем последний доступный джейл для iOS 9.3.3).
А вот с Tizen не все так просто. Сам он очень странный и непривычный. Система является одним большим браузером с поддержкой HTML5, давно находится в разработке и тоже представляет интерес для исследователей безопасности, как что-то новое и неизученное.
Для начала вопрос — сколько вы вообще держали телефонов c TizenOS? Вот столько же статей и security-тулз для этой платформы. Мы пошли по developer way — скачали Tizen SDK, подключились к телефону и дебажили приложение. В этом режиме можно просмотреть файловую систему, получить debug console и делать другие вещи, позволяющие найти проблемы в безопасности. К сожалению, функционал достаточно ограничен, и нет прямого консольного доступа к OS.
Инструмент находится на официальном сайте Tizen. Можно использовать эмулятор, если есть желание познакомиться с этой операционной системой.
Сама платформа Tizen на данный момент имеет большое количество недостатков со стороны безопасности. Можно вспомнить недавнюю новость о сорока зеродеях в платформе и вот эту публикацию. Также о некоторых уязвимостях в SmartTV, где был затронут и TizenOS, рассказывал BeLove — презентация.
Desktop
Про десктопные приложения «МойОфис» будет отдельная статья, посвященная бинарному фаззингу. В рамках же данных работ (именно в пентестах) смотрятся такие области, как взаимодействие с файловой системой (временные папки, права на них и т.п.), DLL hijacking, работа с сетью (передача данных по защищенным каналам — TLS), хранение токенов и подобное.
Многие десктопные приложения написаны на основе Electron, на котором созданы решения GitHub, Slack, Discord и многие другие. Сам Electron является открытым проектом и представляет собой webview, то есть небольшой браузер, который визуально не отличить от нативного приложения.
Исследование сторонних продуктов. DOMPurify и причем тут Safari
Зачастую при исследовании безопасности какого-либо продукта возникает проблема, связанная с тем, что не всегда прозрачно и понятно, где же в итоге была найдена уязвимость: в кастомном написанном коде заказчика или в стороннем продукте, библиотеках, фреймворках, которые используются при разработке. У нас также был такой случай.
При исследовании одного из компонентов нами была найдена довольно критичная уязвимость клиентской части — внедрение JS-кода, ну или просто XSS. Изначально было непонятно, почему так произошло, ведь данный компонент использовал ту самую JS библиотеку DOMPurify для защиты от XSS.
DOMPurify — это средство только для DOM-а, сверхбыстрое, убер-толерантное XSS-дезинфицирующее решение для HTML, MathML и SVG (немножко описания с Гита). MathML — это язык разметки на основе XML для представления математических символов и формул. Все это, конечно, работает и в контексте HTML5 фишек. То есть в этом продукте собрано все самое новое и современное.
Он написан на JavaScript и работает во всех популярных браузерах:
- Safari
- Opera (15+)
- Internet Explorer (10+)
- Firefox
- Chrome
- Все, что использует Blink or WebKit
Разрабатывает инструмент компания Cure53, в частности, Mario Heiderich @0x6D6172696F (.mario), а контрибьютят туда такие известные ребята, как @filedescriptor, @shafigullin и другие. Выходит, такая сборная самых крутых исследователей веб-безопасности трудится над открытым программным средством для защиты от уязвимостей клиентской стороны.
Ссылочка на Гит.
Немного пораскинув мозгами, мы пришли к выводу, что уязвимость действительно не в разработанном приложении, а в подключенной JS-библиотеке.
Далее, мы проверили уязвимость на последней версии DOMPurify и были весьма удивлены, что такой простой пейлоад без всяких хитростей сработал, но только под Safari.
Payload: <svg onload=alert(document.domain)>
Ребята быстро исправили уязвимость, а компания FastMail, которая взяла DOMPurify под крыло своей багбаунти-программы, выплатила нам немножко денег “на пиво”.
Но на этом все не закончилось, поскольку дыра работала только для Safari, мы немного копнули в его сторону и получилось, что функция DOMParser работает некорректно, и при парсинге html страницы исполняет JS, что никакой браузер из популярных не делает (да-да, даже IE), о чем мы сообщили в Apple.
Payload: new DOMParser().parseFromString('<svg onload=alert(document.domain)>', 'text/html');
И буквально на днях Apple выдало CVE-2017-7038 — что-то очень похожее на UXSS-уязвимость, но без обхода SOP. Подробнее обо всех возможных уязвимых функциях, возможно, мы когда-нибудь опишем в отдельной статье.
В итоге, получилась такая нетривиальная схема: XSS в приложении «МойОфис» была возможна из-за подключения DOMPurify-библиотеки, которая не обрабатывала SVG теги (хотя должна была), а отдавала напрямую стандартной браузерной функции DOMParser, которая была реализована с ошибкой.
Вот таким длинным путем мы исправили уязвимость не только у нашего клиента, но и сделали мир немного безопаснее.
Реальные уязвимости
Невозможно написать что-то большое и не допустить ни одной баги, нет такой методологии. Поэтому разберем парочку реальных уязвимостей с высоким уровнем критичности.
Внедрение внешних сущностей XML
Поскольку у нас есть хранение и редактирование документов, мы каким-то образом должны отрисовывать пользователю документ и вносить изменения в них, если это нужно. Как вы можете знать, современные офисные документы — это набор XML-файлов, упакованных в архив. А какое редактирование документов без парсера XML?
Каждый Веб-ресерчер сразу же подумает про XXE. Как же посмотреть эту уязвимость в действии в данном случае?
- Загружаем документ
- Сервер распаковывает архив
- Пытается преобразовать XML во внутренний формат
- Сохраняет в нужном себе формате на сервере
Вот как раз шаг номер три является опасным, осуществляется он с помощью опенсорсной библиотеки, в которой можно было подключать внешние сущности. Что мы сделали:
- Создали валидный .docx документ
- Распаковали
- В один из xml файлов добавили
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
…
<foo>&xxe;</foo>
- Запаковали обратно, переименовали в .docx
- Загрузили на сервер
И после обработки увидели содержимое /etc/passwd. Но с помощью этой уязвимости можно не только читать файлы на сервере.
Так или иначе, нам не удалось ничего важного прочитать, поскольку весь парсинг происходит в изолированном контейнере (docker). Уязвимость была оперативно закрыта.
Кстати, для генерации подобных файлов и проверки XXE можно использовать тулзу. С её помощью некоторые исследователи находили XXE и в багбаунти-программах тоже.
Remote Command Execution via EL Injection
Расскажем и про честное RCE — удаленное выполнение команд OS на сервере. Некоторая часть микросервисов написана на Java, в том числе, с применением Spring. Уязвимости такого рода (EL Injection) для Spring (и не только) очень хорошо поддаются фаззингу, если вы отправите на сервер {{7*7}}, то в ответе на странице получите выполнение математической функции равное 49.
Далее, можно уже пробовать выполнять функции языка и даже запустить команду с помощью:
${T(java.lang.Runtime).getRuntime().exec("ls")}
Подробнее про похожую уязвимость в Spring Boot Oauth модуле можно прочитать тут. А тут тикет на гите, описывающий проблему, которая повлекла выполнение кода в нашем случае.
Но в нашей конкретной ситуации такая простая отправка пейлоада не работала, поскольку при отправке запроса на Веб-сервер наши кавычки проходили URL-encode и не воспринимались Spring-ом как спецсимволы. Что же делать в такой ситуации? Все достаточно просто: можно, используя стандартные средства языка, провести кодировку из числовых значений в символы с помощью функции java.lang.Character.toString() и конкатенировать все символы. Про данный трюк можно прочитать тут.
В итоге, у нас получился большой и страшный пейлоад (чтение /etc/passwd/):
${T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(99).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(112)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(100))).getInputStream())}
Стоит отметить, что RCE было также внутри docker-контейнера, и хоть он создан не для защиты, но все же дает некую изоляцию.
Заключение
Уф, вот и подошла к концу статья. Давайте теперь суммируем, чем отличается наш подход от классических тестов на проникновение:
- Аудиторы больше знают о процессе разработки и работе продукта. Осведомленность достигается за счет доступа к документации и возможности следить за темпами разработки.
- Возможность участвовать в построении архитектуры, что позволяет находить проблемы и уязвимости на стадии планирования.
- Доступ к исходным кодам.
- Смещение работ от черного ящика к белому ящику. Классические тесты обычно сильно ограничены в этом плане.
- Ликвидация проблемы генерации больших отчетов.
- Грамотное распределение ресурсов аудиторов. Все расписано по неделям, время используется эффективно, и всегда в проекте участвуют люди, осведомленные о внутренних особенностях компонентов.
- Повышение уровня экспертизы за счет исследования большого количества разнообразных сервисов.
- Наличие возможности искать уязвимости в сторонних продуктах, которые используются в разработке, и делать мир “чище и приятней” .
- Более подробное изучение системы. За счет перехода от поверхностного сбора “низко висящих фруктов” к исследованию каждого компонента в отдельности, следовательно, возможно осуществлять поиск более сложных уязвимостей.
Каждый подход следует улучшать и для полноты картины можно расширять команду узконаправленными специалистами, добавлять больше активных действий с разработчиками и заниматься их обучением в области безопасности.
Конечно же, такой подход также не дает стопроцентной уверенности в безопасности продуктов, но он более методичный и обширный, чем классические тесты на проникновение. Он максимально направлен на оперативное реагирование, на выпуск нового кода и ликвидацию уязвимостей на как можно более раннем этапе.
Надеемся, что вы смогли вынести для себя что-то новое и приобрели понимание того, как происходит работа по поиску уязвимостей в крупных проектах.
Полезные ссылки
- 7 основных методик разработки.
- Open Security Assurance Maturity Model (OpenSAMM) от OWASP.
- Microsoft Security Development Lifecycle (SDL). Process Guidance.
- DOMPurify.
- XSS-векторы и демо DOMPurify.
- XSS-векторы для HTML5.
- Трекинг пользователей через различные HTML-теги.
- Файлы с XSS векторами для вложений.
- Деанонимизация пользователей Windows через схему file.
- Тулза для автоматической проверки мобильных приложений на уязвимости.
- Инструментарий разработчика Tizen.
- Пост о 40 зеродеях в Tizen.
- Публикация про ошибки Tizen OS.
- Уязвимости SmartTV.
- Уязвимость внедрения внешних сущностей.
- Тулза для автоматической генерации файлов c XXE векторами.
- Spring Boot RCE.
- Spring Boot RCE Tricks.
P.S. Выражаю благодарность за помощь в подготовке материала BeLove.
Комментарии (6)
BonBonSlick
03.08.2017 00:10Годно, хотя многое непонятно)
GShikari
03.08.2017 00:11Можете подробнее сказать, что непонятно? Я в следующих статьях постараюсь учесть.
BonBonSlick
03.08.2017 09:31+1Много новых слов во второй части, и пару в первой. Для понимания что происходит и общей картинки, пришлось почитать в гугле еще кусочки. А в целом статья хорошая, спасибо.
Примеры новых терминов для меня, как для того кто провел 0 пентестов:
Burp Suite, Larry Lau, IDOR, SSTI, Tizen, MobSF, jailbreak, XXE, EL Injection, RCE.
Большая часть ссылок есть в статье.GShikari
03.08.2017 11:51+2Добавил всякого рода аннотация к сокращениям, чтобы было понятно, что именно искать)
g0rd1as
Гигантскую работу, однако, проделали! Статью сохраняю в закладки и буду регулярно перечитывать.