Анатомия уязвимостей

На чем основана анатомия уязвимостей? Уязвимость — это ошибка в программе, которую можно использовать для получения несанкционированного доступа к системе или отказа в обслуживании для уязвимого сервиса. Администратор, а тем более конечный пользователь, не в состоянии изменить природу вещей, зато они могут минимизировать возможность взлома системы или его последствия.

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

Однозначно подпадают под этот критерий ошибки, связанные с переполнением буфера, такие, как выход за границы диапазона для индексных массивов, переполнение стека и т.п. Не менее опасны ошибки, связанные с некорректным преобразованием типов данных. Вместе они составляют 90% всех уязвимостей, и лишь оставшиеся 10% связаны с недостатками в реализации логики программы.

Столь большой процент уязвимостей, основанных на переполнении буфера и некорректном преобразовании типов данных, не случаен. Он связан с тем, что с середины 70-х годов, когда язык С пришел на замену ассемблеру, ключевыми требованиями к ПО были компактность и высокая производительность, а вся ответственность за контроль программного кода возлагалась на программиста. Тогда это было оправдано, поскольку все серьезное ПО писалось под мейнфреймы, а персоналки еще только появлялись, и объем доступной оперативной памяти в них измерялся килобайтами.

Но время шло, мощность компьютеров выросла, появлялись языки с четкой типизацией данных и средствами контроля за переполнением буфера. Первой ласточкой был Pascal, который сочетал в себе как преимущества компилируемых языков, так и некоторые из возможностей динамических языков программирования благодаря развитой библиотеке времени исполнения, которая получила наибольшее развитие с появлением Object Pascal и его реализаций: Delphi и FreePascal.

Появление Java перевело языки программирования на новую эволюционную ступень, где программист мог абстрагироваться от архитектуры компьютера и операционной системы. Ее виртуальная машина, будучи в состоянии препятствовать переполнению буфера и ошибкам преобразования типов, тоже не решила проблему. Вышедшая в свет платформа .Net, под которую успешно перенесено большинство языков программирования и создан язык C#, тем не менее, имеет те же трудности с безопасностью.

Почему проблема осталась? Объяснение заключается в происхождении языков программирования, их своего рода «этимологии».

На чем разработана виртуальная машина Java? На С. С платформой .Net ситуация немногим лучше — она создана на С++ с использованием библиотек языка С. На чем разрабатываются компоненты современных операционных систем (а это миллионы строк исходного кода)? Тоже на C/C++, это относится и к драйверам устройств.

Львиная доля прикладного ПО разработана на С++.

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

Какова вероятность исключить ошибки в программе, состоящей из сотен или тысяч строк кода? Очевидно, что их отсутствие обеспечить просто невозможно, отсюда и ежегодный прирост числа уязвимостей. Когда-то при использовании С предполагалось, что программист должен обеспечивать проверку…. Теперь, при росте функций и архитектурной сложности программ, это стало превышать  не только человеческие возможности, но и экономические ограничения — стоимость тестирования и отладки всех возможных состояний систем не оправдана коммерчески.

Все это данность, но в отношении нее все же можно что-то сделать для снижения рисков эксплуатации уязвимостей. Во-первых, в настройках брандмауэра можно ограничить доступ к потенциально уязвимым службам. Во-вторых, службы надо запускать с правами непривилегированной учетной записи. В-третьих, есть возможность использовать виртуализацию для запуска уязвимых сервисов/демонов. В-четвертых, помогает установка обновлений, исправляющих ошибки в ПО.

Дальнейшие рекомендации зависят от типа используемой операционной системы.

Для Windows:

  • Использовать Data Execution Prevention (DEP) для защиты приложений
  • Ограничить доступ служб к объектам ОС при помощи групповых политик

Для UNIX-совместимых систем (Linux, FreeBSD и MacOS X):

  • Включить поддержку NX-бита в ядре ОС для защиты демонов и приложений
  • Использовать политики (для Linux — SELinux или AppArm, а для FreeBSD — MAC) для того, чтобы ограничить доступ демонов к системным ресурсам
  • Запускать демоны в chroot-окружении для защиты файловой системы
  • Использовать сетевой суперсервер для ограничения доступа к демонам

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

Запись опубликована в рубрике Без рубрики, Публикации. Добавьте в закладки постоянную ссылку.

Комментарии запрещены.