Дэвид Лебланк - 19 смертных грехов, угрожающих безопасности программ
Обычно считается, что поиск в таблице занимает постоянное время, но это не всегда так. Ведь часть таблицы может быть вытеснена из кэша первого уровня (либо из–за того, что таблица слишком велика, либо из–за работы других потоков программы, либо, наконец, из–за того, что в операции участвуют и другие данные).
Мы приведем несколько примеров атак с хронометражем на криптосистемы в разделе «Примеры из реальной жизни». Есть основания полагать, что некоторые их слабости можно атаковать и удаленно, по крайней мере при определенных условиях. А если противник имеет физический доступ к машине, на которой выполняются подобные операции, следует предполагать, что эксплойт возможен.
Хронометрируемый канал – это наиболее распространенный вид побочного канала, но есть еще и каналы, связанные с хранением. Такой канал позволяет противнику видеть не предназначенные ему данные и извлекать из них некоторую информацию. Речь может идти, в частности, о выводах на основе свойств коммуникационного канала, которые не являются частью семантики данных и могли бы быть скрыты. Например, просто перехватив зашифрованное сообщение, передаваемое по кабелю, противник уже знает его длину. Обычно длина сообщения не считается важной характеристикой, но при некоторых обстоятельствах может оказаться таковой. А скрыть ее от противника не составило бы большого труда. Достаточно, скажем, передавать зашифрованные данные с постоянной скоростью, чтобы было невозможно выделить границы сообщений. Иногда каналом могут являться метаданные, сопровождающие собственно данные протокола или системы, как, например, атрибуты файловой системы или заголовки протокола, инкапсулирующие зашифрованную полезную нагрузку. Даже если все данные защищены, противник может извлечь из хранящегося в заголовке IP–адреса получателя информацию о том, кто передает (это верно даже для протокола IPSec).
Побочные каналы, связанные с хранением, в общем случае не так интересны, как основной коммуникационный канал. К примеру, даже если все передаваемые по сети данные криптографически защищены, имя пользователя для процедуры аутентификации обычно приходится передавать в открытом виде. А это дает противнику отправную точку для атаки с угадыванием пароля или с применением социальной инженерии. Ниже мы увидим, что утечка информации как по основному, так и по побочному хронометрируемому каналу может дать и куда более полезные сведения.
Слишком много информации!
Задача любого приложения – предоставить пользователю полезную информацию, необходимую ему для выполнения своей работы. Но на практике информации иногда бывает слишком много. Особенно это относится к сетевым серверам, которые должны быть лаконичны, учитывая возможность того, что противник может прослушивать соединение или вообще оказаться второй стороной. Но и у клиентских приложений есть проблемы с раскрытием избыточной информации.
Вот несколько примеров того, какую информацию не следовало бы сообщать пользователю.
Правильно ли имя пользователя
Если ваша система регистрации выдает разные сообщения при вводе несуществующего имени пользователя и неверного пароля, то вы тем самым даете противнику знать, что имя он угадал правильно. Дальше для получения пароля он может провести атаку полным перебором или с привлечением методов социальной инженерии.
Детальная информация о версии
Раскрытие подробной информации о номере версии позволяет противнику творить свои дела, оставаясь незамеченным. Цель противника – найти уязвимые системы, не оставляя никаких следов своего присутствия. Пытаясь отыскать сетевые службы, которые можно атаковать, противник сначала снимает «цифровой отпечаток» с операционной системы и работающих служб. Можно очень точно идентифицировать многие операционные системы, послав необычный набор пакетов и проверяя полученный ответ (или отсутствие оного). На уровне приложений можно сделать то же самое. Например, Web–сервер Microsoft IIS не настаивает на том, чтобы HTTP–запрос типа GET заканчивался парой символов «возврат каретки /перевод строки», он соглашается на один лишь символ перевода строки. Сервер же Apache в соответствии со стандартом требует наличия обоих символов. Нельзя сказать, что одно приложение правильно, а другое – нет, но различия в поведении помогают определить, с каким из них вы имеете дело. Проведя еще несколько тестов, можно точно выяснить, какой сервер вас обслуживает и, быть может, даже его версию.
Менее надежный метод заключается в том, чтобы послать серверу запрос GET и проанализировать возвращенную в ответе шапку. Вот что мы получим от IIS 6.0:
...HTTP/1.1 200 OK
Content-Length: 1431
Content-Type: text/html
Content-Location: http://192.168.0.4/iisstart.htm
Last-Modified: Sat, 22 Feb 2003 01:48:30 GMT
Accept-Ranges: bytes
ETag: "06be97f14dac21:26c"
Server: Microsoft-IIS/6.0
Date: Fri, 06 May 2005 17:03:42 GMT
Connection: close
Из заголовка Server видно, какой сервер обслужил запрос, но, вообще говоря, пользователь может изменить этот заголовок. Например, некоторые подменяют шапку IIS 6.0 шапкой Apache, а потом потешаются над хакерами, пытающимися провести заведомо обреченную на провал атаку.
Таким образом, противник стоит перед выбором: выполнить исчерпывающую проверку или смириться с не слишком надежным методом, который зато останется не замеченным сенсорами системы обнаружения вторжений. Если сетевой сервер сообщает противнику точную информацию о номере своей версии, тот может провести известную атаку против именно этой версии с меньшими шансами быть обнаруженным.
Если клиентское приложение включает информацию о версии в документ, это тоже ошибка: получив документ, созданный на заведомо уязвимой системе, вы сможете послать автору специально подготовленный документ, при обработке которого будет выполнен произвольный код.
Информация о сетевом хосте
Очень распространена утечка информации о структуре внутренней сети, а именно:
□ МАС–адреса;
□ имена машин;
□ IP–адреса.
Если ваша сеть находится за межсетевым экраном, NAT–маршрутизатором (Network Address Translation – трансляция сетевых адресов) или прокси–сервером, то вряд ли вы заинтересованы в том, чтобы детали ее внутреннего устройства просачивались через границу. Поэтому нужно очень внимательно смотреть, не включаете ли вы в сообщения об ошибках или состоянии закрытую информацию. Так, в сообщениях об ошибках не должны фигурировать IP–адреса.
Информация о приложении
Утечка информации о приложении происходит обычно в виде сообщений об ошибках. Эта тема подробно обсуждается в грехе 8. Короче говоря, не включайте в сообщения конфиденциальные сведения.
Следует отметить, что сообщения об ошибках, которые, на первый взгляд, кажутся безобидными, зачастую таковыми не являются. Примером может служить уже упомянутая выше реакция на неверно введенное имя пользователя. В криптографических протоколах считается правильным никогда не сообщать о причине отказа и по возможности избегать какого бы то ни было извещения об ошибках. Особенно актуальным этот подход стал после недавней атаки на протокол SSL/TLS, связанной с извлечением информации из сообщений об ошибках. В общем случае если вы можете сообщить об ошибке безопасно и на сто процентов уверены в том, кто это сообщение получит, то можете особо не беспокоиться. Но если ошибка «выходит на простор», где ее может увидеть любой (как было в случае SSL/TLS), то лучше просто разорвать соединение.
Информация о пути
Это очень распространенная уязвимость, чуть ли не каждый когда–нибудь да грешил. Рассказывая противнику о структуре своего жесткого диска, вы упрощаете ему задачу выбора места, в которое можно поместить вредоносную программу, если ваш компьютер удастся скомпрометировать.
Информация о структуре стека
Если в программе на С, С++ или языке ассемблера вы передадите вызываемой функции слишком мало аргументов, исполняющая среда не будет возражать, а просто возьмет со стека столько данных, сколько ей нужно. Это может быть как раз та информация, которая необходима противнику для атаки на переполнение буфера в каком–то другом месте программы. Ведь тем самым он получает очень подробные сведения о структуре стека.
Может быть, вам это покажется невероятным, но сплошь и рядом программисты вызывают функции семейства printf(), задавая конкретную форматную строку, однако слишком мало аргументов для нее.
Модель безопасности информационного потока
В простом сценарии «мы против них» нетрудно рассуждать об утечках информации. Либо вы раскрываете противнику конфиденциальные данные, либо нет.
Но в реальном мире системой пользуются многие люди, и приходится задумываться о разграничении доступа. Например, если вы ведете дела с двумя крупными банками, скорее всего, ни один из них не захочет показывать свои данные конкуренту. Можно представить себе и более сложные иерархии, в которых надо уметь избирательно предоставлять те или иные права.