Категория > Новости > HTB Response. Бьемся над самой сложной машиной с Hack The Box - «Новости»

HTB Response. Бьемся над самой сложной машиной с Hack The Box - «Новости»


11-02-2023, 00:00. Автор: Нинель
Hack The Box. Ее уро­вень слож­ности — Insane, и на сегод­няшний день это самая слож­ная машина на HTB и пер­вая в моей серии рай­тапов, которую мне не уда­лось прой­ти до кон­ца. Одна­ко даже получе­ние двух поль­зователь­ских уче­ток ока­залось зах­ватыва­ющим.

warning


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



 

Разведка


 

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


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


10.10.11.163 response.htb

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



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


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


На­ибо­лее извес­тный инс­тру­мент для ска­ниро­вания — это Nmap. Улуч­шить резуль­таты его работы ты можешь при помощи сле­дующе­го скрип­та:


ports=$(nmap -p- --min-rate=500 $1 | grep^[0-9] | cut -d '/' -f 1 | tr 'n' ',' | sed s/,$//)nmap -p$ports -A $1

Он дей­ству­ет в два эта­па. На пер­вом про­изво­дит­ся обыч­ное быс­трое ска­ниро­вание, на вто­ром — более тща­тель­ное ска­ниро­вание, с исполь­зовани­ем име­ющих­ся скрип­тов (опция -A).



Ре­зуль­тат работы скрип­та

Мы наш­ли все­го два откры­тых пор­та: 22 — служ­ба OpenSSH 8.2p1 и 80 — веб‑сер­вер Nginx 1.21.6. С SSH ничего не сде­лать, поэто­му сра­зу перехо­дим к вебу.


Глав­ная стра­ница сай­та response.htb

На сай­те находим упо­мина­ние домена www.response.htb, поэто­му обновля­ем запись в фай­ле /etc/hosts:


10.10.11.163 response.htb www.response.htb

Что­бы рас­ширить область тес­тирова­ния, сос­тавим кар­ту сай­та с помощью Burp Discovery. Для это­го в Burp History выбира­ем целевой адрес и в кон­текс­тном меню Engagement tools → Discover content.


HTB Response. Бьемся над самой сложной машиной с Hack The Box - «Новости»
Кар­та сай­та

Так находим нес­тандар­тный файл /status/main.js.php.


 

Точка входа


Ко­пиру­ем содер­жимое фай­ла /status/main.js.php на локаль­ную машину и изу­чаем. Этот файл содер­жит дан­ные для обра­щения к домену api.response.htb через сайт на домене proxy.response.htb.


Со­дер­жимое фай­ла main.js.php

Так как обра­щение про­исхо­дит к под­домену proxy, добав­ляем в /etc/hosts толь­ко его.


10.10.11.163 response.htb www.response.htb proxy.response.htb

За­тем копиру­ем дан­ные для обра­щения и пов­торя­ем зап­рос.


POST /fetch HTTP/1.1
Host: proxy.response.htb
Content-Type: application/json
Content-Length: 262
{"url":"http://api.response.htb/","url_digest":"cab532f75001ed2cc94ada92183d2160319a328e67001a9215956a5dbf10c545","method":"GET","session":"6c2a752c873e8c03fc927a81647402d0","session_digest":"6ce5cbd27651561e9005287bc5d8cf3201aa6c4fe885057ae80b40af0b8951bd"}
Зап­рос и ответ сер­вера

От­вет от сер­вера закоди­рован в Base64, декоди­ровать мож­но пря­мо в Burp Inspector.


Burp Inspector

Так как даль­ше дан­ные пред­став­лены в фор­мате JSON, мож­но кра­сиво отоб­разить их при помощи ути­литы jq.


По­лучен­ные с сер­вера дан­ные

Прос­мотрим так­же стра­ницы /get_chat_status и /get_servers.


Об­ращение к стра­нице /get_chat_status
От­вет сер­вера
Об­ращение к стра­нице /get_servers
От­вет сер­вера

Рас­кры­ваем еще один сер­вис — chat.response.htb. Добав­ляем его в файл /etc/hosts и прос­матри­ваем ответ сер­вера.


10.10.11.163 response.htb www.response.htb proxy.response.htb chat.response.htb
От­вет сер­вера

Сайт ока­зал­ся недос­тупен. Но мож­но обра­тить­ся к нему через сайт proxy. Прав­да, для это­го нам нуж­но под­твер­дить параметр url под­писью в парамет­ре url_digest, который сами вычис­лить мы не можем. Но параметр session, где переда­ется иден­тифика­тор веб‑сес­сии, тоже под­твержда­ется под­писью session_digest.


Зап­рос /status/main.js.php

Тог­да про­буем вмес­то иден­тифика­тора сес­сии отпра­вить ссыл­ку, что­бы получить под­пись для нее.


По­луче­ние под­писи URL

Как видишь, мы узна­ем дей­стви­тель­ную под­пись URL, отправ­ленно­го вмес­то иден­тифика­тора сес­сии.


 

Точка опоры


Те­перь про­верим, при­дет ли нам ответ, если мы поп­робу­ем обра­тить­ся к чату. Пер­вым делом сге­нери­руем для url дей­стви­тель­ный url_digest.


По­луче­ние зна­чения url_digest

С под­писью мож­но выпол­нить зап­рос к прок­си‑сай­ту.


По­луче­ние содер­жимого стра­ницы chat.response.htb

Спо­соб получе­ния под­писи ока­зал­ся рабочим. Но как бы я ни пытал­ся эксфиль­тро­вать дан­ные, все рав­но при­шел к тому, что нуж­но писать свой прок­сиру­ющий веб‑сер­вер. Работать он будет так:



  1. Че­рез свой бра­узер обра­щаем­ся к внут­ренне­му сай­ту, ука­зывая IP-адрес написан­ного нами веб‑сер­вера.

  2. Наш сер­вер будет кодиро­вать при­нятый зап­рос и отправ­лять на прок­си‑сайт.

  3. Пос­ле получе­ния отве­та от прок­си‑сай­та наш самопис­ный сер­вер будет декоди­ровать при­нятые дан­ные и отправ­лять в качес­тве отве­та бра­узе­ру.


Так как работать будем с сай­том http://chat.response.htb, сде­лаем запись в файл /etc/hosts:


127.0.0.1 chat.response.htb

Сна­чала напишем оснас­тку веб‑сер­вера без вся­ких фун­кций. В клас­се сер­вера ProxyServer реали­зуем обра­бот­чики do_GET и do_POST, которые будут вызывать еди­ный метод do_Multi. Спер­ва прос­то будем выводить URL, к которо­му обра­тит­ся бра­узер.


from http.server import BaseHTTPRequestHandler, HTTPServer
from socketserver import ThreadingMixIn
class ProxyServer(BaseHTTPRequestHandler):
def do_GET(self):
self.do_Multi('GET')
def do_POST(self):
self.do_Multi('POST')
def do_Multi(self, method):
uri = self.path
target_url = 'http://chat.response.htb' + uri
print(method + " " + target_url)
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
pass
ws = ThreadedHTTPServer(("0.0.0.0", 80), ProxyServer)
print("Server started...")
try:
ws.serve_forever()
except KeyboardInterrupt:
pass
ws.server_close()
print("Server stopped.")

За­пус­каем сер­вер и обра­щаем­ся к http://chat.response.htb/.


Ло­ги сер­вера

Перейти обратно к новости