Глава 13
Надежность программного обеспечения
Системные меры безопасности (ядра безопасности, меры контроля доступа, криптография и т. д.) в комплексе с хорошими сетевыми мерами безопасности (брандмауэрами, системами обнаружения вторжения, механизмами проверки) создают впечатление достаточной компьютерной безопасности. Почему же тогда и компьютеры, и сети так ненадежны? Почему мы так часто становимся свидетелями уязвимости компьютеров и почему не происходит изменение в лучшую сторону?
Проблема в том, что такие меры безопасности, как шифрование, ядра безопасности, брандмауэры и прочие, лучше работают в теории, нежели на практике. Другими словами, изъяны системы безопасности значительно чаще случаются при вводе ее в действие, и они намного более серьезны, чем те, что возникают при ее разработке. До сих пор во второй части данной книги говорилось о разработке. В этой главе речь пойдет о вводе в действие.
В июле 1996 года вследствие ошибки в программе вскоре после запуска взорвалась ракета «Ариан 5» Европейского космического агентства: программа пыталась поместить 64-разрядное число в 16-разрядное пространство, вызвав переполнение. Этот урок особенно важен для понимания проблем компьютерной безопасности. По существу, проблема была связана с фрагментом кода, обрабатывавшего данные о скорости бокового ветра, написанного еще для ракеты «Ариан 4». Через 36,7 секунды после запуска управляющий компьютер попытался преобразовать значение скорости из 64-разрядного формата в 16-разрядный. Число оказалось слишком большим, что и вызвало ошибку. Обычно используется дополнительный код, который отслеживает ошибки такого рода и исправляет их. Но в данном случае программисты-разработчики решили не беспокоиться о подобном коде, так как величина скорости никогда не достигала таких больших значений, чтобы создавать проблемы. Возможно, это было верно для «Ариан 4», но «Ариан 5» – более быстрая ракета. Но хуже всего то, что эти вычисления, содержащие ошибку, не имели смысла с того момента, когда ракета оказывалась в воздухе. Программа, их производящая, была нужна лишь для того, чтобы отладить систему перед запуском, и после этого ее надо было бы сразу отключить. Но инженеры еще при разработке более ранней модели ракеты решили использовать эту функцию в течение первых 40 секунд полета, чтобы облегчить перезапуск системы в случае задержки запуска в последний момент перед стартом. Была резервная система, предназначенная дублировать основную в случае ее отказа, но она работала с тем же самым программным обеспечением, содержавшим те же самые ошибки.
В результате всех этих событий работа системы управления, полностью запутавшей бортовой компьютер «Ариан 5», была прекращена. Это привело к ненужной корректировке курса ракеты и повлекло ее самоуничтожение.
Три года спустя во время сложных маневров исчез искусственный спутник планеты Марс, запущенный NASA. Это не было делом рук марсианской противовоздушной обороны, а произошло вследствие ошибки преобразования данных. Инженеры NASA неудачно перевели значение силы сопротивления из английской системы мер в метрическую. Значения различаются в 4,45 раза: этого оказалось достаточно, чтобы научно-исследовательская станция опустилась на 50 миль ниже и сгорела в марсианской атмосфере.
Эти две катастрофы не связаны с компьютерной безопасностью, но они могут служить для пояснения того, насколько сложно разработать и ввести в действие код без ошибок. И Европейское космическое агентство, и NASA располагают достаточно большими средствами и сильно заинтересованы в том, чтобы обеспечить качество программного обеспечения. Но они до сих пор не в состоянии сделать это.
У других дела обстоят не лучше. В 1999 году eBay потеряла 22 часа из-за связанных с программным обеспечением ошибок в коде, полученном от Sun Microsystems. Выявление ошибки задержало выпуск карманных компьютеров Visor. А в 1998 году дефект в коммутаторах, произведенных компанией Cisco Systems, привел в нерабочее состояние передающую сеть компании AT&T Interspan, что отразилось на работе 6600 клиентов.
Печальная действительность состоит в том, что подобные ошибки программного обеспечения возникают везде. Большинство из них не приводит к таким разрушительным последствиям (перезагрузка электронной таблицы после аварийного отказа вызывает всего лишь незначительное раздражение), но так как сложное программное обеспечение во многих случаях функционирует внутри жизненно важных систем (например, в системах уклонения от автокатастрофы, взлета и посадки самолетов, управления атомной электростанцией), мы, вероятно, станем свидетелями увеличения количества подобных случаев. Проводится большая работа по исправлению ошибок, устранению недостатков, это получило название отказоустойчивой стратегии: например, если в автомобиле откажет система уклонения от автокатастрофы, предполагается, что водитель будет вести себя, как в машине без компьютера, вместо того чтобы позволить ей врезаться в ближайшее дерево. Идея в том, чтобы была уверенность, что небольшие недостатки не приведут к потере контроля над ситуацией, как было в случае с «Ариан 5».
Трудно обнаружить ошибки в программном обеспечении, влияющие на правильное выполнение задачи; обнаружить ошибки в системе безопасности еще труднее.
Надежность означает, что компьютер, в первую очередь программное обеспечение, но также и любые специализированные технические средства должны работать даже при появлении случайных ошибок. Они могут возникать при проектировании (использование одинакового программного обеспечения в основной и резервной системах), при вводе в действие (отсутствие проверки наличия ошибок при преобразовании данных), это могут быть ошибки программирования (вспомните математическую ошибку в чипе Intel Pentium[39]) или ошибки пользователя. Время от времени такие ошибки появляются. Это похоже на компьютер Мерфи: сбои происходят… редко, но постоянно. Если компьютер ошибается время от времени, пусть даже редко, это заметно любому пользователю.
Основная проблема состоит в том, что в любой сложной системе, программном обеспечении, применяемом в ракетной технике, большой базе данных, операционной системе, сетевом программном обеспечении, сложном микропроцессоре очень многие вещи могут работать со сбоями. И это определяет предел сложности. Невозможно предусмотреть или проверить абсолютно все. Неизбежно где-нибудь произойдет сбой.
Компьютерная защита более всего похожа на программирование для компьютера Сатаны. (Росс Андерсон ответствен за этот красивый оборот.) Чтобы быть безопасным, программное обеспечение должно работать, несмотря на появление неуловимых и опасных ошибок, которые могут быть преднамеренно внедрены способным нападающим с целью нанести поражение системе. Надежное программное обеспечение должно пережить и случайные ошибки, которыми может воспользоваться сообразительный хакер. (Представьте себе, что это некий хакер вызвал ошибку переполнения в программном обеспечении «Ариан 5» в самое неподходящее время.) Ошибки происходят случайно, и большинство из них редко встречается при обычном использовании. Но нападающие разыщут потенциальные ошибки и непременно воспользуются ими для достижения своих целей.
Широко применяемая стратегия для обнаружения случайных ошибок – предварительное тестирование: предоставить программное обеспечение большой группе пользователей (бета-тестирование). Люди будут пользоваться программами во всевозможных конфигурациях, на различных типах персональных компьютеров и с различными целями (о некоторых из них проектировщики даже не думали). Если они не смогут сломать систему, возможно, в ней нет ошибок. Сложно проводить предварительное тестирование программного обеспечения ракетной техники, но любое крупное коммерческое программное приложение, которое покупает пользователь, прошло тысячи часов предварительного тестирования для нахождения и исправления ошибок программирования.
39
Известна как «floating point flaw». Ошибка выражалась в потере точности (от 4-го до 19–го разряда после десятичной точки) при выполнении деления (инструкция FDiv) с некоторыми сочетаниями операндов. Была обнаружена в 1994 году для процессоров Pentium 60-100 МГц. Intel долгое время не признавала наличие ошибки, но, в конце концов, была вынуждена потратить 475 миллионов долларов на замену чипов. 1997 год выявил две ошибки. Первая, для Pentium II (ошибка флагов: «Dan-0411», «Flag Erratum»), проявлялась при преобразовании форматов больших отрицательных чисел и приводила к невозможности оповещения программ о завершении некоторых операций. Метод модификации микрокода во время загрузки уже работал, и ошибка была исправлена без отзыва проданных процессоров. Осенью выяснилось, что любой процесс, выполняемый на Pentium и Pentium ММХ, способен остановить «сердце» PC, выдав код F0 0F С7 С8 (сравнивающий 32-битовый операнд с 64-битовым, чем не случай с «Ариан»?). Благодаря некоторым конструктивным условиям практически всегда такой блокировки не происходит, но теоретически «Pentium FO bug» возможен. Теперь Intel размещает на своем сайте полную техническую информацию обо всех найденных «опечатках» (erratums). Так, для Pentium III в июне 2002 года количество таких ошибок равнялось 46, но все они имеют гораздо меньший уровень трагизма. – Примеч. ред.