
Іменовані канали (named pipes) є поширеним вибором для взаємодії між програмами, що працюють на одному комп’ютері під керуванням Windows. Вони швидкі, мають пряму підтримку операційної системи та добре підходять для комунікації між службами Windows, настільними програмами, системними процесами, утилітами командного рядка та фоновими агентами.
Типова архітектура може включати привілейовану службу Windows, яка виступає сервером іменованого каналу, тоді як програма, що використовується користувачем, підключається як клієнт. Оскільки обидва процеси працюють на одному комп’ютері, розробники часто розглядають таку взаємодію як внутрішню і, отже, довірену.
На практиці канал доступний з середовища, де може працювати багато непов’язаних процесів під різними користувачами, сесіями та контекстами безпеки.
Локальне не означає довірене
Іменовані канали часто вважаються приватними, оскільки вони використовуються для взаємодії між програмами на одному комп’ютері. Однак таке припущення є небезпечним.
На робочій станції Windows можуть працювати процеси під обліковими записами LocalSystem, адміністраторів, стандартних користувачів, службових облікових записів, а також у окремих інтерактивних чи віддалених сесіях. Крім того, можуть бути встановлені сторонні програми, сценарії, діагностичні інструменти та шкідливе програмне забезпечення, що працює під компрометованим обліковим записом.
Будь-який процес, який знає ім’я каналу та має достатні права доступу, може спробувати підключитися. Windows сама по собі не знає, яку саме програму розробник мав на увазі для використання каналу.
З цієї причини іменований канал слід розглядати як відкритий локальний інтерфейс. Перед обробкою запиту програма повинна визначити, хто підключився, що дозволено цій особі робити, і чи є надані дані безпечними.
Ідентичність, контроль доступу та межі привілеїв
Ризик є найвищим, коли привілейована служба Windows взаємодіє з менш привілейованою настільною програмою.
Служба, що працює під обліковим записом LocalSystem, може мати можливість змінювати захищені файли та ключі реєстру, запускати процеси, змінювати системні налаштування, отримувати доступ до даних інших користувачів або взаємодіяти з драйверами ядра. Коли ці операції надаються через іменований канал, цей канал стає API до привілейованої функціональності.
Успішне підключення доводить лише те, що клієнт мав дозвіл відкрити канал. Воно не доводить, що:
- клієнт є очікуваною програмою;
- підключений користувач авторизований;
- запитувана операція дозволена;
- надана команда є безпечною.
Тому дозволи на доступ до каналу мають бути визначені явно та обмежені найменшим відповідним набором ідентичностей. Широкі дозволи для Everyone, Authenticated Users або всіх інтерактивних користувачів можуть дозволити непов’язаним процесам отримати доступ до каналу.
Автентифікація та авторизація також повинні залишатися окремими. Користувач може мати дозвіл запитувати статус служби, але не зупиняти її, змінювати захищені налаштування, запускати процеси або отримувати доступ до довільних файлів. Чутливі команди слід авторизувати індивідуально.
Імітація (Impersonation) може допомогти, виконуючи операції в контексті безпеки клієнта, але її слід використовувати обережно. Сервер повинен перевірити, чи вдалася імітація, обмежити роботу, що виконується під час імітації, і завжди відновлювати свою початкову ідентичність.
Боротьба з кібератаками на основі ШІ
Дізнайтеся, як надмірні дозволи можуть перетворити інструменти ШІ на серйозний ризик безпеці.
Дізнайтеся, як практична стратегія нульової довіри може допомогти стримати загрози, керовані ШІ, перш ніж вони поширяться.
Прочитати блог
Недовірені сервери, команди та дані
Клієнт повинен перевіряти сервер так само, як сервер перевіряє клієнта.
Передбачуване ім’я каналу є лише ідентифікатором. Воно не є секретом і не доводить, який процес створив канал. Зловмисник може створити канал з очікуваним ім’ям до того, як запуститься легітимний сервер, що призведе до підключення клієнта до процесу, контрольованого зловмисником.
Опція first-pipe-instance може допомогти виявити, що ім’я вже зайнято, але вона не замінює належні засоби контролю доступу або перевірку ідентичності сервера.
Повідомлення, отримані через канал, також слід розглядати як неперевірений ввід. Навіть автентифікований клієнт може надіслати:
- пошкоджені або занадто великі корисні навантаження;
- недійсні шляхи до файлів або реєстру;
- непідтримувані комбінації команд;
- серіалізовані об’єкти з пошкодженнями;
- значення, розроблені для виклику умов помилок.
Привілейована служба, яка перетворює такий ввід безпосередньо на операції з файлами, реєстром, процесами або командним рядком, може стати “збентеженим заступником”: зловмисник надає інструкції, а служба надає привілеї.
Запити повинні використовувати суворе кадрування повідомлень, обмежені розміри, білі списки команд, валідацію схем, нормалізацію шляхів, авторизацію специфічних для операцій і безпечну обробку помилок.
Доступність та віддалене викриття
Безпека іменованих каналів не обмежується лише ескалацією привілеїв та неавторизованими командами.
Зловмисний або несправний процес може неодноразово підключатися, утримувати з’єднання відкритими, надсилати неповні повідомлення або надсилати запити, що споживають надмірні ресурси ЦП, пам’яті або ядра.
Сервер повинен використовувати обмеження з’єднань, тайм-аути, скасування, обмежені розміри повідомлень, контрольовану паралельність та обмеження частоти запитів, де це доречно.
Також небезпечно припускати, що кожен іменований канал доступний лише з локального комп’ютера. Іменовані канали Windows можуть підтримувати віддалений доступ за певних конфігурацій.
Канали, призначені виключно для локальної міжпроцесної взаємодії (IPC), повинні явно блокувати мережеві ідентичності, такі як NT AUTHORITYNETWORK, або використовувати механізм, що гарантує виключно локальну взаємодію.
Правильна модель загроз проста: кожне з’єднання через іменований канал слід розглядати як потенційно вороже, доки не буде перевірено ідентичність клієнта або сервера, дозволи, запитувана операція та вміст повідомлення.
Коли іменований канал стає межею безпеки
Іменований канал стає межею безпеки, коли процеси на його кінцях працюють з різними привілеями або під різними рівнями довіри.
Поширеним прикладом є служба Windows, що працює під обліковим записом LocalSystem, та настільна програма, що працює під обліковим записом стандартного користувача. Служба може мати можливість змінювати захищені файли та ключі реєстру, запускати процеси, змінювати загальносистемні налаштування, отримувати доступ до даних інших користувачів або взаємодіяти з драйвером ядра. Настільна програма зазвичай не може виконувати ці операції безпосередньо.
Коли служба приймає команди через іменований канал, цей канал стає інтерфейсом до цих привілейованих можливостей. Будь-яка слабкість у дозволах каналу, перевірках ідентичності, валідації команд або логіці авторизації може дозволити недовіреному локальному процесу зловживати привілеями служби.
Успішне з’єднання не доводить, що клієнт є очікуваною програмою. Воно лише доводить, що процес, який підключався, мав достатній дозвіл на відкриття каналу. Інший процес, що працює під тим самим обліковим записом користувача, може мати точно такий самий доступ. Тому сервер повинен перевіряти безпекову ідентичність, що стоїть за з’єднанням, а не покладатися на ім’я процесу, шлях до виконуваного файлу або секретність імені каналу.
Сервер також повинен авторизувати кожну операцію окремо. Клієнт, якому дозволено запитувати статус служби, не повинен автоматично отримувати дозвіл на зупинку служби, зміну захищених налаштувань, запуск процесу або запит доступу до довільного файлу.
Ця відмінність є особливо важливою, коли сервер обробляє шляхи, аргументи командного рядка, розташування в реєстрі, імена виконуваних файлів або серіалізовані команди, контрольовані клієнтом. Без суворої валідації служба може стати “збентеженим заступником”: клієнт обирає дію, але привілейована служба її виконує.
Наприклад, на перший погляд нешкідливий запит, як-от:
Читати файл: C:ProgramDataProductstatus.json
може стати небезпечним, якщо клієнт зможе замінити шлях на:
читати файл: C:WindowsSystem32configSAM
Та сама проблема стосується запитів, які запускають процеси, видаляють файли, оновлюють значення реєстру, встановлюють компоненти або взаємодіють з драйвером. Служба повинна не просто перевіряти, чи синтаксично правильна команда. Вона повинна перевірити, чи дозволено підключеному ідентифікатору виконувати цю конкретну операцію над цим конкретним ресурсом.
Таким чином, безпечний сервер іменованих каналів повинен застосовувати кілька перевірок перед виконанням привілейованого запиту:
- перевірити ідентичність клієнта Windows, що підключився;
- обмежити доступ за допомогою явного дескриптора безпеки каналу;
- авторизувати кожну команду незалежно;
- валідувати всі шляхи, аргументи, ідентифікатори та розміри корисного навантаження;
- відхиляти непідтримувані або неоднозначні операції;
- уникати надання доступу до загальнофункціональних привілейованих можливостей.
Останній пункт є критично важливим. Команда, як-от “записати це значення в будь-який ключ реєстру”, створює набагато більшу поверхню атаки, ніж вузько визначена команда, як-от “оновити це конкретне налаштування програми”. Чим загальнішим стає протокол каналу, тим тісніше він нагадує привілейований локальний API — і тим ретельніше його потрібно захищати.
Правильний принцип дизайну простий: сервер каналу ніколи не повинен виконувати операцію лише тому, що її запитав підключений клієнт. Він повинен виконати операцію тільки після підтвердження того, хто її запитував, чи авторизовано цього запитувача, і чи запит залишається в межах вузько визначених меж безпеки.
Контроль доступу та авторизація клієнта
Сервер іменованих каналів повинен вирішувати, хто може підключитися, перш ніж він почне обробляти повідомлення. Це починається з явного дескриптора безпеки, який надає доступ лише необхідним ідентичностям Windows, таким як конкретний SID користувача, обліковий запис служби, група адміністраторів або сеанс входу.
DACL каналу контролює доступ до обох кінців іменованого каналу. Коли клієнт намагається підключитися, Windows порівнює токен доступу клієнта та запитувані права з цим DACL. Покладатися на стандартний дескриптор ризиковано, оскільки його дозволи можуть бути ширшими, ніж потребує програма.
Доступ до каналу не надає автоматично авторизації для кожної доступної команди. Клієнту може бути дозволено отримати інформацію про статус, але заборонено змінювати налаштування, запускати процеси або отримувати доступ до захищених файлів. Тому авторизація повинна виконуватися для кожної чутливої операції, а не лише один раз при встановленні з’єднання.
Для локальної взаємодії між програмами програми також можуть перевіряти процес, пов’язаний з протилежним кінцем каналу:
- сервер може викликати
GetNamedPipeClientProcessId; - клієнт може викликати
GetNamedPipeServerProcessId.
Ці API Windows повертають ідентифікатор процесу, пов’язаний з підключеним клієнтом або сервером. Їх слід викликати лише після встановлення з’єднання каналу.
Наступний допоміжний код на C# отримує PID піра за допомогою нативних API Windows:
[DllImport(“kernel32.dll”, SetLastError = true)][return: MarshalAs(UnmanagedType.Bool)]private static extern bool GetNamedPipeClientProcessId(SafePipeHandle pipe, out uint clientProcessId);[DllImport(“kernel32.dll”, SetLastError = true)][return: MarshalAs(UnmanagedType.Bool)]private static extern bool GetNamedPipeServerProcessId(SafePipeHandle pipe, out uint serverProcessId);
Ми також можемо викликати іншу функцію з kernel32.dll, QueryFullProcessImageName, щоб отримати шлях до виконуваного файлу з дескриптора процесу, відкритого з PROCESS_QUERY_INFORMATION або PROCESS_QUERY_LIMITED_INFORMATION. Повернутий шлях можна порівняти з очікуваним розташуванням виконуваного файлу як додатковий крок перевірки.
На стороні сервера перевірка повинна відбуватися безпосередньо після прийняття з’єднання та перед читанням або виконанням команд:
Очікуваний виконуваний файл повинен розташовуватися в каталозі, який стандартні користувачі не можуть змінити. В іншому випадку зловмисник може замінити файл, зберігаючи при цьому очікуваний шлях.
Для більш надійної перевірки програма може додатково перевірити автентифікаційний підпис (Authenticode) виконуваного файлу або порівняти його з дозволеним криптографічним хешем. Windows надає WinVerifyTrust для перевірки підписаних виконуваних файлів.
Однак перевірка PID та шляху до виконуваного файлу повинна залишатися вторинним контролем, а не основним механізмом авторизації. Дослідження безпеки продемонстрували способи підробки PID, що повідомляється для клієнта іменованого каналу, та способи передачі підключеного дескриптора каналу іншому процесу. Повернений PID може ідентифікувати процес, який відкрив з’єднання, але не доводить, який процес зараз надсилає кожне повідомлення.
Таким чином, безпечна реалізація повинна поєднувати кілька механізмів контролю:
- явний і обмежувальний DACL каналу;
- перевірка ідентичності або SID клієнта Windows;
- авторизація кожної привілейованої команди;
- сувора валідація вмісту повідомлень;
- опціональна перевірка PID, шляху до виконуваного файлу, підпису або хешу як додатковий рівень захисту (defense in depth).
З’єднання слід відхиляти, якщо перевірка ідентичності не вдається або не може бути завершена. Привілейована служба ніколи не повинна повертатися до прийняття запиту лише тому, що з’єднання з каналом відбулося успішно.
Імітація та привілейовані операції
Сервер іменованих каналів часто працює з більшими привілеями, ніж підключений до нього клієнт. Наприклад, служба Windows може працювати як LocalSystem, тоді як клієнтська програма працює під обліковим записом стандартного користувача. Якщо служба виконує кожну запитувану операцію під власною ідентичністю, клієнт може опосередковано отримати доступ до файлів, ключів реєстру, процесів та системних ресурсів, до яких він не міг отримати доступ безпосередньо.
Імітація іменованих каналів дозволяє серверу тимчасово виконувати код у безпековому контексті підключеного клієнта. Windows оцінює доступ до ресурсів, використовуючи токен клієнта, а не токен облікового запису служби.
У .NET, NamedPipeServerStream.RunAsClient надає контрольований спосіб імітації підключеного клієнта:
server.WaitForConnection();server.RunAsClient(() =>{ string path = @”C:ProgramDataMyApplicationsettings.json”; // Доступ перевіряється за допомогою ідентичності підключеного клієнта. string content = File.ReadAllText(path); ProcessClientData(content);});
Цей підхід корисний, коли клієнт повинен мати можливість виконати операцію лише за умови, що його власний обліковий запис Windows вже має дозвіл. Наприклад, імітація може використовуватися при читанні файлу, що належить користувачеві, доступі до ключа реєстру, специфічного для користувача, або перевірці, чи має клієнт доступ до захищеного ресурсу.
Однак імітація не є заміною авторизації. Сервер все одно повинен перевірити, чи дозволено клієнту запитувати операцію. Імітація лише змінює безпековий контекст, у якому Windows виконує перевірки доступу; вона не визначає, чи є команда доречною.
Привілейована служба також повинна уникати непотрібних перемикань між ідентичністю клієнта та ідентичністю служби. Розглянемо запит, який просить службу прочитати файл, а потім встановити його вміст як конфігурацію.
Файл може бути прочитаний під час імітації клієнта, але встановлення може відбутися пізніше під обліковим записом LocalSystem. У цьому випадку клієнт все ще може вплинути на привілейовану операцію, навіть якщо частина запиту була оброблена під час імітації.
Більш безпечний дизайн полягає у розділенні операції на чітко визначені етапи:
- Автентифікація та авторизація клієнта.
- Валідація всіх шляхів, аргументів та даних, контрольованих клієнтом.
- Імітація лише для операцій, які повинні використовувати дозволи клієнта.
- Повернення до ідентичності служби перед виконанням вузько визначених привілейованих завдань.
- Перевалідація будь-яких даних, що переходять з етапу імітації до етапу привілеїв.
Область дії імітації повинна бути якомога меншою. Тривала робота, зворотні виклики, асинхронні операції та непов’язана логіка служби не повинні виконуватися під ідентичністю клієнта.
При використанні нативних API Windows застосовується той самий шаблон:
[DllImport(“advapi32.dll”, SetLastError = true)][return: MarshalAs(UnmanagedType.Bool)]private static extern bool ImpersonateNamedPipeClient(SafePipeHandle pipe);[DllImport(“advapi32.dll”, SetLastError = true)][return: MarshalAs(UnmanagedType.Bool)]private static extern bool RevertToSelf();
Сервер повинен перевірити, чи ImpersonateNamedPipeClient пройшла успішно, і завжди повинен викликати RevertToSelf у блоці finally:
if (!ImpersonateNamedPipeClient(server.SafePipeHandle)){ throw new Win32Exception(Marshal.GetLastWin32Error());}try{ // Виконується під безпековим контекстом підключеного клієнта. PerformClientScopedOperation();}finally{ if (!RevertToSelf()) { throw new Win32Exception(Marshal.GetLastWin32Error()); }}
Обробка помилок є критично важливою. Якщо імітація не вдалася, а служба продовжує обробку, операція може виконатися під оригінальною привілейованою ідентичністю служби. Тому невдала спроба імітації повинна призвести до відхилення запиту, а не до тихого повернення до облікового запису служби.
Той самий принцип застосовується і після імітації. Програма повинна надійно відновити свою оригінальну ідентичність перед обробкою іншого клієнта або виконанням непов’язаної роботи. В іншому випадку пізніші операції можуть випадково виконатися під контекстом попереднього клієнта.
Привілейовані команди каналів також повинні бути вузькими та специфічними. Команда, як-от:
записати будь-яке значення в будь-який ключ реєстру
створює набагато більшу поверхню атаки, ніж:
оновити затверджене налаштування політики програми
Служба не повинна надавати загальний доступ до файлів, модифікацію реєстру, створення процесів або виконання команд лише тому, що вона може виконувати ці операції. Кожна привілейована команда повинна точно визначати, до яких ресурсів можна отримати доступ, які значення приймаються, і які ідентичності клієнтів можуть її викликати.
Імітація найефективніша, коли використовується як один рівень у ширшій системі безпеки. Сервер повинен все ще застосовувати обмежувальні дозволи на канал, перевіряти підключеного клієнта, авторизувати кожну команду, валідувати кожен запит і тримати привілейовані операції вузько визначеними.
Розгляд повідомлень каналу як неперевіреного вводу
Перевірка процесу, підключеного до іменованого каналу, не робить його повідомлення безпечними. Легітимна програма може бути скомпрометована, містити вразливість або передавати дані, контрольовані користувачем, до каналу. Зловмисний процес також може отримати або успадкувати дійсний дескриптор каналу.
З цієї причини кожне повідомлення, отримане через іменований канал, слід розглядати як неперевірений ввід. Сервер повинен перевіряти як структуру повідомлення, так і запитувану ним операцію перед виконанням будь-яких привілейованих дій.
Небезпечна реалізація може десеріалізувати запит і виконати його безпосередньо:
PipeRequest request = Deserialize(data);File.WriteAllText(request.Path, request.Content);
Навіть коли request має очікувану структуру, значення, такі як Path і Content, залишаються контрольованими клієнтом. Тому привілейовану службу можна інструктувати перезаписати файли поза каталогом програми, змінити захищені налаштування або спожити надмірний дисковий простір.
Безпечніший підхід полягає у наданні вузько визначених команд та перевірці кожного поля:
private static void ProcessRequest(PipeRequest request){ if (request == null) throw new InvalidDataException(“The request is missing.”); switch (request.Command) { case PipeCommand.UpdateConfiguration: ValidateConfiguration(request.Configuration); UpdateApprovedConfiguration(request.Configuration); break; case PipeCommand.GetStatus: ReturnApplicationStatus(); break; default: throw new InvalidDataException(“Unsupported command.”); }}
Протокол повинен уникати загальних операцій, таких як:
Потік Файл(шлях, вміст) ЗапуститиПроцес(шлях, аргументи) ВстановитиЗначенняРеєстру(ключ, ім’я, значення) ВиконатиКоманду(команда)
Ці команди дозволяють клієнту вибирати як привілейовану операцію, так і її ціль. Перевагу слід надавати специфічним для програми запитам, дозволена поведінка яких контролюється сервером:
ОновитиКонфігураціюПрограми(конфігурація) ЗапитатиВідновленняПрограми() ВстановитиСхваленеОновлення(ідентифікатор_оновлення) ОтриматиСтатусСлужби()
Перевірка структури та розміру повідомлення
З’єднання іменованого каналу є потоком байтів, якщо програма явно не використовує режим передачі повідомлень. Один виклик Read не гарантує повернення повного повідомлення програми, і сервер не повинен припускати, що межі читання відповідають межам запитів.
Протокол повинен визначати явне кадрування повідомлень, наприклад, заголовок фіксованого розміру, за яким слідує корисне навантаження з довжиною, що передує:
[Version][Command][Payload Length]
Оголошену довжину слід перевірити перед виділенням пам’яті або читанням корисного навантаження:
private const int MaxMessageSize = 1024
• 1024;private static async Task<byte[]> ReadPayloadAsync( Stream pipe, int payloadLength, CancellationToken cancellationToken){ if (payloadLength < 0 || payloadLength > MaxMessageSize) throw new InvalidDataException(“Invalid payload length.”); byte[] payload = new byte
; int offset = 0; while (offset < payload.Length) { int read = await pipe.ReadAsync( payload, offset, payload.Length – offset, cancellationToken); if (read == 0) throw new EndOfStreamException( “The pipe was closed before the message was complete.”); offset += read; } return payload;}
Без максимального розміру зловмисник може оголосити дуже велике корисне навантаження і змусити службу виділити надмірну пам’ять. Додаток також повинен обмежувати розміри колекцій, довжину рядків, глибину вкладеності та кількість об’єктів, прийнятих десеріалізатором.
Перевірка значень, а не лише типів
Успішна десеріалізація доводить лише те, що корисне навантаження можна було перетворити на очікуваний тип об’єкта. Це не доводить, що значення прийнятні.
Наприклад, шлях до файлу слід нормалізувати та перевірити щодо дозволеного каталогу:
private static string ValidatePath( string suppliedPath, string allowedDirectory){ string fullPath = Path.GetFullPath(suppliedPath); string fullDirectory = Path.GetFullPath(allowedDirectory) .TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar; if (!fullPath.StartsWith( fullDirectory, StringComparison.OrdinalIgnoreCase)) { throw new UnauthorizedAccessException( “The requested path is outside the allowed directory.”); } return fullPath;}
Той самий принцип застосовується до шляхів реєстру, аргументів процесів, URL-адрес, ідентифікаторів, пакетів оновлень та значень конфігурації. Сервер повинен перевіряти кожне значення за білим списком або вузько визначеним діапазоном, а не намагатися блокувати відомі небезпечні значення.
Перевірки шляхів також потребують обережності навколо символічних посилань, точок з’єднання, точок повторного аналізу та перегонів “час перевірки/час використання”. Для чутливих файлових операцій перевірки рядкового шляху може бути недостатньо.
Безпечне відхилення недійсних запитів
Неправильно сформовані або неавторизовані повідомлення слід відхиляти без продовження часткової обробки. Сервер повинен уникати повернення стек-трейсів, внутрішніх шляхів, токенів безпеки або детальної інформації про винятки клієнту.
Помилки, що надсилаються через канал, повинні використовувати невеликий, контрольований набір кодів відповідей:
public enum PipeResult{ Success, InvalidRequest, Unauthorized, UnsupportedCommand, InternalError}
Детальна діагностична інформація може бути записана до захищених журналів служби, тоді як клієнт отримує лише інформацію, необхідну для обробки збою.
Кожен запит повинен проходити передбачувану послідовність:
- Прочитати обмежене повідомлення.
- Перевірити версію протоколу та структуру повідомлення.
- Автентифікувати та авторизувати підключеного клієнта.
- Перевірити кожне значення, контрольоване клієнтом.
- Виконати лише вузько визначену операцію.
- Повернути контрольовану відповідь.
Іменований канал є лише транспортним механізмом. Він не робить дані надійними, не гарантує правильного кадрування повідомлень і не запобігає надсиланню зловмисних запитів підключеним процесом. Програма, що приймає, залишається відповідальною за застосування протоколу та захист кожної операції, що надається через нього.
Ризики відмови в обслуговуванні та віддаленого доступу
Кінець іменованого каналу може бути захищений від неавторизованих команд, але все ще залишатися вразливим до атак відмови в обслуговуванні. Зловмиснику не завжди потрібен дозвіл на виконання привілейованої операції; запобігання спілкуванню легітимних програм зі службою може бути достатнім для порушення роботи продукту.
Зловмисний або несправний процес може багаторазово підключатися до каналу, займати всі доступні екземпляри, утримувати з’єднання відкритими без надсилання повних повідомлень або безперервно перепідключатися після роз’єднання. Як тільки всі екземпляри сервера зайняті, легітимні клієнти можуть не мати можливості встановити з’єднання.
Той самий ризик існує і після прийняття з’єднання. Клієнт може надсилати дані надзвичайно повільно, оголосити занадто велике корисне навантаження, зупинитися на півдорозі повідомлення або затопити сервер валідними, але дорогими запитами. Без обмежень така поведінка може споживати потоки, завдання, пам’ять, процесорний час, дескриптори та внутрішні черги запитів.
Буфери іменованих каналів також споживають несторінкований пул ядра. Тому кількість екземплярів каналу та обсяг буферизованих даних обмежені системними ресурсами. Створення необмеженої кількості екземплярів або вибір непотрібно великих буферів може сприяти вичерпанню ресурсів.
Захисний сервер повинен встановлювати чіткі обмеження для:
- одночасних з’єднань та екземплярів каналу;
- розмірів повідомлень та полів;
- часу, відведеного на встановлення та завершення запиту;
- очікуючих запитів на клієнта;
- паралельних дорогих операцій;
- частоти запитів;
- ємності внутрішньої черги.
Блокуючі операції повинні підтримувати скасування і не повинні чекати нескінченно, доки клієнт надішле більше даних. Коли клієнт перевищує ліміт часу, розміру або запитів, сервер повинен розірвати це з’єднання та швидко звільнити його ресурси.
Обмеження слід застосовувати до початку дорогої роботи. Наприклад, сервер повинен відхиляти надмірний заявлений розмір корисного навантаження перед виділенням відповідного буфера. Аналогічно, авторизація та базова перевірка запитів повинні відбуватися до доступу до диска, створення процесів, криптографічної роботи, запитів до бази даних або взаємодії з драйвером ядра.
Програма також повинна уникати створення одного необмеженого робочого потоку для кожного з’єднання. Модель обмеженої паралельності запобігає вичерпанню пулу потоків процесу або створенню неконтрольованого бек-логу великою кількістю підключених клієнтів. Обмеження швидкості можуть застосовуватися на з’єднання, процес, ідентифікатор користувача або сеанс входу, залежно від архітектури програми.
Однак заходи контролю доступності не повинні покладатися лише на PID клієнта. Процес може багаторазово перезапускатися, використовувати кілька процесів або встановлювати з’єднання під тим самим обліковим записом користувача. Слід розглядати кілька сигналів разом, і сервер повинен зберігати глобальне обмеження, навіть коли присутні індивідуальні контролі.
Іншим часто неврахованим ризиком є віддалена доступність. Іменовані канали Windows не обов’язково обмежуються взаємодією в межах локального комп’ютера. Вони також можуть підтримувати взаємодію між комп’ютерами через мережу, і Microsoft стверджує, що іменовані канали можуть бути віддалено доступні, коли запущена служба Windows Server.
Це означає, що використання локального імені каналу саме по собі не гарантує виключно локальної взаємодії. Канал, призначений для взаємодії між локальною службою та локальною настільною програмою, повинен явно забезпечувати це вимога.
Нативні сервери каналів можуть вказувати PIPE_REJECT_REMOTE_CLIENTS, що призводить до автоматичного відхилення віддалених з’єднань Windows. Без цієї опції віддалені клієнти можуть бути прийняті та оцінені відповідно до дескриптора безпеки каналу.
Список контролю доступу каналу також може заборонити доступ ідентичності NT AUTHORITYNETWORK. Там, де доступ повинен бути обмежений однією інтерактивною сесією, сервер може надати доступ до відповідного SID входу, а не до широких груп, спільних для локальних та віддалених користувачів.
Ці захисти слід поєднувати, а не розглядати як альтернативи:
- відхиляти віддалених клієнтів при створенні каналу, якщо API це підтримує;
- забороняти мережеві ідентичності в дескрипторі безпеки каналу;
- надавати доступ лише необхідним користувачам або сеансам входу;
- перевіряти ідентичність підключеного процесу;
- застосовувати обмеження на з’єднання, тайм-аути, розміри та паралельність.
Захист від відмови в обслуговуванні та обмеження віддаленого доступу є частиною моделі безпеки каналу. Іменований канал не є безпечним лише тому, що відхиляються неавторизовані команди. Він також повинен залишатися доступним для легітимних клієнтів і забезпечувати, чи дозволено з’єднанням надходити з-поза меж локального комп’ютера.
Розробка безпечної архітектури іменованих каналів
Безпечний дизайн іменованих каналів повинен мінімізувати як кількість відкритих операцій, так і обсяг привілейованого коду, який безпосередньо обробляє дані, контрольовані клієнтом. Канал повинен діяти як вузька межа зв’язку, а не як загальний інтерфейс до операційної системи.
Практична архітектура розділяє обробку з’єднань, валідацію, авторизацію та виконання привілеїв:

Клієнт ніколи не повинен взаємодіяти безпосередньо з загальними привілейованими функціями. Натомість він повинен надсилати вузько визначений запит до шлюзу каналу. Шлюз перевіряє формат повідомлення та передає структурований запит шару авторизації. Привілейована робота починається лише після успішного завершення всіх перевірок безпеки.
Зберігайте протокол каналу вузьким
Протокол каналу повинен надавати доступ до бізнес-операцій, а не до примітивів операційної системи.
Наприклад, програма може законно потребувати запиту на оновлення політики, встановлення схваленого оновлення, отримання статусу служби або оновлення конкретного значення конфігурації. Зазвичай їй не потрібні необмежені команди для запису довільних файлів, зміни довільних ключів реєстру, запуску довільних виконуваних файлів або виконання інструкцій командного рядка.
Вузькі операції роблять авторизацію та валідацію практичними. Сервер знає, до яких ресурсів кожна команда може отримати доступ, які поля очікуються, і які ідентичності клієнтів можуть її викликати.
Хороший протокол повинен включати:
- явну версію протоколу;
- фіксований набір типів запитів;
- унікальні ідентифікатори запитів;
- обмежені розміри корисного навантаження;
- передбачувані формати відповідей та помилок;
- чіткі правила для непідтримуваних або неправильно сформованих повідомлень.
Сервер повинен відхиляти невідомі версії, команди, поля та стани, а не намагатися їх м’яко інтерпретувати.
Розділіть доступ до з’єднання від дозволу на команду
Дозвіл на підключення до каналу не повинен означати дозвіл на використання кожної функції, доступної через нього.
Дескриптор безпеки каналу повинен обмежувати, які ідентичності Windows можуть встановлювати з’єднання. Після встановлення з’єднання сервер повинен ідентифікувати клієнта та авторизувати кожну команду незалежно.
Це дозволяє підтримувати різні рівні довіри через одну службу. Наприклад, звичайним користувачам може бути дозволено запитувати статус, тоді як лише адміністратори або довірений процес керування можуть змінювати захищені налаштування.
Для особливо чутливих операцій може бути краще використовувати окремі іменовані канали:
Product.Status Читання лише інформаціїProduct.UserActions Обмежені дії користувачаProduct.Admin Адміністративні операціїProduct.Internal Комунікація довірених компонентів
Кожен канал може мати власні правила контролю доступу, обмеження повідомлень та набір підтримуваних команд. Це зазвичай безпечніше, ніж розміщувати кожну операцію за одним великим протоколом і покладатися виключно на внутрішні перевірки команд.
Однак створення додаткових каналів не покращує безпеку автоматично. Кожен новий кінцевий пункт збільшує поверхню атаки і повинен бути незалежно захищений. Канали слід розділяти лише тоді, коли вони представляють справді різні межі довіри.
Використовуйте багаторівневу перевірку ідентичності
Жодна окрема перевірка ідентичності не повинна вважатися остаточною.
Архітектура може поєднувати:
- обмежувальний DACL каналу;
- SID підключеного користувача;
- сеанс входу клієнта;
- PID піра;
- шлях до виконуваного файлу;
- цифровий підпис виконуваного файлу;
- виклики та відповіді на рівні програми;
- авторизація для конкретних операцій.
Перевірки PID та шляху до виконуваного файлу можуть допомогти виявити несподівані програми, але вони повинні залишатися контролем захисту в глибині (defense-in-depth). Процеси можуть змінюватися, дескриптори можуть успадковуватися або передаватися, а довірений процес сам може бути скомпрометований.
Найсильніші рішення повинні базуватися на ідентичностях безпеки Windows та вузько визначених дозволах, а не лише на видимому імені виконуваного файлу.
Ізолюйте привілейоване виконання
Компонент, відповідальний за читання повідомлень каналу, повинен виконувати якомога менше привілейованої роботи.
Обробка з’єднань, десеріалізація, кадрування та базова валідація піддаються вводу, контрольованому зловмисником. Відокремлення цієї логіки від привілейованих операцій зменшує вплив вразливості парсера або протоколу.
Шар привілейованих операцій повинен отримувати лише валідовані, строго типізовані інструкції. Він не повинен отримувати сирі буфери повідомлень, довільні шляхи, командні рядки або серіалізовані об’єкти безпосередньо від клієнта.
Для високочутливих програм дизайн може піти далі, розділивши шлюз каналу та робочий процес привілеїв на різні процеси. Шлюз може працювати зі зменшеними привілеями, перевіряти вхідні запити та пересилати лише схвалені операції меншому привілейованому компоненту через другий обмежений канал.
Цей додатковий межовий процес збільшує складність, але може значно зменшити обсяг коду, спрямованого на атаку, що працює як LocalSystem або інший потужний обліковий запис.
Контролюйте життєвий цикл кожного з’єднання
Кожне прийняте з’єднання повинно мати чіткий і обмежений життєвий цикл:
- Прийняти з’єднання.
- Ідентифікувати та перевірити піра.
- Застосувати обмеження на рівні з’єднання.
- Прочитати обмежений запит.
- Авторизувати та перевірити запитувану операцію.
- Виконати схвалену дію.
- Повернути контрольовану відповідь.
- Відключитися або чекати наступного обмеженого запиту.
Сервер не повинен дозволяти неавтентифікованим клієнтам утримувати з’єднання невизначено довго. Тайм-аути бездіяльності, дедлайни запитів, обмеження з’єднань, скасування та обмежені черги повинні бути частиною архітектури з самого початку.
Тривалі операції не повинні без потреби блокувати читач каналу. Служба може прийняти запит, призначити ідентифікатор операції та дозволити клієнту перевіряти прогрес через окремий запит статусу. Це запобігає монополізації серверних ресурсів одним з’єднанням.
Зробіть сервер авторитетним
Клієнт повинен запитувати результат, а сервер повинен визначати, як цей результат буде досягнутий.
Наприклад, клієнт може запитати встановлення схваленого оновлення за ідентифікатором. Сервер повинен визначити розташування пакету, перевірити його підпис, визначити команду встановлення та забезпечити дозволене місце призначення. Клієнт не повинен надавати шлях до виконуваного файлу, URL-адресу для завантаження, аргументи командного рядка та цільовий каталог.
Це зберігає рішення, пов’язані з безпекою, всередині довіреного компонента та зменшує кількість значень, контрольованих клієнтом, що перетинають межу привілеїв.
Сервер також повинен уникати довіри до рішень безпеки, які раніше приймав клієнт. Твердження, як-от “користувач є адміністратором”, “цей файл підписаний” або “цей шлях безпечний”, повинні бути незалежно перевірені сервером.
Аудит дій, пов’язаних з безпекою
Безпечна архітектура повинна записувати достатньо інформації для розслідування підозрілої поведінки без розкриття конфіденційних даних.
Корисні події аудиту включають:
- відхилені з’єднання;
- невдалі перевірки ідентичності;
- неавторизовані команди;
- неправильно сформовані або занадто великі повідомлення;
- повторні тайм-аути;
- несподівані ідентичності процесів;
- привілейовані операції та їхні результати;
- аномальні швидкості з’єднань або запитів.
Журнали повинні ідентифікувати користувача Windows, сеанс, PID піра, тип команди та результат, де це доречно. Сирі секрети, токени автентифікації та повні конфіденційні корисні навантаження не повинні записуватися до журналів.
Повторні збої можуть вказувати на атаку, але вони також можуть виявити дефектну версію клієнта або проблему розгортання. Тому дані аудиту повинні підтримувати як розслідування безпеки, так і усунення операційних несправностей.
Рекомендована архітектура
Для більшості сценаріїв привілейованих служб Windows захищена конструкція складається з:
- іменований канал, що працює лише локально, з явним дескриптором безпеки;
- окремі кінцеві точки для суттєво різних рівнів довіри;
- перевірка як ідентичності Windows, так і пір-процесу;
- версіонований, обмежений довжиною, специфічний для програми протокол;
- авторизація для кожної команди;
- сувора валідація кожного значення, контрольованого клієнтом;
- короткі та ретельно контрольовані області дії імітації;
- невеликий шар виконання привілеїв;
- обмежені з’єднання, черги та час виконання;
- аудит безпеки, орієнтований на безпеку.
Основний принцип полягає в тому, що іменований канал повинен надавати найменш можливий інтерфейс між рівнями довіри. Безпечна архітектура не намагається зробити довільні привілейовані операції безпечними. Вона уникає надавати доступ до довільних привілейованих операцій взагалі.
Практичний контрольний список безпеки іменованих каналів
Перш ніж надавати функціональність програми через іменований канал, переконайтеся, що дизайн охоплює кожну з наступних областей:
- Визначте межу довіри. Розглядайте канал як відкритий локальний інтерфейс, особливо коли одна сторона працює з підвищеними привілеями.
- Явно обмежте доступ до каналу. Використовуйте вузький дескриптор безпеки замість того, щоб покладатися на стандартні дозволи або широкі групи, такі як Everyone.
- Відхиляйте віддалених клієнтів. Налаштуйте канал для виключно локальної взаємодії та забороняйте мережеві ідентичності, коли віддалений доступ не потрібен.
- Перевіряйте обидва кінцеві пункти. Перевірте підключену ідентичність Windows і, де це доречно, підтвердіть PID піра, шлях до виконуваного файлу та цифровий підпис.
- Не довіряйте імені каналу. Передбачуване ім’я ідентифікує кінцеву точку, але не автентифікує процес, який її створив.
- Авторизуйте кожну команду. Дозвіл на підключення не повинен надавати доступ до всіх операцій, наданих сервером.
- Зберігайте протокол вузьким. Надавайте специфічні для програми дії, а не довільні можливості для роботи з файлами, реєстром, процесами або виконання команд.
- Розглядайте всі повідомлення як неперевірені. Перевіряйте кадрування, версію протоколу, тип команди, розмір корисного навантаження, значення полів, шляхи та кількість об’єктів.
- Застосовуйте обмеження завчасно. Відхиляйте недійсні розміри та непідтримувані запити перед виділенням пам’яті або початком дорогої роботи.
- Використовуйте імітацію обережно. Імітуйте лише тоді, коли операція повинна використовувати дозволи клієнта, зберігайте область дії невеликою та відмовляйтеся при збої імітації.
- Ізолюйте привілейоване виконання. Відокремте парсинг і валідацію від коду, який виконує привілейовані операції.
- Контролюйте використання ресурсів. Обмежте одночасні з’єднання, очікуючі запити, час бездіяльності, час виконання, глибину черги та частоту запитів.
- Повертайте контрольовані помилки. Уникайте розкриття стек-трейсів, внутрішніх шляхів, токенів або інших конфіденційних деталей реалізації.
- Аудит подій, пов’язаних з безпекою. Записуйте відхилені з’єднання, невдалі перевірки ідентичності, неправильно сформовані запити, неавторизовані команди та привілейовані операції.
- Відмова із закриттям (Fail closed). Якщо перевірку ідентичності, авторизацію, валідацію або імітацію неможливо надійно завершити, відхиліть запит.
Безпечна реалізація іменованих каналів не повинна залежати від одного захисту. Найсильніший дизайн поєднує обмежувальний контроль доступу, перевірку кінцевих точок, авторизацію на рівні операцій, сувору валідацію вводу, обмежене використання ресурсів та вузько визначену привілейовану функціональність.
Біографія автора:
Фарід Мустафаєв – розробник програмного забезпечення в ThreatLocker, який спеціалізується на розробці служб Microsoft Windows та кібербезпеці. Маючи понад 15 років досвіду роботи в галузі, він глибоко знає технології .NET, включаючи ASP.NET WebAPI, Windows Services, Windows Forms, WPF, RESTful API та низькорівневі внутрішні механізми Windows. Він керував розробкою та зміцненням служб Windows, призначених для захисту систем від шкідливих програм та програм-вимагачів, включаючи роботу з інтеграціями на рівні ядра та вдосконаленнями кастомних драйверів.
Раніше Мустафаєв працював технічним керівником, керуючи архітектурними рішеннями, навчаючи розробників та створюючи масштабовані, підтримувані системи. Його досвід також включає архітектури на основі мікросервісів та хмарні рішення на AWS, з акцентом на доступність, продуктивність та безпеку в розподілених середовищах.
Спонсорований і написаний ThreatLocker.
- Cybersecurity
- Interprocess Communication
- Named Pipes
- ThreatLocker
- Windows
- Попередня стаття
- Наступна стаття
Коментарі до цієї статті вимкнено. Популярні статті
-
Microsoft випустила патчі для усунення критичних вразливостей виконання коду та ескалації привілеїв
-
Citrix закликає адміністраторів якомога швидше застосувати патчі для нових вразливостей NetScaler
-
Зловмисники отруїли Rust-крейт arrayref, щоб поширювати шкідливе ПЗ для крадіжки інформації
Спонсорські публікації
-
Захистіть себе від брокерів даних, шахраїв та наступного витоку даних за допомогою цифрових ідентичностей.
-
Дізнайтеся, як ШІ змінює електронні атаки. Завантажте звіт Kaseya Email Security Report 2026.
-
CVE Certighost новий. Привілеї, що стоять за ним, ні. Дізнайтеся, де ховається ваш.
-
Дізнайтеся, як мінімальні привілеї зберігають ваші інструменти ШІ потужними, контрольованими та безпечними.
-
Будьте на крок попереду нових загроз у новому році. Приєднуйтесь до Huntress на щомісячному Tradecraft Tuesday.
-
Превентивні заходи на основі сигнатур знизилися до 50%. Дізнайтеся, що все ще зупиняють ваші засоби контролю.
Слідкуйте за нами:
Основні розділи
- Новини
- Вебінари
- Посібники для покупців VPN
- Посібники з програмного забезпечення для системних адміністраторів
- Завантаження
- Посібники з видалення вірусів
- Посібники
- База даних стартапів
- База даних видалення
- Глосарій
Спільнота
- Форуми
- Правила форуму
- Чат
Корисні ресурси
- Посібник для новачків
- Карта сайту
Компанія
- Про BleepingComputer
- Зв’язатися з нами
- Надіслати нам пораду!
- Пишіть для BleepingComputer
- Соціальні мережі та стрічки
- Журнал змін
Умови використання – Політика конфіденційності – Заява про етику – Розкриття інформації про афілійованість
Copyright @ 2003 – 2026 Bleeping Computer® LLC – Всі права захищені
Вхід
Інформація підготовлена на основі матеріалів: www.bleepingcomputer.com
