Истинная цена программных ошибокОпределить цену программных ошибок трудно, поскольку влияние одного сбоя в критически важной системе может иметь порой непредсказуемые последствия для различных секторов экономики. По оценкам Национального института по стандартам и технологиям США (NIST), американская экономика ежегодно тратит 60 млрд долл. на разработку и распространение программных «заплат», а также переустановку инфицированных систем. В эту сумму входят также расходы, связанные с потерей производительности из-за действия вредоносных программ и с другими проблемами, вызванными ошибками в программном обеспечении (www.nist.gov/public_affairs/releases/n02-10.htm). Расходы на очистку от вирусов существенно разнятся в зависимости от каждого конкретного случая, так, вирус Love Bug (2000 год) обошелся мировому сообществу примерно в 8,75 млрд долл., CodeRed (2001) стоил компаниям 2,75 млрд, а Slammer (2003) – 1,5 млрд долл. (www.computereconomics.com/article.cfm?id“6).

Хуже всего то, что программные проблемы не заканчиваются сбоем в работе браузеров, «зомбированными» компьютерами, рассылающими спам, или кражей номеров кредитных карт. Функционирование критически важных инфраструктурных комплексов, в том числе энергораспределительных систем, нефтеперерабатывающих заводов, газопроводов, водоочистных сооружений и атомных электростанций, основано на промышленных автоматизированных системах сбора данных и управления в режиме реального времени. Программное обеспечение, лежащее в основе таких систем, подвержено тем же ошибкам, что и его корпоративные аналоги, однако сбои в этих случаях имеют значительно более серьезные последствия. В августе 2003 года северо-восток США остался без электричества в том числе и из-за программной ошибки в системе управления аварийной сигнализацией. Переполнение памяти возникло из-за так называемых «гонок» (race condition) – ошибки программирования многозадачной системы, вызывающей неопределенность порядка выполнения различных частей кода. Система попала в бесконечный цикл, тем самым оставив операторов без актуальной информации о состоянии энергосистемы. Если бы все было запрограммировано грамотно, то оператор смог бы предотвратить каскадные сбои и минимизировать убытки [1]. По некоторым оценкам, ущерб составил от 7 млрд до 10 млрд долл. (www.icfi.com/Markets/Energy/doc_files/blackout-economic-costs.pdf).

Учитывая, что программные ошибки обходятся так дорого, проницательный читатель может спросить, почему же отрасль программного обеспечения не прилагает более серьезных усилий для того, чтобы их предотвратить? Типичный ответ, который можно услышать даже от специалистов по защите программного обеспечения, состоит в том, что программные ошибки не считают столь уж важными, они, мол, «не убивают людей». К сожалению, эти слова свидетельствуют о непонимании того, как сильно сегодня мы зависим от корректной работы программного обеспечения. Приведем несколько примеров, показывающих, насколько действительно смертоносными могут быть ошибки в программном обеспечении различных критически важных систем.

Сбой в работе комплекса Patriot

Patriot – состоящая на вооружении армии США мобильная система противоракетной обороны, оснащаемая ракетами класса «земля-воздух» и предназначенная для защиты от самолетов, крылатых ракет и баллистических ракет ближнего радиуса действия. 25 февраля 1991 года сбой в системе Patriot помешал отследить и перехватить иракскую ракету Scud, выпущенную по военной базе Дахран в Саудовской Аравии. Ракета достигла цели, в результате чего погибли 28 американских солдат и еще около 100 человек получили ранения (см. www.fas.org/spp/starwars/gao/im92026.htm). 

