вторник, 14 сентября 2010 г.

Оценка безопасности различных дистрибутивов Linux


Лаборатория компании MWR Infosecurity провела сравнительный анализ дистрибутивов Linux с точки зрения информационной безопасности. Результаты исследования изложены в статьях "Анализ безопасности кода, выполняемого в адресном пространстве пользователя (userspace)" и "Анализ безопасности кода ядра".

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

Различные дистрибутивы по-разному находят компромисс между защищенностью и производительностью/поддержкой кода программного обеспечения. В статье сравнивается пять популярных дистрибутивов актуальных версий: Debian 5.0.4, Fedora 13, OpenSUSE 11.2, Ubuntu 10.04 и Gentoo (не перекомпилированная стабильная Hardened-ветка дистрибутива, Stage 3). По мнению авторов статьи, первые четыре из перечисленных дистрибутивов лидируют по количеству инсталляций, а Hardened-версия Gentoo выбрана как демонстрация дистрибутива, который включает в себя практически все известные методы защиты кода.

Сравнение проводилось в виртуальной среде KVM и с включенным NX-битом (защита от выполнения в сегменте данных) на процессоре Intel в 32-разрядном режиме. Сравнение выполнялось при помощи модифицированного скрипта checksec.sh. В тестах выполнялась проверка процессов в графической (X11) пользовательской сессии, организованной через ssh (в сессии присутствовал sshd) и работающего web-браузара Mozilla Firefox. Стоит отметить, что количество процессов, инициированных графической сессии может существенно отличаться в различных дистрибутивах, например, от 34 в Gentoo до 96 - в сессии Ubuntu.
Выполнялось сравнение следующих методов:

  • RELRO - защищает структуры исполняемого ELF-файла (изменение которых позволяет взломщику изменить ход выполнения программы) путем модификации секций PLT (Procedure Linking Table) или GOT (Global Offset Table) ELF-файла. При полном RELRO, вся таблица GOT перед началом исполнения в памяти помечается доступной только для чтения и таким образом предотвращает свою модификацию потенциальным злоумышленником. Частичный режим RELRO защищает только PLT. Кроме того, оба метода реорганизуют структуры данных ELF таким образом, что упомянутые таблицы помещаются перед остальными структурами данных ELF, что затрудняет для атакующего кода возможность расширения GOT и PLT. Так как RELRO требует, чтобы все связи исполняемого кода были разрешены до начала его работы, это может привести к заметному ухудшению производительности при старте программ, которые требуют для работы большого количества разделяемых библиотек (shared libraries).
  • Тесты показали, что Debian и Fedora практически не используют RELRO, частичный режим RELRO реализован для всех процессов в SuSE и Ubuntu (для наиболее критичных, как dbus-daemon используется полный RELRO). В Gentoo - напротив для всех процессов реализован полный RELRO, за исключением Xorg-сервера, собранного с частичном RELRO.

  • Stack Smashing Protection (SSP) - защита от разрушения стека, называемая еще канареечной проверкой (канарейки в угольных шахтах в Англии до появления химических анализаторов воздуха использовались как индикаторы метана, до того как смесь становилась взрывоопасной - прим. пер). Эта защита базируется на помещении в стек маленьких меток - случайных чисел, генерируемых при старте программы, которые проверяются при работе со стеком, обычно при завершении работы функции. Вредоносный код переполнения буфера обычно помещается в стек и, таким образом, разрушает метки. Работа механизмов SSP обнаруживает разрушение и аварийно завершает взломанный процесс.
    Тесты показали, что SSP интенсивно используется Fedora, SuSE и Ubuntu - около 80% процессов используют эту защиту, а Debian и Gentoo - почти не используют (10%).

  • FORTIFY_SOURCE - свойство компилятора, который автоматически подменяет незащищенные от переполнения буфера библиотечные функции их защищенным эквивалентом, таким образом пытаясь защитить код от уязвимости, связанной с переполнением стека. Подробнобное описание FORTIFY_SOURCE можно получить здесь и здесь.
    Тесты показали интенсивное использование FORTIFY_SOURCE во всех сравниваемых дистрибутивах, кроме Debian данный метод применяется для порядка 80% процессов, а в Hardened Gentoo - для почти 90%.

  • PIC/PIE (Position Independent Code/Executable) - исполняемый позиционно-независимый код. Возможность предсказания где какие области памяти находятся в адресном пространстве процесса безусловно является подспорьем для взломщика. Несмотря на свойства операционных систем по случайному размещению пользовательского кода в памяти, большинство пользовательских программ продолжают загружаться и выполняться с предопределенного адреса виртуальной памяти процесса, так как не скомпилированы с опцией PIE. Напротив, использование PIE позволяет операционной системе загружать секции исполняемого кода в память произвольным образом, что существенно усложняет взлом. Понятно, что в 64-битных системах эта возможности обеспечивается лучше, чем в 32-битных - благодаря бóльшему по размеру виртуальному адресному пространству процесса.
    В исследуемых инсталляциях Gentoo показал использование PIE для 100% работающих процессов, в то время как в остальных рассматриваемых дистрибутивах процент был много меньше - от 8% в Debian до 21% в SUSE. Из остальных дистрибутивов стоит отметить, что только в Ubuntu, с данной опцией был собран браузер Firefox, который безусловно можно причислить к потенциально часто атакуемым.

Описанные выше методы применимы к процессам, работающим в пользовательском адресном пространстве Linux (userspace), и работа большинства из них невозможна без соответствующей поддержки ядра Linux. Представленное далее сравнение затрагивает только возможности ядра для обеспечения рассмотренных методов защиты пользовательского кода (а иногда относится к аспектам функционирования самого ядра) и не касается механизмов SELinux, Grsecurity RBAC и AppArmor.

Безопасность ядра имеет очень большое значение, так как возможность выполнения даже незначительно вредоностного кода в режиме ядра может сделать бесполезной всю систему безопасности userspace, описанную выше. Тестирование проводилось на тех же дистрибутивах - Debian (версия ядра 2.6.26-2-686), Fedora (2.6.33.6-147.fc13.i686), Gentoo (2.6.32-hardened-r9), OpenSuse (2.6.31.12-0.2-default) и Ubuntu (2.6.32-23-generic). Рассматривались параметры:

  • mmap_min_addr (/proc/sys/vm/mmap_min_addr) - минимальный адрес виртуальной памяти userspace, который может быть назначен пользовательской программе. Может иметь определенный смысл в контексте безопасности, когда код злоумышленника может спровоцировать разыменование NULL-указателя в коде ядра. Минимальным адресом указывается ненулевое значение так как по нулевому адресу может быть помещен предварительно подготовленный исполняемый код, который может быть теоретически выполнен.
    Все тестируемые дистрибутивы устанавливают значение данного параметра в 4096 или 65536. Во втором случае система делает невозможным выполнение программы в первых 64Kb виртуальной памяти. Заметим, что значение 4096 также усложняет доступ к нулевой странице, но не делает его невозможным. Также следует отметить, что не все пользовательские программы работают корректно при невозможности доступа к первым 64Kb виртуальной памяти (напирмер, wine требует установки mmap_min_addr в 0).
  • randomize_va_space (/proc/sys/kernel/randomize_va_space) - указывает на то, какие секции пользовательских программ при старте могут получать случайные адреса: значение 0 отключает эту возможность, "1" - дает возможность случайно распределять адреса для стека, VDSO (Virtual Dynamically-linked Shared Object, linux-gate.so - разделяемой библиотеки предоставляющей таблицу системных вызовов) и адресов для работы вызова mmap(). Значение randomize_va_space также предполагает случайное распределение выполняемых секций пользовательских процессов и разделяемых библиотек, скомпилированных в режиме PIC/PIE. Значение "2", дополнительно к предыдущему выделяет случайный виртуальный адрес для "кучи" (process heap).Для всех тестируемых дистрибутивов значение randomize_va_space установлено в "2", однако замечено, что в Debian начальный адрес "кучи" постоянен для всех процессов, т.е поведение системы согласуется с установкой randomize_va_space в "1".
  • paxtest - набор программных средств, разработанное Питером Буссером (Peter Busser) и Брэдом Шпенглером (Brad Spengler) для тестирования различных механизмов защиты памяти. Суть метода в попытке выполнить случайный код различными способами в различных областях памяти с использованием различных техник. Результаты проверки представлены в следующей таблице:
DebianFedoraGentooOpenSuseUbuntu
Executable anonymous mappingVulnerableKilledKilledVulnerableKilled
Executable bssVulnerableKilledKilledVulnerableKilled
Executable dataVulnerableKilledKilledVulnerableKilled
Executable heapVulnerableKilledKilledVulnerableKilled
Executable stackVulnerableKilledKilledVulnerableKilled
Executable shared library bssVulnerableVulnerableKilledVulnerableVulnerable
Executable shared library dataVulnerableVulnerableKilledVulnerableVulnerable
Executable anonymous mapping (mprotect)VulnerableVulnerableKilledVulnerableVulnerable
Executable bss (mprotect)VulnerableKilledKilledVulnerableVulnerable
Executable data (mprotect)VulnerableKilledKilledVulnerableVulnerable
Executable heap (mprotect)VulnerableKilledKilledVulnerableVulnerable
Executable stack (mprotect)VulnerableVulnerableKilledVulnerableVulnerable
Executable shared library bss (mprotect)VulnerableVulnerableKilledVulnerableVulnerable
Executable shared library data (mprotect)VulnerableVulnerableKilledVulnerableVulnerable
Writable text segmentsVulnerableVulnerableKilledVulnerableVulnerable
Return to function (strcpy)VulnerableVulnerableVulnerableVulnerableVulnerable
Return to function (memcpy)VulnerableVulnerableVulnerableVulnerableVulnerable
Return to function (strcpy, PIE)VulnerableVulnerableVulnerableVulnerableVulnerable
Return to function (memcpy, PIE)VulnerableVulnerableVulnerableVulnerableVulnerable

Как видно из результатов тестов, ядра всех тестируемых дистрибутивов подвержены уязвимостям типа "return-to-function", позволяющим вредоносному коду использовать корректные системные функции в своих целях. Атаки такого типа достаточно сложно отличить от "легального" кода. Лучшая защищенность может быть достигнута с использованием 64-битного адресного пространства, так как согласно данной публикации 32-битное адресное пространство может быть просто просканировано вредоносным кодом для поиска искомого значения данных.

Следует отметить, что кроме Hardened Gentoo с патчем от Grsecurity, ядра других дистрибутивов в большей или меньшей степени подвержены атакам, в частности, Debian и OpenSuSE не предоставляют дополнительной защиты, в соответствии с paxtest. При этом в Fedora и Ubuntu не дают возможности записывать данные в определенные области памяти с последующем выполнением этих данных. Ядро Fedora даже выдержало тесты с сегментами памяти данных, в которые была попытка записи кода с последующим его выполнением. Однако у всех, кроме Hardened Gentoo, ядер сегмент с выполнимым кодом программы (text) оказался доступным для записи. Это делается намеренно, когда код программы или разделяемой библиотеки не является позиционно независимым и может потребоваться его легальное перемещение (загрузчиком, во время выполнения). Другой пример, когда требуется перемещение кода, это так называемые функции-трамплины - вложенные функции, генерируемые gcc. Подробнее о таких функциях написано в документации на gcc - здесь и здесь.

Еще один результат paxtest касается случайного распределения объектов в адресном пространстве процесса:


DebianFedoraGentooOpenSuseUbuntu
Anonymous mapping randomisation test9 bits12 bits17 bits12 bits12 bits
Heap randomisation test (ET_EXEC)No randomisation14 bits23 bitsNo randomisation13 bits
Heap randomisation test (PIE)12 bits18 bits23 bits12 bits14 bits
Main executable randomisation (ET_EXEC)No randomisationNo randomisation15 bitsNo randomisationNo randomisation
Main executable randomisation (PIE)12 bits12 bits15 bits12 bits12 bits
Shared library randomisation test10 bits3 bits17 bits10 bits12 bits
Stack randomisation test (SEGMEXEC)10 bits19 bits23 bits19 bits19 bits
Stack randomisation test (PAGEEXEC)10 bits19 bits23 bits19 bits19 bits


paxtest по разному выполняет проверку для обычного и PIC/PIE-кода. Правила случайного распределения памяти основаны на количестве битов, используемых для вычисления случайного адреса, например 16-битное значение дает 2^16=65536 вариантов, и в среднем на поиск искомого адреса злоумышленнику нужно будет сделать 32К переборов. Из тестов видно, что ядра всех, кроме Hardened Gentoo предлагают примерно одинаковую степень энтропии в вычислении случайного адреса. Исключение тут делается в ядре Fedora с 3bit entropy для разделяемых библиотек с позиционно-независимым кодом.

Главный вывод из написанного состоит в том, что ни один из рассмотренных дистрибутивов, кроме, пожалуй, Hardened Gentoo, не уделяет должного внимания безопасности.

Источник http://www.opennet.ru/opennews/art.shtml?num=27938