10.6.1. Переполнение буфера
10.6.1. Переполнение буфера
Почти псе основные Internet-демоны, включая демоны таких программ, как sendmail, finger, talk и др., подвержены атакам типа переполнение буфера. О них следует обязательно помнить при написании программ, которые должны выполняться с правами пользователя root, а также программ, осуществляющих межзадачное взаимодействие или читающих файлы, которые не принадлежат пользователю, запустившему программу.
Суть атаки заключается в том, чтобы заставить программу выполнить код, который она не собиралась выполнять. Типичный механизм достижения этой цели — перезапись части стека программы. В стеке, помимо всего прочего, сохраняется адрес памяти, по которому программа передает управление после завершения текущей функции. Следовательно, если поместить код взлома в памяти, а затем изменить адрес возврата так. чтобы он указывал на этот код, то по завершении текущей функции программа начнет выполнять код хакера с правами текущего процесса. Если процесс принадлежит пользователю root, последствия будут катастрофическими. Если атаке подвергся процесс другого пользователя, катастрофа наступит "только" для него (а также для любого пользователя, который работает с файлами пострадавшего).
Хуже всего обстоит дело с программами, которые работают в режиме демона и ожидают поступление запросов на подключение. Демоны обычно принадлежат пользователю root. Если в программе есть описываемая "дыра", любой, кто сможет подключиться к этой программе, способен захватить контроль над компьютером, послав по сети "смертельную" последовательность данных. Программы, не работающие с сетью, гораздо безопаснее, так как их могут атаковать только пользователи, уже зарегистрировавшиеся в системе.
Старым версиям программ finger, talk и sendmail присущ один общий недостаток: все они работают со строковым буфером фиксированной длины. Предельный размер строки предполагается по умолчанию, но ничто не мешает сетевым клиентам вводить строки, вызывающие переполнение буфера. В программах содержится примерно такой код, как показан ниже.
#include <stdio.h>
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().
Проблема переполнения буфера возникает при работе с любыми статическими массивами, а не только со строками. При написании безопасных программ следует тщательно проверять, не осуществляется ли запись в массив за его пределами.
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКЧитайте также
Переполнение переменной jiffies
Переполнение переменной jiffies Переменная jiffies, так же как и любое целое число языка программирования С, после достижения максимально возможного значения переполняется. Для 32-разрядного беззнакового целого числа максимальное значение равно 2??- 1. Поэтому перед тем как
Переполнение адреса
Переполнение адреса Так как мы решили не использовать на System/38 48-разрядный адрес повторно до следующей перезагрузки, встал вопрос о том, что однажды все доступные адреса могут быть исчерпаны. В поисках ответа на него, мы провели некоторые интересные подсчеты. В
3.1 ЗАГОЛОВКИ БУФЕРА
3.1 ЗАГОЛОВКИ БУФЕРА Во время инициализации системы ядро выделяет место под совокупность буферов, потребность в которых определяется в зависимости от размера памяти и производительности системы. Каждый буфер состоит из двух частей: области памяти, в которой хранится
12.3.3.1 Выделение буфера
12.3.3.1 Выделение буфера Обратимся еще раз к алгоритму getblk, рассмотренному нами в главе 3. Алгоритм работает с тремя структурами данных: заголовком буфера, хеш-очередью буферов и списком свободных буферов. Ядро связывает семафор со всеми экземплярами каждой структуры.
14.2. Переполнение буфера
14.2. Переполнение буфера Это одна из самых популярных и в то же время наиболее сложная в использовании уязвимость. Для начала определимся, почему программисты допускают такие ошибки, при которых возможно выполнить переполнение буфера?В таких языках, как С++, для работы с
6.20.2 Использование буфера
6.20.2 Использование буфера Протокол IP, производящий пересылку датаграммы, несет ответственность за ее доставку. Для тех случаев, когда датаграмма по тем или иным причинам не попала в точку назначения, предусмотрен буфер датаграмм, позволяющий произвести операцию
3.6. Менеджеры буфера обмена
3.6. Менеджеры буфера обмена Во время работы с текстом вы наверняка что-то копируете в буфер обмена. Текстовый редактор Word умеет хранить несколько таких фрагментов. Однако такие данные находятся там недолго – стоит выключить компьютер или просто скопировать другой текст,
3.1.3. Переполнение при арифметических операциях
3.1.3. Переполнение при арифметических операциях Переполнением принято называть ситуацию, когда при операциях над переменной результат выходит за пределы ее диапазона. Рассмотрим следующий пример (листинг 3.4, проект Overflow1 на компакт-диске).Листинг 3.4. Переполнение при
Переполнение и потеря значимости при обработке чисел с плавающей точкой
Переполнение и потеря значимости при обработке чисел с плавающей точкой Что произойдет, если значение переменной типа float выйдет за установленные границы? Например, предположим, что вы умножаете 10е38 на 100 (переполнение) или делите 10е - 37 на 1000 (потеря значимости).
10.6.1. Переполнение буфера
10.6.1. Переполнение буфера Почти псе основные Internet-демоны, включая демоны таких программ, как sendmail, finger, talk и др., подвержены атакам типа переполнение буфера. О них следует обязательно помнить при написании программ, которые должны выполняться с правами пользователя root, а
8.2. Использование буфера обмена
8.2. Использование буфера обмена Буфер обмена представляет собой область оперативной памяти, которая используется операционной системой для временного хранения данных. Он выступает в роли общего хранилища данных для всех приложений системы, фактически любая программа
Глава 8 Переполнение буфера
Глава 8 Переполнение буфера В этой главе обсуждаются следующие темы: • Стек • Стековый фрейм функции • Основы переполнения буфера • Пример программы, уязвимой к переполнению буфера • Современные способы переполнения буфера • Новаторские принципы построения