Причиной сбоя стала ошибка округления, приводящая к неточности в работе часов, которая усугубилась увеличенным временем работы между перезагрузками системы. При разработке первоначальной архитектуры предполагалось, что система Patriot будет действовать в мобильных условиях и, как следствие, часто перемещаться. В силу чего предполагалось, что ее операционный цикл составит 14 часов. Система в Дахране работала значительно дольше – примерно 100 часов, в результате чего расфазировка синхронизирующих импульсов составила 0,34 с. Несмотря на то что в процентном отношении такая ошибка может показаться небольшой, именно она привела к некорректному расчету местонахождения приближающейся ракеты. Система Patriot определяет, является ли приближающийся объект целью для перехвата, вычисляя «зону попадания» на основе данных первого радарного контакта этого объекта, известной скорости цели и таймера. Радарный контакт в прогнозируемой «зоне попадания» подтверждает факт обнаружения цели, но рассинхронизация часов привела к тому, что система неправильно вычислила границы зоны поражения цели, поэтому не зарегистрировала второй радарный контакт с целью.

По иронии судьбы военные уже подготовили исправление этой программной ошибки, и обновленное программное обеспечение появилось на базе всего день спустя после ракетного удара, но было уже поздно.

Передозировки при лучевой терапии

Гибель людей из-за систем вооружений (в результате неисправности последних или по другим причинам) в каком-то смысле вещь ожидаемая – идет война и бывает всякое, но смерть в мирное время, например от медицинского оборудования, предназначенного для лечения, вызывает большую тревогу. Печально известная ошибка в линейном ускорителе Therac-25 стала причиной гибели нескольких больных, получивших смертельные дозы радиации во время лечения, проводимого с июня 1985-го по январь 1987 года в нескольких онкологических клиниках в США и Канаде. Эти дозы, как было оценено позже, более чем в 100 раз превышали те, что обычно применяются при лечении.

Частично причиной этих несчастий стала ошибка типа race condition. В Therac-25 использовалось меньше аппаратных компонентов, чем в предыдущих модификациях, и применялось новое программное обеспечение для микросхемы предохранительной блокировки, которая гарантирует правильное позиционирование защитных поверхностей и препятствует превышению заданного максимума мощности электронного луча вне зависимости от данных, вводимых оператором. Программная ошибка проявлялась, когда оператор слишком быстро вводил определенную последовательность команд на управляющем терминале. Информация, отображающаяся на экране оператора, не соответствовала реальной работе устройства и не позволяла оператору понять, что возникла ошибка. Та же самая ошибка была и в программном обеспечении предыдущей модели Therac-20, но там была более «глупая», непрограммируемая аппаратная предохранительная блокировка, оказавшаяся в результате более надежной [2].

Один из последних случаев смертельной передозировки при лучевой терапии произошел в Национальном онкологическом институте в Панама-Сити в 2001 году. Разработанное компанией Multidata Systems International программное обеспечение планирования лечения в определенной ситуации некорректно вычисляло дозы радиации. Двадцать восемь пациентов подверглись чрезмерному облучению, что стало причиной смерти нескольких больных. Эта программная ошибка проявлялась, когда операторы пытались преодолеть системные ограничения на количество и конфигурацию защитных поверхностей, используемых для изоляции зоны облучения. Они обнаружили, что, если изображать область с отверстием внутри, то таким образом можно заставить систему направлять нужную дозу радиации в правильное место. Однако им было неизвестно, что при изображении такой поверхности в одном направлении вычисления будут корректными, но, если рисовать поверхность по-другому, то возникнет передозировка. Мы не можем винить в этих инцидентах одно только программное обеспечение – предполагалось, что операторы выполняют вычисления вручную для того, чтобы гарантировать, что доза, определенная программой, является приемлемой. Они игнорировали эту важную проверку из-за отсутствия в этом медицинском институте строгих административных процедур (www.fda.gov/cdrh/ocd/panamaradexp.html или www.fda.gov/bbs/topics/NEWS/2003/NEW00903.html).

Разрыв трубопровода

Надежность и безопасность работы критически важных инфраструктурных систем, таких как военные и медицинские системы, во многом зависит от программного обеспечения. Операторы используют системы диспетчерского контроля и сбора данных (Supervisory Control And Data Acquisition, SCADA) для получения актуальной информации, необходимой для правильной оценки состояния системы и ее надежной работы. Несмотря на то что критически важные инфраструктурные комплексы помимо SCADA оборудованы физическими средствами безопасности, программная ошибка, не позволяющая оператору видеть реальное состояние системы, может привести к катастрофическому сбою.

