Підтримка Windows Vista з пакетом оновлень 1 (SP1) завершується 12 липня 2011 р. Щоб і надалі отримувати оновлення системи безпеки для Windows, переконайтеся, що ви використовуєте Windows Vista з пакетом оновлень 2 (SP2). Докладні відомості див. на веб-сторінці корпорації Майкрософт: підтримка деяких версій Windows завершується.
Коли програма динамічно завантажує бібліотеку динамічного компонування (DLL) без зазначення повного шляху, Windows намагається знайти бібліотеку DLL, виконавши пошук у визначеному наборі каталогів. Якщо зловмисник отримує контроль над одним із каталогів, вони можуть змусити програму завантажити зловмисну копію DLL замість DLL, на яку вона очікувала. Ці атаки відомі як "атаки попереднього завантаження DLL" і є спільними для всіх операційних систем, які підтримують динамічне завантаження спільних бібліотек DLL. Наслідком таких атак може бути те, що зловмисник може виконати код у контексті користувача, який запускає програму. Під час запуску програми з правами адміністратора це може призвести до локального підвищення прав. Ми знаємо про відновлення інтересу до цих атак. Щоб обмежити вплив цієї проблеми на наших взаємних клієнтів, ми випускаємо цей документ спільноті розробників, щоб переконатися, що вони знають про цю проблему та мають необхідні інструменти для вирішення цієї проблеми в їхніх програмах.
Зведення
Опис атак попереднього завантаження DLL
Атаки на основі loadLibrary
Коли програма динамічно завантажує бібліотеку DLL без зазначення повного шляху, Windows намагається знайти цю бібліотеку DLL за допомогою лінійного пошуку за допомогою правильно визначеного набору каталогів, відомого як "Порядок пошуку DLL". Якщо Windows знайде бібліотеку DLL у порядку пошуку DLL, вона завантажить цю бібліотеку DLL. Однак, якщо Windows не вдається знайти бібліотеку DLL в будь-якому з каталогів у порядку пошуку DLL, це поверне помилку завантаження DLL. Нижче наведено порядок пошуку бібліотеки DLL для функцій LoadLibrary та LoadLibraryEx , які використовуються для динамічного завантаження DLL-бібліотек:
- Каталог, з якого завантажено програму
- Системний каталог
- 16-розрядний системний каталог
- Каталог Windows
- Поточний робочий каталог (CWD)
- Каталоги, перелічені в змінну середовища PATH
Нижче описано такий сценарій.
- Програма завантажує бібліотеку DLL, не вказуючи повний шлях, який вона очікує знайти в CWD програми.
- Програма повністю готова до обробки інциденту, коли не вдається знайти бібліотеку DLL.
- Зловмисник знає цю інформацію про програму та керує CWD.
- Зловмисник копіює власну спеціально створену версію DLL у CWD. Припускається, що зловмисник має дозвіл на це.
- Windows шукає каталоги в порядку пошуку DLL і знаходить бібліотеку DLL у CWD програми.
У цьому випадку спеціально створений DLL запускається в програмі і отримує права поточного користувача.
Рекомендації
Щоб запобігти цій атаці, програми можуть видалити поточний робочий каталог (CWD) зі шляху пошуку DLL, викликавши API SetDllDirectory за допомогою пустого рядка (""). Якщо програма залежить від завантаження бібліотеки DLL з поточного каталогу, отримайте поточний робочий каталог і скористайтеся цим файлом, щоб пройти повністю кваліфікований шлях LoadLibrary.
Ми також знаємо, що деякі розробники використовують LoadLibrary для перевірки наявності певної бібліотеки DLL, щоб визначити, яку версію Windows використовує користувач. Пам'ятайте, що це може зробити програму вразливою. Якщо бібліотека, на яку впливає проблема, дійсно не існує у випуску Windows, у якій виконується програма, зловмисник може ввести бібліотеку з таким іменем у CWD. Ми наполегливо рекомендуємо не використовувати цей метод. Натомість використовуйте рекомендовані методи, описані в статті MSDN "Отримання версії системи".
Програма, яка завантажує компоненти plug-in сторонніх постачальників і які не можуть змусити плагіни використовувати відповідний шлях для викликів LoadLibrary, має викликати SetDllDirectory(""), щоб видалити CWD, а потім викликати SetDllDirectory("місце інсталяції плагіна"), щоб додати каталог інсталяції плагіна до шляху пошуку DLL.
Атаки на основі SearchPath
Подібна атака існує, коли програма використовує API SearchPath, щоб знайти бібліотеку DLL і динамічно завантажити шлях, який повертає searchPath. Нижче наведено стандартний порядок пошуку для API SearchPath:
- Каталог, з якого завантажено програму
- Поточний робочий каталог (CWD)
- Системний каталог
- 16-розрядний системний каталог
- Каталог Windows
- Каталоги, перелічені в змінну середовища PATH
Ми не радимо використовувати цей шаблон, оскільки він не захищений. Не радимо використовувати функцію SearchPath як метод пошуку файлу .dll, якщо цільове використання виводу викликає функцію LoadLibrary. Це може призвести до пошуку неправильного файлу .dll, оскільки порядок пошуку функції SearchPath відрізняється від порядку пошуку, який використовується функцією LoadLibrary. Якщо потрібно знайти та завантажити файл .dll, скористайтеся функцією LoadLibrary.
ShellExecute і CreateProcess
Мовні формати цих проблем також можуть існувати, коли розробники викликають подібні функції, як-от ShellExecute і CreateProcess , щоб завантажити зовнішні виконувані файли. Радимо розробникам бути обережними під час завантаження двійкових файлів і вказати повний шлях. Це має становити меншу складність під час завантаження двійкового файлу замість бібліотеки.
Рекомендовані кроки для розробників програмного забезпечення
Ми рекомендуємо розробникам виконати такі дії:
Перевірте їхні програми на наявність екземплярів незабезпечених завантажень бібліотек (приклади з них наведено далі в цій статті). До них належать такі дії:
- Використання searchPath для визначення розташування бібліотеки або компонента.
- Використання LoadLibrary для визначення версії операційної системи.
Використовуйте повні шляхи для всіх викликів loadLibrary, CreateProcess і ShellExecute, де це можна зробити.
Упровадьте виклики до SetDllDirectory із пустим рядком ("") для видалення поточного робочого каталогу з порядку пошуку DLL за промовчанням, де це потрібно. Пам'ятайте, що SetDllDirectory впливає на весь процес. Таким чином, ви повинні зробити це один раз на початку процесу ініціалізації, а не до і після викликів loadLibrary. Оскільки SetDllDirectory впливає на весь процес, кілька потоків, які викликають SetDllDirectory з різними значеннями, можуть спричинити невизначену поведінку. Крім того, якщо процес призначено для завантаження DLL сторонніх постачальників, тестування знадобиться, щоб визначити, чи не спричинить налаштування процесу несумісності. Відома проблема полягає в тому, що, коли програма залежить від Visual Basic for Applications, параметр процесу може призвести до несумісності.
Скористайтеся функцією SetSearchPathMode , щоб увімкнути безпечний режим пошуку процесів для цього процесу. Поточний робочий каталог переміщується в останнє місце в списку пошуку SearchPath за весь час виконання процесу.
Намагайтеся не перевіряти наявність DLL-бібліотек, не вказуючи повний шлях, навіть якщо безпечний режим пошуку ввімкнуто, оскільки це все одно може призвести до атак попереднього завантаження DLL.
Інструкції з визначення незахищених завантажень бібліотеки
У вихідному коді нижче наведено приклади незахищених завантажень бібліотеки:
У наведеному нижче прикладі коду програма шукає "schannel.dll", використовуючи найменш безпечний шлях пошуку. Якщо зловмисник може розмістити schannel.dll в CWD, він завантажиться навіть до того, як програма шукатиме відповідні каталоги Windows.
DWORD retval = SearchPath(NULL, "schannel", ".dll", err, result, NULL); HMODULE handle = LoadLibrary(result);У наведеному нижче прикладі коду програма намагається завантажити бібліотеку з різних розташувань програми та операційної системи, описаних на початку цього документа для виклику LoadLibrary(). Якщо існує ризик, що файл відсутній, програма може спробувати завантажити файл з поточного робочого каталогу. Цей сценарій трохи менш небезпечний, ніж у попередньому прикладі. Однак, він як і раніше піддає користувача програми ризику, якщо середовище не повністю передбачувані.
HMODULE handle = LoadLibrary("schannel.dll");
Нижче наведено приклади кращих і безпечніших завантажень бібліотеки.
У наведеному нижче прикладі коду бібліотека завантажується безпосередньо за допомогою повного шляху. Зловмисник не може ввести зловмисний код, якщо він не має дозволів на записування до цільового каталогу програми.
HMODULE handle = LoadLibrary("c:\\windows\\system32\\schannel.dll");Примітка. Відомості про визначення системного каталогу див. в таких ресурсах:
Отримати каталог системи
http://msdn.microsoft.com/en-us/library/ms724373%28VS.85%29.aspx ShGetKnownFolderPath
http://msdn.microsoft.com/en-us/library/bb762188%28v=VS.85%29.aspxУ наведеному нижче прикладі коду поточний робочий каталог видаляється зі шляху пошуку перед викликом LoadLibrary. Це значно знижує ризик, оскільки зловмиснику доведеться керувати каталогом програм, каталогом Windows або будь-якими каталогами, указаними на шляху користувача, щоб використовувати атаку попереднього завантаження DLL.
SetDllDirectory (""); HMODULE handle = LoadLibrary("schannel.dll");У всіх системах, у яких інстальовано оновлення системи безпеки 963027 (описане в MS09-014), наведений нижче код остаточно перемістить CWD на останнє місце в порядку пошуку. Будь-які пізніші виклики до функції SetSearchPathMode зсередини цього процесу, які намагаються змінити режим пошуку, завершаться помилкою.
SetDllDirectory (""); HMODULE handle = LoadLibrary("schannel.dll");У наведеному нижче прикладі коду поточний робочий каталог видаляється зі шляху пошуку перед викликом LoadLibrary. Це значно зменшує ризик, оскільки зловмиснику доведеться керувати каталогом програм, каталогом Windows або каталогами, указаними на шляху користувача, щоб використовувати атаку попереднього завантаження DLL.
SetSearchPathMode (BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE | BASE_SEARCH_PATH_PERMANENT ); HMODULE handle = LoadLibrary("schannel.dll");
Використання монітора процесу для динамічного виявлення незахищених завантажень
Корпорація Майкрософт публікує засіб під назвою "Монітор процесів". Цей засіб дає змогу розробникам і адміністраторам уважно відстежувати поведінку запущеного процесу. За допомогою монітора процесів можна динамічно визначити, чи може один із ваших програм бути вразливим до такого роду проблем.
Щоб завантажити монітор процесів, відвідайте таку веб-сторінку Microsoft:
http://technet.microsoft.com/en-us/sysinternals/bb896645.aspxСпробуйте запустити програму за допомогою CWD, установленого в певному каталозі. Наприклад, двічі клацніть файл із розширенням, обробник файлів якого призначено вашій програмі.
Настройте монітор процесів за допомогою таких фільтрів:
Якщо ви потрапите на вразливий шлях, відобразиться приблизно такий вигляд:
Виклик віддаленої спільної спільної сторінки файлів для завантаження DLL-файлу вказує на те, що це вразлива програма.
Додаткові відомості
Щоб отримати додаткові відомості, відвідайте такі веб-сторінки Microsoft:
Порядок пошуку бібліотеки динамічних посилань
http://msdn.microsoft.com/en-us/library/ms682586(VS.85).aspx Документація MSDN до функції SearchPath
http://msdn.microsoft.com/en-us/library/aa365527(VS.85).aspx Документація MSDN щодо функції LoadLibrary
http://msdn.microsoft.com/en-us/library/ms684175(VS.85).aspx Документація MSDN до функції SetDllDirectory
http://msdn.microsoft.com/en-us/library/ms686203(VS.85).aspx Документація MSDN до функції SetSearchPathMode
http://msdn.microsoft.com/en-us/library/dd266735(VS.85).aspx Запис блоґу Девіда Леблана, головного інженера з безпеки з Microsoft Office
http://blogs.msdn.com/b/david_leblanc/archive/2008/02/20/dll-preloading-attacks.aspx Запис блоґу Ендрю Ротса, команди інженерів MSRC щодо атак попереднього завантаження DLL