Разработка приложений в среде Linux. Второе издание
Шрифт:
Возвращаясь к нашему примеру переполнения буфера, следует отметить, что для переменной
Существенная проблема возникает, если программа записывает возвращаемый адрес вне пределов стека, но не порождает ошибку сегментации. Это позволяет изменять адрес, возвращаемый из работающей функции, на любой случайный адрес в памяти. Когда функция возвращает управление,
Реализации, использующие переполнение буфера, как правило, включают некоторый код в массив, записываемый в стек, и возвращаемый адрес устанавливается на этот код. Этот прием позволяет взломщику запускать любой произвольно выбранный код с теми правами доступа, которыми обладает атакуемая программа. Если эта программа является сетевым демоном, работающим как root, то любой удаленный пользователь получает доступ root к локальной системе!
Обработка строк — не единственное место, в котором встречается переполнение буфера (хотя, пожалуй, наиболее распространенное). Еще одним уязвимым моментом является чтение файлов. Файловые форматы нередко сохраняют размер элемента данных, за которым следуют сами данные. Если размер сохранения используется для выделения буфера, а конец поля данных определяется каким-то другим способом, может произойти ошибка переполнения буфера. Этот тип ошибки сделал возможным для Web-сайтов обращение к файлам, которые искажены так, чтобы предоставить удаленное пользование.
Чтение данных через сетевое соединение предоставляет еще одну возможность для переполнения буфера. Многие сетевые протоколы указывают максимальный размер для полей данных. Например, протокол ВООТР [160] фиксирует для всех пакетов размер 300 байтов. Это, однако, не мешает другой машине передать через сеть 350-байтовый пакет ВООТР. Если в сети работают программы с дефектами, то они попытаются скопировать этот нестандартный 350-байтовый пакет в пространство, выделенное для корректного 300-байтового пакета ВООТР, тем самым вызовут переполнение буфера.
160
ВООТР — это предшественник DHCP, позволяющий компьютерам автоматически узнавать свои IP-адреса при запуске сетевых интерфейсов.
Локализация и трансляция служат еще двумя побудителями переполнения буфера. Если программа написана для английского языка, то без сомнения для хранения названия месяца, загружаемого из таблицы, будет достаточно десятисимвольной строки. Когда эта программа переводится на испанский, "September" превращается в "Septiembre" и может произойти переполнение буфера. Всякий раз, когда программа поддерживает различные языки и локали, большинство первоначально статических строк становятся динамическими, и внутренние строковые буферы должны это учитывать.
Теперь уже очевидно, что переполнение буфера представляет собой критическую проблему в системе безопасности. Ее очень легко упустить из виду во время программирования (в конце концов, кто должен волноваться о файловых именах, длина которых превышает
Существует несколько приемов для устранения из кода возможности переполнения буфера. Хорошо продуманные программы используют множество способов для внимательного выделения буферов соответствующих размеров.
Лучшим способом распределения памяти для объектов является метод
Подобно
161
Функция
Есть еще также несколько других функций, которые помогают избежать переполнения буфера. Библиотечные методы
Обе функции ведут себя как их родственники, называемые аналогично,
Частой ошибкой при использовании
Несмотря на то что эти функции могут сделать выполнение программы некорректным при передаче длинных строк (из-за усечения этих строк), данный прием хорошо предотвращает перегрузки в буферах статических размеров. Во многих случаях это приемлемый компромисс (во всяком случае, при этом не произойдет ничего хуже того, что может случиться из-за переполнения буфера).
Функция