В Беллингеме (штат Вашингтон) 10 июня 1999 года прорвало трубопровод диаметром 41 см, в результате чего около 900 тыс. литров бензина вылилось в ручей, протекающий через парк Whatcom Falls. Бензин вспыхнул и загорелся на площади примерно 2,5 кв. км вдоль ручья. В результате этой аварии погибли два десятилетних мальчика и 18-летний юноша, и еще восемь человек обратились за врачебной помощью. Владелец трубопровода – компания Olympic Pipeline оценила общий материальный ущерб в 45 млн долл., но как оценить деньгами смерть детей?

Сам по себе разрыв образовался вследствие целого ряда причин: трубопровод был поврежден в результате ведущегося рядом строительства, высокое давление в трубе во время последующей перекачки топлива усугубило повреждение, что привело к разрыву и утечке бензина. Однако расследование показало, что отсутствие предупреждения от SCADA не позволило операторам определить неисправность и предпринять необходимые меры. Авторы отчета уверены, что более раннее отключение трубопровода могло предотвратить произошедший взрыв (www.ntsb.gov/publictn/2002/PAR0202.pdf).

Поиск решений

Как показывают приведенные примеры, программные ошибки влияют на работу многих критически важных систем, от военных комплексов до медицинской аппаратуры и инженерной инфраструктуры. Более того, в некоторых случаях ошибки приводят к фатальным последствиям, поскольку программное обеспечение уже стало неотъемлемой частью того, как мы оцениваем ситуацию в физическом мире и как реагируем на нее. Не имеет особого значения, проявляются ли программные ошибки из-за неверных действий оператора, оказываются следствием маловероятной последовательности событий или умышленных злонамеренных действий – результат будет в равной степени гибельным. Надежность и безопасность – две стороны одной медали, поскольку и то и другое может пострадать из-за недостаточной готовности, надежности и целостности системы.

Было бы неверным целиком возлагать вину за описанные здесь инциденты на программные ошибки, но при столь серьезной зависимости от программного обеспечения необходимо четко понимать последствия программных ошибок. Эти примеры только подтверждают выводы отчета NIST – программное обеспечение недостаточно тестируется для того, чтобы обеспечить надежность функционирования критически важных систем. Научные работы в ряде дисциплин, таких как проверка моделей, верификация программного обеспечения, статический анализ и автоматизированное тестирование, вселяют надежду на появление программных систем, избавленных от определенных дефектов.

Анализ моделей и верификация программного обеспечения опираются на математическое моделирование вычислений, выполняемых программой, с целью проверки того, что определенная ошибка (такая, как деление на ноль) не может возникнуть ни в какой части программы. Эти методы позволяют определить не местонахождение ошибки, а те части кода, которые гарантированно ее не содержат. Несмотря на то что такой подход, по сути, превращает обычную задачу поиска ошибок в ее противоположность, он позволяет гарантировать качество кода, правильность которого может быть доказана системой. К сожалению, приведение этих доказательств для больших программ не имеет практического смысла, поскольку точная модель поведения программного обеспечения быстро становится слишком громоздкой, заставляя систему делать приближения, которые влияют на точность анализа.

Пользуется популярностью и статический анализ, например, несколько коммерческих компаний продают инструментальные средства анализа программ на языках Си, C++ Java и C#. Статический анализ включает в себя несколько методик, самые известные из которых – это лексический анализ и интерпретация абстракций. Инструментарий лексического анализа сканирует программное обеспечение в поисках словоупотреблений и языковых идиом, которые часто используются неправильно и, как следствие, с большой вероятностью свидетельствуют о том, что программист сделал ошибку. Однако эти инструменты нередко имеют большой процент «ложных тревог», в силу чего разработчикам приходится анализировать много ошибочных предупреждений в поисках реальных ошибок. Инструментарий интерпретации абстракций позволяет выполнять символьное представление программы, при котором считается, что все входные данные и неизвестные адреса в памяти содержат символьное значение, которым программа может манипулировать. Такая методика обычно дает более точные результаты, чем лексический анализ, однако большой размер и сложность программы могут заставить инструментарий использовать приближения, которые порождают немало «ложных тревог» и пропусков реальных ошибок [3].

