HTB Response. Бьемся над самой сложной машиной с Hack The Box

Содержание статьи

  • Разведка
  • Сканирование портов
  • Точка входа
  • Точка опоры
  • Продвижение
  • Пользователь bob
  • Пользователь scryh

В этом рай­тапе я покажу, как иссле­довать API сай­та на пред­мет потен­циаль­ных лазе­ек, затем мы напишем собс­твен­ный прок­си‑сер­вер на Python, а потом при­меним XSS для эксфиль­тра­ции дан­ных и про­экс­плу­ати­руем слож­ную уяз­вимость чте­ния про­изволь­ных фай­лов.

Уп­ражнять­ся мы будем на вир­туаль­ной машине Response с пло­щад­ки Hack The Box. Ее уро­вень слож­ности — Insane, и на сегод­няшний день это самая слож­ная машина на HTB и пер­вая в моей серии рай­тапов, которую мне не уда­лось прой­ти до кон­ца. Одна­ко даже получе­ние двух поль­зователь­ских уче­ток ока­залось зах­ватыва­ющим.

warning

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

 

Разведка

 

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

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

10.10.11.163 response.htb

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

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

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

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

#!/bin/bashports=$(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.

Кар­та сай­та

Так находим нес­тандар­тный файл /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.1Host: proxy.response.htbContent-Type: application/jsonContent-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

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

  • Че­рез свой бра­узер обра­щаем­ся к внут­ренне­му сай­ту, ука­зывая IP-адрес написан­ного нами веб‑сер­вера.
  • Наш сер­вер будет кодиро­вать при­нятый зап­рос и отправ­лять на прок­си‑сайт.
  • Пос­ле получе­ния отве­та от прок­си‑сай­та наш самопис­ный сер­вер будет декоди­ровать при­нятые дан­ные и отправ­лять в качес­тве отве­та бра­узе­ру.
  • Так как работать будем с сай­том 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, HTTPServerfrom socketserver import ThreadingMixInclass 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): passws = ThreadedHTTPServer(("0.0.0.0", 80), ProxyServer)print("Server started...")try: ws.serve_forever()except KeyboardInterrupt: passws.server_close()print("Server stopped.")

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

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

    Источник: xakep.ru

    Ответить

    Ваш адрес email не будет опубликован. Обязательные поля помечены *