Раздел: Документация
0 ... 33 34 35 36 37 38 39 ... 102 находится в весьма жестких и агрессивных условиях, не обеспечивающИ)( нимального уровня жизнедеятельности.иЧи- И если вам нужен путеводитель по стране переполняющихся буферу женный исчерпывающим руководством по выживанию, — эта глава для ФИЛОСОФСКОЕ НАЧАЛО Чудовищная сложность современных компьютерных систем неизбежно при водит к ошибкам проектирования и реализации, многие из которых позволяют злоумышленнику захватывать контроль над удаленным узлом или делать с ним что-то нехорошее. Такие ошибки называются дырами, или уязвимостями (holes и vulnerability соответственно). Мир дыр чрезвычайно многолик и разнообразен: это и отладочные люки, н слабые механизмы аутентификации, и функционально-избыточная интерпретация пользовательского ввода, и некорректная проверка аргументов, нт.д. Классификация дыр чрезвычайно размыта, взаимно противоречива и затруднена (во всяком случае, своего Карла Линнея дыры еще ждут), а методики их поиска и «эксплуатации» не поддаются обобщению и требуют творческого подхода к каждому отдельно взятому случаю. Было бы наивно надеяться,что одна единственная публикация сможет описать весь этот зоопарк! Давайте лучше сосредоточимся па ошибках переполнения буферов (bufferoverflow/ overrun) как на наиболее важном, популярном, перспективном и приоритетном направлении. Большую часть главы мы будем витать в бумажных абстракциях теоретических построений и лишь к концу спустимся на ассемблерную землю, обсуждая наиболее актуальные проблемы практических реализаций. Нет, не подумайте. Никто не собирается в сотый раз объяснять, что такое стек, адреса памяти и от куда они растут! Эта глава рассчитана на хорошо подготовленную читатель скую аудиторию, знающую ассемблер и бегло изъясняющуюся на Си/Си++ словаря. Как происходит переполнение буфера вы, вероятно, уже представляе те, и теперь хотели бы ознакомится с полным списком возможностей, иред0 ставляемых переполняющимися буферами. Какие цели может преследовать кующий? По какому принципу происходит отбор наиболее предпочтите объектов атаки? Ну и т. д.... Другими словами, сначала мы будем долго и нудно говорить о том, что м°н. сделать с помощью переполнения и лишь затем перейдем к вопросу, «как но это сделать». Описанные приемы работоспособны на большинстве процессорных аР*аеТ, тур и операционных систем (например, UNIX/SPARC). Пусть вас не ему что приводимые примеры в основном относятся к Windows NT и прои*в (С от нее системам. Просто в момент написания другой операционной систе оказалось под рукой. oSS---- i z „ЯСНОЙ РУЛЕТ ОШИБОК ПЕРЕПОЛНЕНИЯ, или ПОПЫТКА КЛАССИФИКАЦИИ (СКУКА СМЕРТНАЯ) Согласно «Новому Словарю Хакера» Эрика Раймонда, ошибки переполнения буфера - это ...то, что с неизбежностью происходит при попытке засунуть в буфер больше, чем тот может переварить. На самом деле это всего лишь частный случай последовательного переполнения при записи (листинг 4.1). Помимо него, существует индексное переполнение, заключающееся в доступе к произвольной ячейке памяти за концом буфера, где под «доступом» понимаются как операции чтения, так и операции записи (листинг 4.2). Переполнение при записи приводит к затиранию, а следовательно, искажению одной или нескольких переменных (включая служебные переменные, внедряемые компилятором, такие, например, как адреса возврата или указатели this), нарушая тем самым нормальный ход выполнения программы и вызывая одно пз следующих последствий: •нет никаких последствий; •программа выдает неверные данные или, попросту говоря, делает из чисел винегрет; •программа «вылетает», зависает или аварийно завершается с сообщением об ошибке; •программа изменяет логику своего поведения, выполняя незапланированные действия. Переполнение при чтении менее опасно, так как «всего лишь» приводит к потенциальной возможности доступа к конфиденциальным данным (например, паролям или идентификаторам TCP/IP соединения). Листинг 4.1. Пример последовательного переполнения буфера при записи seq Write(char *Р) rhar buff[8]; strcpytbuff. р): Листинг 4.2. Пример индексного переполнения буфера при чтении i(Wite(int i) ct»r buffr>"0l23456789": return buff[i]: 118Глава 4. Ошибки переполнения буфера извнр -----—!иэну. За концом буфера могут находиться данные следующих типов: •другие буферы; •скалярные переменные; •указатели. Или же вовсе может не находиться ничего (например, невыделенная стран памяти). Теоретически за концом буфера может располагаться исполняем * код, но на практике такая ситуация почти никогда не встречается.Ь1" Наибольшую угрозу для безопасности системы представляют именно указав ли, поскольку они позволяют атакующему осуществлять запись в производь ные ячейки памяти или передавать управление по произвольным адресам, например, на начало самого переполняющегося буфера, в котором расположен машинный код, специально подготовленный злоумышленником и обычно на-зываемы й shel 1 -кодом. Буферы, располагающиеся за концом переполняющегося буфера, могут хранить некоторую конфиденциальную информацию (например, пароли). Раскрытие чужих паролей, равно как и навязывание атакуемой программе своего пароля -вполне типичное поведение для атакующего. Скалярные переменные могут хранить индексы (и тогда они фактически приравниваются к указателям), флаги, определяющие логику поведения программы (в том числе и отладочные люки, оставленные разработчиком), и прочую информацию. В зависимости от своего местоположения буферы делятся на три независимые категории: 1.Локальные буферы, расположенные в стеке и часто называемые автоматическими переменными. 2.Статичные буферы, расположенные в секции (сегменте) данных. 3.Динамические буферы, расположенные в куче. Все они имеют свои специфичные особенности переполнения, которые мы обя зательно рассмотрим во всех подробностях, но сначала немного нофнлософ ствуем. НЕИЗБЕЖНОСТЬ ОШИБОК ПЕРЕПОЛНЕНИЯ В ИСТОРИЧЕСКОЙ ПЕРСПЕКТИВЕ Ошибки переполнения — это фундаментальные программистские ошибку торые чрезвычайно трудно отслеживать и фундаментальность коТОРЫХграм-печивается самой природой языка Си — наиболее популярного языка п" мирования всех времен и народов — а точнее, его низкоуровневым хаРа.тиЧно. взаимодействия с памятью. Поддержка массивов реализована лишь час и работа с ними требует чрезвычайной аккуратности и внимания со с . программиста. Средства автоматического контроля выхода за граничь ствуют, возможность определения количества элементов массива по У лю и не ночевала, строки, завершающиеся нулем, — вообще песня.- 0 ... 33 34 35 36 37 38 39 ... 102
|