В последние годы большое внимание уделяется и автоматизированному тестированию. С появлением методики fuzzing, при которой с помощью технологии мутации и других механизмов программе посылаются псевдослучайные наборы входных данных с целью вызывать сбой в ее работе, многие разработчики стали активнее менять свои подходы к функциональному тестированию. Добавление fuzz-тестирования в процесс разработки программного обеспечения дает некоторую уверенность в том, что программное обеспечение способно корректно обрабатывать даже непредвиденные входные данные. Такие методики используют более изощренные инструменты анализа исходного или бинарного кода, позволяющие выявлять незаметные ошибки, которые могут и не приводить к фатальному сбою [4, 5].

***

Несмотря на то что многие академические исследования посвящены в первую очередь анализу и тестированию программного обеспечения, имеющиеся инструменты пока не находят широкого распространения в отрасли. Согласно приближенным оценкам Quality of Protection Workshop, отраслевые затраты на защиту программных активов (оцениваемые в 0,2% оборота рынка программного обеспечения) на порядок меньше, например, затрат на защиту сетевых активов (оцениваемых в 2,3% оборота рынка сетевого оборудования, 1raindrop.typepad.com/1_raindrop/2008/11/the-economics-of-finding-and-fixing-vulnerabilities-in-distributed-systems-.html). С другой стороны, рынок программных инструментальных средств и сервисов растет. В 2007 году его оборот составлял 275–300 млн долл., а в некоторых секторах, таких как средства статического анализа и тестирования по принципу «черного ящика», темпы роста составляют 50–83% [6]. Мы можем только надеяться, что эта тенденция сохранится, поскольку более надежное и безопасное программное обеспечение может помочь предотвратить повторение в будущем трагедий, аналогичных описанным.

Литература

  1. US–Canada Power System Outage Task Force, Final Report on the August 14, 2003 Blackout in the United States and Canada: Causes and Recommendations, tech. report, US Dept. of Energy, Apr. 2004.
  2. G. Williamson, Software Safety and Reliability, IEEE Potentials, vol. 16, no. 4, 1997, pp. 32–36.
  3. R. Lippmann, M. Zitser, T. Leek, Testing Static Analysis Tools using Exploitable Buffer Overflows from Open Source Code, ACM SIGSOFT Software Eng. Notes, vol. 29, no. 6, 2004, pp. 97–106.
  4. T. Leek, M. Zhivich, R. Lippmann, Dynamic Buffer Overflow Detection, Proc. Workshop Evaluation of Software Defect Detection Tools, 2005.
  5. M. Zhivich, Detecting Buffer Overflows using Testcase Synthesis and Code Instrumentation, master’s thesis, Dept. of Electrical Eng. and Computer Science, Massachusetts Inst. of Tech., May 2005.
  6. G. McGraw, Software [In]Security: Software Security Demand Rising, InformIT, 11 Aug. 2008; www.informit.com/articles/article.aspx?p=12337978.

Майкл Живич, Роберт Каннингэм (mzhivich/rk@ll.mit.edu) – сотрудники лаборатории Линкольна Массачусетского технологического института.


Michael Zhivich, Robert K. Cunningham, The Real Cost of Software Errors, IEEE Security & Privacy, March/April, 2009. IEEE Computer Society, 2009. All rights reserved. Reprinted with permission.


Мифы о безопасном ПО: уроки знаменитых катастроф

Ошибки в программном обеспечении могут вызвать чрезвычайные последствия тем не менее в обществе на уровне массового потребителя ИТ продолжает витать иллюзия непогрешимости компьютера и работающего на нем ПО. Однако это далеко не так.

Ошибки и их последствия

Форум ACM Forum on Risks to the Public in Computers and Related Systems – превосходный ресурс, содержащий примеры программных ошибок и их последствий.