Странная машина
Странная машина — понятие в области компьютерной безопасности, обозначающее вычислительный артефакт, в рамках которого возможно выполнение дополнительного кода вне изначальной спецификации программы[1]. Это понятие тесно связано с концепцией странных инструкций, которые представляют собой строительные блоки эксплойта, основанного на специально сформированных входных данных[2].
Концепция странной машины служит теоретической рамкой для понимания существования эксплойтов, использующих уязвимости безопасности. Эксплойты эмпирически существуют в программном обеспечении, однако до появления теории странных машин их не изучали с теоретической точки зрения.
Теория
Странные машины возникают вследствие сложности модели вычислений и внешних воздействий, выходящих за рамки предусмотренной модели. Например, странная машина может возникнуть из-за того, что входной формат является Тьюринг-полным, наличия уязвимостей повреждения памяти или потому, что аппаратное обеспечение способно вести себя непредсказуемо с точки зрения модели вычислений[3].
С теоретической точки зрения появление странных машин становится понятным, если рассматривать программное обеспечение как способ ограничить количество достижимых состояний и переходов между ними на компьютере: универсальный ЦП с помощью программного обеспечения сужается до имитации конечного автомата (пусть и с очень большим пространством состояний). Многие состояния и переходы, которые теоретически доступны для процессора, исключаются, особенно те, что нарушают требования безопасности программного обеспечения. Если система каким-либо образом переходит в состояние, «не имеющее смысла» с точки зрения задуманного конечного автомата (из-за повреждения памяти, отказа оборудования или ошибок программирования), программное обеспечение начнёт преобразовывать это повреждённое состояние в другие сбойные состояния, по мере поступления новых входных данных. Возникает новое вычислительное устройство: странная машина, которая может достигнуть таких состояний процессора, какие первоначально не предполагались разработчиком, и действует она под контролем входных данных злоумышленника.
Применение
Ожидаемый, корректный ввод активирует нормальную, предусмотренную функциональность компьютерной программы, а неожиданный для разработчика ввод может запустить непредусмотренные функции. Странная машина состоит именно из этой непреднамеренной функциональности, которой можно по сути управлять, подбирая специальные входные данные для реализации эксплойта.
В классической атаке с использованием переполнения буфера в стеке, специально сформированные входные данные подаются уязвимой программе так, чтобы сами оказались исполнены как программный код. Однако если области памяти с данными защищены и не могут исполняться напрямую, входные данные могут содержать указатели на различные участки уже существующего кода, которые затем исполняются в неожиданном порядке, реализуя эксплойт. Такие фрагменты кода называются элементами в контексте ориентированного на возврат программирования.
Посредством интерпретации данных как кода функциональность странной машины, определённо выходящая за пределы исходной спецификации программы, может также быть достигнута и в системах PCC, которые формально доказаны к корректности определённым образом[4]. Это существенное различие связано с разрывом между формальным абстрактным моделированием компьютерной программы и её реальной инстанцией, которая может подвергаться неблагоприятным воздействиям, не учитываемым при формализации, например ошибки памяти или сбои электропитания.
Поведение странной машины наблюдается даже в аппаратном обеспечении. Например, показано, что вычисления можно реализовать, используя только инструкции MOV на архитектуре x86[5].
Защита
Основные меры противодействия проблемам, вызываемым функциональностью странной машины, включают в себя валидацию входных данных в программном обеспечении и предотвращение проблем, связанных с платформой, на которой выполняется программа (например, ошибок памяти). Валидация входных данных призвана ограничить диапазон и форму неожиданных входных данных, например, с помощью белых списков допустимых значений, чтобы программа не переходила во внутреннее некорректное состояние при обработке данных. Не менее важно применение безопасных практик программирования — таких, как защита от переполнения буфера, — в целях снижения вероятности того, что входные данные будут интерпретированы аппаратурой неожиданным образом.