Марк Митчелл - Программирование для Linux. Профессиональный подход
- Название:Программирование для Linux. Профессиональный подход
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:2002
- Город:Москва
- ISBN:5-8459-0243-6
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Марк Митчелл - Программирование для Linux. Профессиональный подход краткое содержание
Данная книга в основном посвящена программированию в среде GNU/Linux. Авторы применяют обучающий подход, последовательно излагая самые важные концепции и методики использования расширенных возможностей системы GNU/Linux в прикладных программах. Читатели научатся писать программы, к интерфейсу которых привыкли пользователи Linux; освоят такие технологии, как многозадачность, многопотоковое программирование, межзадачное взаимодействие и взаимодействие с аппаратными устройствами; смогут улучшить свои программы, сделав их быстрее, надежнее и безопаснее; поймут особенности системы GNU/Linux, ее ограничения, дополнительные возможности и специфические соглашения.
Книга предназначена для программистов, уже знакомых с языком С и имеющих базовый опыт работы в GNU/Linux.
Программирование для Linux. Профессиональный подход - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Второй аргумент функции — это имя пользователя, которого требуется аутентифицировать. В данном примере имя пользователя берется из переменной среды USER(обычно это имя соответствует эффективному идентификатору текущего процесса, но так бывает не всегда). В большинстве реальных программ в данном месте выдается запрос на ввод имени. Третьим аргументом является ссылка на объект диалога. В четвертом аргументе указывается переменная, в которую функция pam_start()запишет дескриптор сеанса. Этот дескриптор должен передаваться всем последующим функциям библиотеки РАМ.
Далее в программе вызывается функция pam_authenticate(). Во втором ее аргументе указываются различные флаги. Значение 0 означает стандартные установки. Возвращаемое значение функции говорит о том. как прошла аутентификация. В конце программы вызывается функция pam_end(), которая удаляет выделенные ранее структуры данных.
Предположим, что пользователь должен ввести пароль "password". Если это будет сделано, получим следующее:
% ./pam
Password: password
Authentication OK.
Будучи запущенной в терминальном окне, программа не покажет введенный пароль, чтобы кто-нибудь посторонний не смог его подглядеть.
Вот что произойдет, если в систему попробует вломиться хакер:
% ./pam
Password: badguess
Authentication failed!
Полное описание работы модулей аутентификации приведено в каталоге /usr/doc/pam.
10.6. Дополнительные проблемы безопасности
В этой главе мы рассматриваем лишь несколько наиболее общих проблем, связанных с безопасностью. Но существует великое множество других "дыр", и далеко не все из них еще раскрыты. Поэтому в ответственных случаях без помощи экспертов не обойтись.
10.6.1. Переполнение буфера
Почти псе основные Internet-демоны, включая демоны таких программ, как sendmail, finger, talkи др., подвержены атакам типа переполнение буфера. О них следует обязательно помнить при написании программ, которые должны выполняться с правами пользователя root, а также программ, осуществляющих межзадачное взаимодействие или читающих файлы, которые не принадлежат пользователю, запустившему программу.
Суть атаки заключается в том, чтобы заставить программу выполнить код, который она не собиралась выполнять. Типичный механизм достижения этой цели — перезапись части стека программы. В стеке, помимо всего прочего, сохраняется адрес памяти, по которому программа передает управление после завершения текущей функции. Следовательно, если поместить код взлома в памяти, а затем изменить адрес возврата так. чтобы он указывал на этот код, то по завершении текущей функции программа начнет выполнять код хакера с правами текущего процесса. Если процесс принадлежит пользователю root, последствия будут катастрофическими. Если атаке подвергся процесс другого пользователя, катастрофа наступит "только" для него (а также для любого пользователя, который работает с файлами пострадавшего).
Хуже всего обстоит дело с программами, которые работают в режиме демона и ожидают поступление запросов на подключение. Демоны обычно принадлежат пользователю root. Если в программе есть описываемая "дыра", любой, кто сможет подключиться к этой программе, способен захватить контроль над компьютером, послав по сети "смертельную" последовательность данных. Программы, не работающие с сетью, гораздо безопаснее, так как их могут атаковать только пользователи, уже зарегистрировавшиеся в системе.
Старым версиям программ finger, talkи sendmailприсущ один общий недостаток: все они работают со строковым буфером фиксированной длины. Предельный размер строки предполагается по умолчанию, но ничто не мешает сетевым клиентам вводить строки, вызывающие переполнение буфера. В программах содержится примерно такой код, как показан ниже.
#include
int main() {
/* Никто, будучи в здравом уме, не выбирает имя пользователя
длиной более 32 символов. Кроме того, я думаю, что в UNIX
допускаются только 8-символьные имена. Поэтому выделенного
буфера должно быть достаточно. */
char username[32];
/* Предлагаем пользователю ввести свое имя. */
printf("Enter your username: ");
/* Читаем введенную строку. */
gets(username);
/* Выполняем другие действия... */
return 0;
}
Комбинация 32-символьного буфера и функции gets()делает возможным переполнение буфера. Функция gets()читает вводимые данные до тех пор, пока не встретится символ новой строки, после чего помещает весь результат в массив username. В комментариях к программе предполагается, что пользователи выбирают себе короткие имена, не превышающие в длину 32 символа. Но при написании защищенных программ необходимо помнить о существовании хакеров. В данном случае хакер может выбрать сколь угодно длинное имя. Локальные переменные, в частности username, сохраняются в стеке, поэтому выход за пределы массива оборачивается тем, что в стек помещаются произвольные данные.
К счастью, предотвратить переполнение буфера относительно несложно. При чтении строк следует всегда пользоваться функцией наподобие getline(), которая либо динамически выделяет буфер достаточной длины, либо прекращает принимать входные данные, когда буфер оказывается заполнен. Вот вариант выхода из положения:
char* username = getline(NULL, 0, stdin);
Функция getline()автоматически вызывает функцию malloc(), которая выделяет буфер для введенной строки и возвращает указатель на него. Естественно, следует не забыть вызвать функцию free(), чтобы по окончании работы с буфером вернуть память системе.
Ситуация еще проще, если используется язык C++, где есть готовые строковые примитивы. В C++ ввод строки осуществляется так:
string username;
getline(cin, username);
Буфер строки usernameудаляется автоматически, поэтому даже не придется вызывать функцию free().
Проблема переполнения буфера возникает при работе с любыми статическими массивами, а не только со строками. При написании безопасных программ следует тщательно проверять, не осуществляется ли запись в массив за его пределами.
10.6.2. Конкуренция доступа к каталогу /tmp
Другая распространенная проблема безопасности связана с созданием файлов с предсказуемыми именами, в основном в каталоге /tmp. Предположим, что программа prog, выполняющаяся от имени пользователя root, всегда создает временный файл /tmp/progи помещает в него важную информацию. Тогда злоумышленник может заранее создать символическую ссылку /tmp/progна любой другой файл в системе. Когда программа попытается создать временный файл, функция open()завершится успешно, но в действительности вернет дескриптор символической ссылки. Любые данные, записываемые во временный файл, окажутся перенаправленными в файл злоумышленника.
Интервал:
Закладка: