24 августа 2010 в 19:04

Концептуальная уязвимость в механизме загрузки DLL (MSA2269637)

На прошлой неделе на Хабре уже писали о заявлении HD Moore и найденной им уязвимости, которая содержится в достаточно большом количестве приложений и работает на всех версиях MS Windows. Но все оказалось куда серьезнее, так как речь идет не просто о найденной уязвимости, а о концептуальной ошибке в дизайне механизма загрузки динамических библиотек. По этому поводу вчера Microsoft официально выпустила Security Advisory (2269637), что означает официальное признание серьезности данной уязвимости. Но давайте попробуем разобраться в сути этой проблемы, так как она ничуть не менее серьезная, нежели недавно найденная уязвимость в загрузке LNK-файлов.

Уязвимость заключается в том, что многие программы при вызове функции LoadLibrary() не проверяют корректность пути, по которому эта библиотека может быть загружена. Таким образом, они позволяют произвести подмену выполняемой библиотеки. Это связано с тем, что поиск загружаемой библиотеки осуществляется в первую очередь в директории, содержащей образ исполняемого файла, который породил процесс (подмененная библиотека выполняется с привилегиями пользователя, запустившего процесс). К примеру, Georgi Guninski предложил следующую демонстрацию (PoC) данной уязвимости:

1) Скомпилировать разработанный им код, как динамическую библиотеку
2) Переименовать получившуюся библиотеку в riched20.dll и поместить в любую директорию на ваш выбор
3) Проверить, есть ли открытые приложения из пакета MS Office. И если есть, тогда закрыть их
4) Отрыть документ MS Word при помощи двойного клика по нему из Windows Explorer в той директории, куда была помещена наша riched20.dll

По большому счету, такого рода уязвимости приложений не новое веяние, и известны они были уже давно. Например, об этой проблеме David LeBlanc писал (“DLL Preloading Attacks”) еще в 2008 году. Другое дело в том, что проблема существует до сих пор и количество приложений, уязвимых таким образом, по-прежнему очень велико. Самое страшное и поразительное то, что подмену можно осуществить не только на локально расположенную DLL, но и загрузить удаленно расположенную библиотеку. Примером для демонстрации этой возможности послужила уязвимость для iTunes, которая при открытии медиа-файлов с сетевых ресурсов могла подгружать динамические библиотеки из этого же сетевого хранилища. Для успешной эксплуатации нужно лишь сформировать SMB или WebDAV путь (к примеру, такой: \\server\movies\) к сетевому ресурсу, и чтобы при запуске файла в этой же директории располагалась динамическая библиотека, которую мы хотим выполнить. Для проведения атак подобного рода уже реализован универсальный эксплойт в составе проекта Metasploit (пример использования описан тут).

Теперь давайте поговорим о том, что с этим делать и как этого можно избежать в своих программах. Вероятнее всего, на закрытие этой уязвимости уйдёт немало времени у разработчиков, ведь уязвимость содержится в архитектуре механизма выполнения динамических библиотек. И закрыть ее, не повлияв на работоспособность уже имеющегося софта, будет не так то просто. Итак, во-первых, существует реализация функции SafeLoadLibrary() от David LeBlanc и best practices от MS:

HMODULE SafeLoadLibrary(const wchar_t* wzFileName)
{
static wchar_t wzSystem[MAX_PATH];
wchar_t wzCurDir[MAX_PATH];
HMODULE hMod = NULL;
if(wzSystem[0] == L'\0')
{
if(GetSystemDirectory(wzSystem, _countof(wzSystem)) == 0)
return NULL;
}

// Now get the actual current working directory
if(GetCurrentDirectory(_countof(wzCurDir), wzCurDir) == 0)
wzCurDir[0] = L'\0';
SetCurrentDirectory(wzSystem);
hMod = LoadLibrary(wzFileName);
SetCurrentDirectory(wzCurDir);
return hMod;
}


Так же существует утилита DLL Hijacking Audit Tool, созданная Rapid7/HDmoore, для поиска уязвимых приложений и рекомендации от MS.
Автор: @SVH
ESET NOD32
рейтинг 134,92
Похожие публикации

Комментарии (73)

  • 0
    «У нас есть отличный механизм. Но оказалось, что он уязвим. Пожалуйста, не используйте данный механизм, либо ставьте приложения на костыли.»

    Microsoft такой Microsoft.
    Хотя, если разработчик является параноиком и проверяет всё и вся, в том числе и в языках со строгой типизацией, программа вряд ли будет уязвима, хоть и несколько монструозна.
    • +27
      А при чем здесь Microsoft? Сменить текущую директорию конечно же существенно проще, чем LD_LIBRARY_PATH или LD_PRELOAD.
      Автор поста не читатель — автор писатель, ведь его же собственная ссылка указывает на best practices, которые английским по белому указывают на SetDllDirectory:
      If this parameter is an empty string (""), the call removes the current directory from the default DLL search order.

      А пост LeBlanc, из котого автор вытащил кусок кода, прямым текстом заявляет:
      Note that if you can call SetDllDirectory(""), as I documented in my previous post, then you should do that, as it is easier and will solve the problem for all your LoadLibrary calls. If you cannot do that, here's a code sample that will fix individual calls for you.

      О чем автор, предусмотрительно, «забыл» упомянуть, подразумевая, что тот быдлокод обязателен для всех разработчиков.

      А начинается все со страшилок про то, что существует уязвимость, которая не менее опасна, чем недавно запатченная RCE, но известная как минимум два года и нигде не использующаяся. Удаленный вектор крайне трудно реализуем (drive-by не работает: пользователю нужно вручную сменить текущую директорию на что-нибудь, контроллируемое злоумышленником и запустить оттуда файл).

      И это не говоря про довольно вольное понимание автором термина «архитектура» и о том, что общесистемный патч для тех, кому это нужно уже выпущен (но рекомендовано применять его крайне осторожно, потому что это может нарушить совместимость с некоторыми приложениями).

      Пост надо переименовать в «По стопам alizar: художественное искажение фактов for fun and profit».
      • +1
        > и запустить оттуда файл
        Уточню: запустить оттуда файл, ассоциированный с уязвимым приложением.
      • 0
        О чем автор, предусмотрительно, «забыл» упомянуть, подразумевая, что тот быдлокод обязателен для всех разработчиков.


        Если API дейстительно настолько прост и понятен как вы говорите, то возникают два вопроса:

        1. Зачем делать режим, в котром уязвимость возможна, режимом по умолчанию, и давать «best practices» совет: всегда отключайте этот дурацкий режим — вызывайте SetDllDirectory("")?

        2. Почему даже соведний отдел того же Microsoft не смог разобраться в «простом и понятном» API и написал «быдлокод»?
        • +1
          1. Совместимость. И да, по умолчанию, ее ОЧЕНЬ трудно использовать (но эппл смогли — молодцы).
          2. Вы тоже «не читатель»? Я даже процитировал слова LeBlanc.
          If you cannot do that, here's a code sample that will fix individual calls for you.

          Это не для всех. Это только для тех, кто почему то (почему?) не может использовать нормальное API.
          • –3
            1. Сколько программ поломается из-за внезапной смены режима по умолчанию? Сколько приложений загружает библиотеки из текущего каталога и при этом текущим каталогом не является каталог установки приложения? Несколько сотен? А популярных? Десяток? Так эта проблема для конкретно этих приложений исправляется при помощи специально изобретённого в Microsoft средства подставляния костылей обеспечения совместимости — shims.

            2. Сам вы не читатель. Я задал вполне конкретный вопрос — почему даже в соседнем отделе не смогли разобраться с «понятным» API. Вы ответили на него? Нет, назвали меня «не читателем».
            • 0
              1. Режим по умолчанию, как я уже сказал, не загружает из текущей директории то, что есть в системных или директории, из которой запущено приложение.
              2. Уязвимость не подтверждена, если Вы об офисе. Кроме того, сомневаюсь, что там «не могут» (не разобрались) использовать нормальное API и вместо этого меняют текущую директорию каждый раз перед LoadLibrary. Если Вы не об этом — прошу раскрыть свою мысль.
              • –1
                1.… но загружает из текущего каталога те, которые загрузились бы через %PATH%.

                2. Исходя из истории, у MS на протяжении месяцев могут висеть «официально не подтверждённые» уязвимости, которые уже во всю используются.
                • –1
                  1. Да. Но загрузка чего нибудь не из системной директории и не из одной директории с исполняемым файлом — КРАЙНЕ редкая вещь в мире Windows. И именно для таких случаев сделан SetDllDirectory
                  2. Я не о том подтверждении. Официально-то как раз все подтверждено (кстати, интереса ради, не затруднит привести ссылку на уязвимость, «известную всем, кроме Microsoft»?). Я о других подтверждениях в этом топике (Word 2010 и 2007 не загружают PoC dll-ку).
                  • 0
                    Не передёргивайте, в обоих случаях.

                    1. Да, это редкая вещь! И она, непонятно почему, включена по умолчанию — программа может найти библиотеки, лежащие в %PATH%. А до этого она найдёт ещё и библиотеки из текущего каталога. Зачем оставлять это включённым по умолчанию? Чтобы всем потом выключать через SetDllDirectory("")? Всё равно те, кому нужно что-то нестандартное, будут при помощи всё той же SetDllDirectory настраивать пути для себя?

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

                    2. Из того, о чём писал я: habrahabr.ru/blogs/microsoft/64910/

                    Что интересно, первое сообщение про уязвимость было отправлено в Microsoft 25 августа 2008, а рабочий пример использования уязвимости — 22 сентября 2008. Таким образом, уязвимость оставалась не закрытой 323 дня.
                    • 0
                      1. «Зачем оставлять это включённым по умолчанию?»
                      Как раз потому, что если приложение УЖЕ делает что-то нестандартное (загружает dll-ку из PATH), то неявная смена поведения скорее «поломает» это приложение насовсем, чем «починит» уязвимость в нем.
                      2. Передергивания здесь нет. Office двух последних версий (минимум) не загружает PoC.

                      Что же до уязвимостей. К превеликому сожалению, не могу проверить Ваши слова.
                      По первой ваши же ссылки ведут на CVE, idefence, vupen и прочая. Все как один датированы июлем 2009. Более того, я нашел эту уязвимость на секунии и увидел все тот же «Release Date 2009-07-14». Не могли бы Вы привести ссылки на disclosure летом 2008-го?

                      По второй «Release Date 2009-08-11», закрыта 14-го.

                      На всякий случай отмечу, что открытие деталей об уязвимости вместе с патчем — общепринятая практика. Вы же утверждали, что MS (месяцами) официально не признает disclosed уязвимости — не могли бы Вы привести более убедительные ссылки?
                      Вот с Apple — знаю, с Microsoft — не знаю (но могу и просто заблуждаться).
                      • –1
                        1. Неявная смена поведения может быть вполне явной. Готовилась к выпуску Windows 7. Как написано в статье, уязвимость была известна ещё в начале 2008 года, так что вполне можно было её закрыть хотя бы в Windows 7. После выпуска беты Windows 7 все обнаружили, что очень много кривых программ не работает. Если бы их стало на сотню больше, никто бы не обратил внимания.

                        2. Я говорил об уязвимостях, которые во всю используются. Вам вряд ли кто-то скажет, сколько эта уязвимость ходила в привате.
                        • 0
                          1. Ну я не могу ответить за MS. В любом случае я вижу только одну кривую программу, имеющую отличимую от нуля популярность — iTunes. Большинство остального — скорее всего какие нибудь in-house быдлопрограммы, выпустить shim-ы для которых будет проблематично и при этом беспокоиться о безопасности таких программ не приходится.
                          2. Не могу проверить информацию про «во всю используются». Скорее речь шла про responsible disclosure (или, как оно теперь называется, CVD).

                          Кстати, у MS есть достаточно неплохие средства для телеметрии использования уязвимости in-the-wild, так что выбор стоит между «Сообщить той сотне-тысяче пользователей всю информации и пара процентов из них самостоятельно предпримет какие то шаги» и «Не сообщать до выпуска патча и не ставить под удар МИЛЛИАРД остальных пользователей». Общепринятая практика даже при меньших масштабах.

                          Если посмотреть на историю msblast, sasser, conficker (и большинство остальных нашумевших эпидемий) начинались через МЕСЯЦЫ после выпуска патча (собственно сами уязвимости, использованные в этих червях, были получены реверсингом патчей). То есть пользователи уведомлены и им предоставлены средства для того, чтобы обезопасить себя, им на каждом углу трубят об эпидемии, чтоб защититься от которой нужно всего лишь применить патч — а они все игнорируют.
                          • 0
                            1. Ну вот видите, только одна кривая программа на самом деле. Так что вполне можно было всё менять: Apple бы заранее выпустила апдейт, программисты кривых in-house программ получили бы +1 тикет, что после установки апдейта их поделка не работает.

                            2. А самые интересные взломы происходят с помощью неизвестных или 0day уязвимостей. Огромный ботнет можно получить просто разослав по email или ICQ спам «запусти, это мини-игра» — вообще без программных уязвимостей.
                            • 0
                              1. Ну здесь я вижу возможные причины для обоих вариантов. MS должны были выбрать один — я не могу судить о настоящих причинах, побудивших их выбрать данный конкретный вариант (хотя если бы такое решение зависело от меня, я бы, пожалуй, сделал так же).

                              2. Ну да. Таргетированные (с очень ограниченным распространением) атаки вполне могут долго оставаться незамеченными. Ботнеты же очень быстро попадают в honeynet-ы и блокируются первым же апдейтом антивирусных баз.
                              На моей памяти все более менее заметные ботнеты использовали или какой нибудь вариант соц. инженерии («запусти, это мини-игра») или уязвимости, запатченные несколько месяцев назад. И то и другое — вообще не Windows-специфично.
                              Более того, как раз в винде средства безопасности реализованы лучше всего.

                              Но это никаким образом не приближает нас к исходной посылке о том, какой плохой Microsoft.
      • +2
        Каюсь. Я всё таки не настолько искушён в прикладном программировании =(
        Спасибо. Много встало на свои места.
      • 0
        > А при чем здесь Microsoft? Сменить текущую директорию конечно же существенно проще, чем LD_LIBRARY_PATH или LD_PRELOAD.

        ахха. что Linuxу хорошо — Windows смерть
  • –1
    100 и 1 способ как быстро избавиться от WinXP от MS.
    • 0
      > уязвимости, которая содержится в достаточно большом количестве приложений и работает на всех версиях MS Windows.

      Не только WinXP использует DLL :). Интересно, как эта уязвимость поведет себя в Wine? :)
      • –1
        это я к тому, что за последний месяц это уже вторая глобальная уязвимость, которую исправят только для win >= vista
        • 0
          откуда инфа?
          • 0
            например отсюда www.computerra.ru/vision/548561/
            • 0
              каюсь, был введен в заблуждение автором, поддержка хп до 2014, ура товарищи)
        • +2
          поддержка хп продолжается до 2014 года (пока, потом может еще продлят).
  • +6
    Всегда удивляли функции API от Microsoft, для использования которых надо написать дополнительно кучу проверок. Неужели нельзя внести все необходимые действия внутрь функций и писать менее огромные книги по использованию своего API.
    • +3
      API низкого уровня на то и API на мой взгляд. Другое дело что библиотеки, которые их используют, должны автоматом делать эти проверки.
    • +5
      Так задумано, вот что говорит по этому поводу Реймонд Чен:

      Back in the old days, programmers were assumed to be smart and hardworking. Windows didn't provide functions for things that programs could already do on their own.

      В старые добрые времена предполагалось, что программисты — умны и старательны. Windows не предоставляла функций для того, что программы и сами могут сделать

      То есть, если проверку можно написать самому — ее нужно писать самому, а кто не может или не хочет — сам себе злой Буратино.

      В его блоге еще много язвительных замечаний и баек в духе «В конце восьмидесятых было принято, что функция должна стараться отработать даже на неверных данных. Это сейчас в таком случае следует немедленно завершить работу программы с воплями и криками». Весьма занимательное чтиво.
    • 0
      API от MS удивляли? Ну ладно, в данном случае, это просто «авторская интерпретация» собственных же ссылок. Но хотелось бы услышать с чем Вы сравниваете (чтоб не приводить примеры «мимо кассы»).
  • +2
    Да ладно, не поверю что только сейчас нашли. Это же на поверхности лежит.
    • 0
      Все гениальное просто? ;)
      • 0
        Учитывая что автор пишет одно (совершенно кстати не баг и не уязвимость)
        Гунинский второе (если это так то это серьезная уязвимость)
        А MS третье (как всегда)
        то про просто да :)
      • +9
        Ну в nix-ах не зря в PATH и LD_LIBRARY_PATH не содержится текущий каталог.
    • 0
      Мне кажется, эту штуку уже очень давно используют, по крайней мере, в каких-то книжках я читал, что правильно нужно подгружать библиотеки только по полному пути.

      А вот фокус с webdav исключительно красив.
      • +3
        Да конечно давно, я так например перехватывал DirectX в одной игре 6 лет назад.

        Создается прокси-библиотека, кидается в каталог с игрой которая ее сама подгружает без какого-либо дополнительного усилия, теперь можно рисовать в ней дополнительный интерфейс (например встроить веб-браузер), так же пишется прокси и для directinput чтобы пользователь мог еще и взаимодействовать с тем, что мы сами рисуем. В итоге получаем в игре дополнительный интерфейс.
        • +1
          Только, согласитесь, «библиотека кидается в каталог с игрой» несколько отличается от «библиотека подгружается из текущей директории».
          • +1
            Соглашусь конечно :)

            Просто лично я больше склонен считать это косяками программистов, ведь процесс загрузки не тайна и известен. Например не стоит забывать, что еще в WinXP для предотвращения любых неловкостей были введены сборки. Определились с необходимыми библиотеками, включили их в свою сборку, подписали сертификатом и получили защищенную системой сборку которая может содержать даже несколько разных версий библиотек для разных версий ваших приложений и может распространяться отдельно, а ссылка на сборки через манифесты. Прямая же загрузка библиотек — это для тех, кто знает что делает (вроде как более низкий уровень), а делать это нужно конечно же с абсолютными путями.
  • 0
    зачастили что-то в последнее время, да и уязвимости все как на подбор: с удаленным запуском произвольного кода.

    я правильно понял, что заплатки как таковой быть не может пока не перепишут все ПО?
    • +1
      Пока не перепишут всё ПО, которое имеет такую почти XSS-уязвимость, если точнее.

      Большинство софта не загружает библиотеки по непроверенным пользовательским данным.
  • НЛО прилетело и опубликовало эту надпись здесь
    • +8
      Чтобы не заменять системные достаточно того что первый путь поиска это директория с образом файла исполняемого процесса. А если загрузка происходит из директории в которой которой лежит документ это именно уязвимость.
      • НЛО прилетело и опубликовало эту надпись здесь
    • +1
      А еще лучше — держать свои дллки возле бинарника, а не в %System32%.

      Так дополнительно к защите от описанного эксплоита уменьшается риск того, что кто-то в процессе инсталляции чего-нибудь другого заменит дллку на другую версию, с которой прога несовместима вплоть до креша в неопределенный момент времени.
      • 0
        Тогда значительная часть достоинств использования дээльэлек пропадает.
        • +2
          Пусть пропадает, если вместе с ней пропадет DLL-Hell…
  • –13
    Ну что я могу сказать… Печально смотреть, Микрософт в очередной обосрался… Надеюсь, что больше таких серъёзных уязвимостей найдено не будет. Ну что это за ошибка — на проверять путь...? Достойна школьника, начинающего прогать на Бейсике.

    Радовать может только то, что постоянное нахождение ошибок в продукте — следствие повышенного внимания, а следовательно — популярности.
  • +4
    А что делает кстати этот пост в блоге нод32?
  • 0
    хм, вроде именно по этому принципу и работают прокси библиотеки, в частности для перехвата DirectX в играх? Например, широко популярная Enb Series?
    Честно, всегда думал, что это фича, а не баг, а вон как все вышло.)
    • +1
      Нередко фича в опытных руках превращается в уязвимость.
  • +2
    Интересно, а кто-нибудь запускал упомянутую демонстрацию? Самому компилить лень, а по ссылке на готовую дллку выдается 404. Но что-то мне подсказывает, что сработает она только в ХР SP1 и ниже.

    МС пишет, что начиная со второго сервиспака ХР порядок поиска ДЛЛ по умолчанию такой:

    — стартовая директория программы
    — system32
    — system
    — windows
    — текущая
    — все, что написано в PATH

    msdn.microsoft.com/en-us/library/ms682586%28VS.85%29.aspx

    Если так, то надо сильно постараться написать приложение так, чтобы уязвимость сработала. Все-таки, далеко не все прописывают пути к библиотекам в PATH, а все остальные места сработают раньше.
    • +2
      Ну iTunes вон умудрились и текущий путь сменить и делать LoadLibrary на библиотеки, не присутсвтующие нигде, выше «текущей» в Вашем списке. Виноват, естественно, Microsoft.
    • +1
      У меня на офисе не прокатила (офис 2010)
      • +1
        Спасибо, я так и думал. :)
    • +1
      Не работает. Компилил сам.
      WinXP SP2, MSO2003.
  • +2
    Не заработало. Word 2007 взял эту C:\Program Files (x86)\Common Files\Microsoft Shared\office12\riched20.dll
    • +2
      Промазал, это к

      > Georgi Guninski предложил следующую демонстрацию (PoC) данной уязвимости: 1)
  • 0
    По мне так это удобная фича, можно прокси dll'ки для игр делать.
    • 0
      Для этого не нужно грузить библиотеки из текущего каталога.
      • 0
        Как раз таки это самый безболезненный способ в некоторых случаях.
        Например отвязать курсор от окна где она привязана к окну и т.д.
        • 0
          Вы точно не путаете текущий каталог и каталог установки программы?
          • 0
            мм… уязвимость разве не в том что дллку можно подсунуть в каталог с программой?
            ведь текущий каталог проверяется как я помню после локальной и системных…
            • 0
              Если вы можете записывать в каталог программы, значит у вас уже есть права администратора — что взламывать-то?

              habrahabr.ru/company/eset/blog/102549/?reply_to=3186460#comment_3186321
              • 0
                Охо…
                Понял, надо бы проверить, а то как я помню сначала искало в месте расположения ПО, потом системные, и только потом текущий каталог.
                Хотя подозреваю что это какое-то время назад менялось (xp->vista->w7)
                Спасибо что донесли, а то в статье написано «поиск загружаемой библиотеки осуществляется в первую очередь в директории, содержащей образ исполняемого файла»…
            • 0
              нет, в каталог с программой это стандартное и задуманное поведение.
  • 0
    Про проверку пути до DLL-ки это не спасет. А что мешает при наличии в программе проверки пути до DLL-ки вместо оригинальной DLL подсунуть DLL-ку проксик с нужными функциями + прозрачный вызов фунций из оригинальной DLL которая просто переименована.
    • +6
      Права доступа на запись в системные каталоги. Если пользователь с правами администратора подменяет DLL'ки из системных каталогов, то это уже «приехали», система взломана.

      Уязвимость в чём состоит? Вам прислали по почте архив, в котором readme.doc и riched20.dll. Вы распаковали архив и даблкликнули на readme.doc, Word загрузил riched20.dll.
      • +2
        Только, как показывают эксперименты (см. выше) этот номер не проходит — грузится правильная библиотека. Возможно, хак сработает на старой версии ХР без сервиспаков, но сколько этих версий еще в ходу?
        • –2
          Скорее всего сработает не на старой XP, а на офисе < 2007.
          • 0
            Тоже может быть. Просто на старой ХР порядок поиска отличался. А что там со старым офисом — трудно сказать.
          • +3
            На 2003 тоже не работает.
        • 0
          Нет, на XP ни на какой не работает.
  • 0
    Забыл как называется, но системные стандартные DLL таким образом подменить не получается. Т.е. только те, которые идут вместе с программой. Но тут ничего не поделаешь, софтина должна сама проверять что грузит. Наверное редко это делается, потому что чаще всего смысла нет подменять такие библиотеки.
    • 0
      Те, которые идут с программой тоже заменить нельзя. Только те, которые НЕ ИДУТ с программой (как бы странно это ни звучало)

Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

Самое читаемое Разное