Печать редко приходит на ум, когда речь заходит о безопасности Windows, и именно в этом кроется часть проблемы. Служба диспетчера печати, известная как spoolsv.exe, тридцать лет живёт по правилам, продиктованным эпохой офисных сетей девяностых годов, когда доверие к серверу печати внутри периметра считалось само собой разумеющимся. При этом работает она под SYSTEM, загружает сторонний код в привилегированном контексте и слушает сеть через RPC. Такое сочетание сделало её одной из самых богатых мишеней во всей системе: от уязвимости, задействованной Stuxnet в 2010 году, до серии инцидентов вокруг PrintNightmare летом 2021 года, когда исследователи и злоумышленники месяцами находили всё новые обходы исправлений. Эта статья разбирает, почему печать устроена именно так, где прячутся её слабые места, как выглядит файловая механика очереди и что администраторам стоит делать сегодня.

Архитектура службы spoolsv.exe под SYSTEM

Диспетчер печати построен как небольшой конвейер. Приложение вызывает графический интерфейс GDI, формирует задание, и служба spoolsv.exe принимает его как спул, то есть промежуточный файл, который можно передать принтеру независимо от того, свободен ли тот в данный момент. Спулинг позволяет документу уходить в очередь мгновенно, а приложению - не ждать медленное железо. Идея старше самой Windows, но реализация осталась консервативной: служба должна уметь общаться с портами, загружать драйверы, управлять заданиями любых пользователей и принимать удалённые вызовы по именованным каналам и RPC. Всё это требует самых широких прав, поэтому spoolsv.exe традиционно работает под учётной записью SYSTEM - фактически наивысшим уровнем привилегий на локальной машине.

Проблема не в самой привилегии, а в том, какой код попадает в этот контекст. Драйвер принтера в мире Windows - не абстрактное описание устройства, а набор библиотек и файлов конфигурации, которые служба загружает при установке принтера. Исторически предполагалось, что такие драйверы пишет производитель оборудования, подписывает и распространяет осознанно. На практике же механизм сетевой установки позволял машине брать драйвер с удалённого сервера печати и загружать его в процесс, работающий под SYSTEM. Любая логическая ошибка на этом пути - небрежная проверка прав, слабый контроль целостности пакета, доверие к удалённому источнику - превращалась в выполнение кода с максимальными правами. Именно это рутинно эксплуатировали исследователи: поверхность атаки здесь огромна, ведь spooler общается с клиентами, серверами, драйверами, мониторами портов и печатающими приложениями одновременно.

Наследие девяностых от ядерных драйверов до Point and Print

Чтобы понять, откуда растут корни уязвимостей, нужно вернуться к эпохе Windows NT 4.0. Драйверы принтеров версии 3, так называемые v3, изначально выполнялись в режиме ядра. Логика была прагматичной: быстро, близко к графической подсистеме, проще для производителей. Платили за это стабильностью - плохо написанный драйвер уронивал всю систему в синий экран. В Windows 2000 модель вытеснили в пользовательский режим: драйверы v3 перестали работать в ядре, и авария в драйвере стала аварией процесса, а не системы. Это было улучшение надёжности, но не безопасности в современном смысле: пользовательский режим для spoolsv.exe всё равно означает SYSTEM.

Второй исторический пласт - механизм Point and Print. Его придумали для офиса, где сотни рабочих станций должны подключаться к общему принтеру без ручной установки драйверов каждым пользователем. Схема элегантная: клиент подключается к очереди на сервере печати, сервер отдаёт драйвер, клиент устанавливает его автоматически, и пользователь сразу печатает. В девяностых это считалось образцом удобного администрирования. С позиции безопасности же здесь смешано всё самое опасное: удалённый сервер передаёт исполняемый код, клиент загружает его в привилегированный процесс, а решение о доверии исторически принималось по слабым критериям. Если злоумышленник контролирует такой сервер или может выдать себя за него, он получает дорогу к SYSTEM на каждой машине, которая к нему подключилась. Многочисленные ограничения, которые Microsoft накладывала позже, - попытки подтянуть модель девяностых к реальности сетей, где доверия по умолчанию больше не существует.

Уязвимости от Stuxnet до череды PrintNightmare

Печать привлекала исследователей задолго до того, как тема стала массовой. В 2010 году червь Stuxnet использовал уязвимость в службе диспетчера печати для распространения между машинами: дефект позволял через специально сформированный файл в очереди печати записать код в системную область, и заражение расползалось по сети почти бесшумно. Инцидент показал главное - spooler не просто удобная служба, а работающий сетевой шлюз к привилегиям, который почти никто не рассматривает всерьёз.

По-настоящему громкой тема стала летом 2021 года. Исследователи опубликовали детали уязвимости, получившей имя PrintNightmare: сочетание дефектов в интерфейсе удалённого управления драйверами позволяло любому аутентифицированному пользователю домена установить драйвер и тем самым выполнить код под SYSTEM, включая контроллеры домена, где служба нередко была запущена. Реакция индустрии превратилась в длительный сериал: выпускались исправления, почти сразу появлялись варианты обхода, находились смежные уязвимости в той же подсистеме - локальное повышение прав, удалённое выполнение, ошибки в обработчиках портов. Полный каталог подобных дефектов занял бы страницу. Важнее вывод: проблема не была одиночной ошибкой в одной функции. Это системная слабость архитектуры, и плотность находок объясняется тем, что исследователи впервые всерьёз взялись за код, написанный в другую эпоху.

Почему злоумышленники так любят spooler, видно из его свойств как мишени. Служба включена на серверах печати по определению, а по невнимательности - и на массе машин, где печати вообще нет. Привилегии максимальные. Поверхность RPC богатая и исторически почти не аудированная. Легитимный трафик печати выглядит обыденно, и вредоносная активность легко теряется в нём. Наконец, ошибки здесь часто переиспользуемы: найдя слабое место в обработке драйверов, можно годами придумывать новые вариации.

Файловая механика очереди и восстановление зависшей печати

Печать в Windows - это ещё и конкретные файлы на диске, и понимание механики помогает и администратору, и аудитору. Спул заданий лежит в каталоге C:\Windows\System32\spool\PRINTERS. Каждое задание представлено парой файлов: данные документа в формате EMF или XPS и файл управления заданием с расширением SHD, где хранятся параметры - владелец, принтер, настройки. Пока задание не доставлено, оно живёт на диске, что, кстати, имеет и следовую ценность: спул может содержать текст и изображения документа, поэтому доступ к каталогу ограничен системой.

Классическая бытовая неприятность - застрявшее задание, которое блокирует всю очередь и не удаляется через интерфейс. Отлаженная админская практика восстановления выглядит так:

  1. Остановить службу командой net stop spooler.
  2. Удалить содержимое каталога C:\Windows\System32\spool\PRINTERS - не саму папку, а именно файлы заданий внутри.
  3. Запустить службу командой net start spooler и проверить печать тестовой страницей.

Здесь важно понимать границу: очистка очереди - это восстановление работоспособности реального принтера, а не способ затушить инцидент. Если в спуле оказалось подозрительное задание или сторонний драйвер, сначала стоит сохранить файлы для анализа и проверить журналы событий. Удалённый спул - это и удалённая улика.

Архитектура защиты и современные ограничения

Защита печати сегодня держится на нескольких столпах. Первый - модель драйверов v4, появившаяся ещё в Windows 8. В ней нет ядерной части, нет тяжёлых пакетов от производителя, а драйверы строятся на универсальном классе с конфигурационными файлами. Это резко сужает поверхность: загружать в SYSTEM сторонний бинарный код больше не нужно, а значит, и главный рычаг PrintNightmare теряет силу. Переход парка на v4 и классные драйверы - один из самых действенных шагов.

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

Третий блок - усмирение Point and Print через групповые политики. Администратор ограничивает список серверов, с которых разрешено получать драйверы, требует подписанные пакеты и устанавливать драйверы только администраторам, а также отключает предупреждения, которые отучают пользователя нажимать "согласен" на любой запрос. После событий 2021 года политики Point and Print ужесточились и по умолчанию, но в крупных сетях их стоит выставлять явно, чтобы поведение не зависело от версии обновлений.

Четвёртый элемент - наблюдаемость. Журналы Microsoft-Windows-PrintService позволяют видеть установку драйверов и задания, а события службы и Sysmon добавляют контекст о том, какие библиотеки загружал spoolsv.exe. Регулярный аудит этих источников - не роскошь, а способ заметить аномалию вроде нового драйвера, который никто не заказывал, или задания в неурочный час. Печать слишком долго была слепой зоной мониторинга; исправить это несложно и недорого.

Куда движется печать дальше

Индустрия постепенно уходит от модели, где каждый принтер требует своего драйвера. IPP Class Driver позволяет Windows печатать на любых принтерах, поддерживающих открытый протокол IPP, без установки фирменных пакетов вообще. В связке с Mopria-совместимыми устройствами это превращает принтер в почти бездрайверное сетевое устройство - так же, как класс storage-драйверов когда-то избавил от драйверов флешек.

Параллельный путь - облако. Microsoft Universal Print переносит очереди и управление принтерами в облачный сервис на базе Azure, где печать становится частью управляемой инфраструктуры с централизованными политиками и без выделенных серверов печати в каждом филиале. Для организаций это убирает целый класс уязвимых машин из сети, хотя и добавляет зависимость от облачного контура и его политик доступа.

Типовой аварийный приём зависшей очереди заслуживает отдельной карточки памяти. Когда задание «застряло» и не удаляется, действия короткие: остановить службу spooler, очистить каталог спула, запустить службу обратно - и большинство «поломанных принтеров» возвращаются к жизни без вмешательства в драйвер. Почему это работает: проблема была не в принтере, а в промежуточном файле очереди, и его удаление развязывает узел. Здесь же источник главного операционного риска: каталог спула растёт от сотен заданий гигабайтами, а при забитом системном разделе служба отказывает первой. Место спула администраторы зрелых печатных ферм поэтому выносят на отдельный том и чистят регламентно, а в высоконагруженных фермах очередь обслуживают несколькими службами и перенаправлением портов.

Смотреть на диспетчер печати как на досадное наследие уже поздно - смотреть на него как на привилегированную сетевую службу с богатой историей ошибок нужно было давно. Рецепт здесь не новый: убрать службу оттуда, где она не нужна, держать драйверы под контролем, ограничить Point and Print и следить за журналами. Печать останется с нами ещё надолго, и лучше, чтобы она оставалась бюджетным удобством офиса, а не самой тихой дорожкой к SYSTEM.

Полезна и бытовая нота для конечного офиса: когда очередь зависла, сперва останавливают службу, потом чистят каталог и лишь потом запускают её вновь - без этой простой последовательности застрявший файл гарантирует, что новые задания также встанут строем. Администратору же остаётся разумная повестка: аудит службы там, где печать не используется, аккуратные драйверы и своевременные патчи - гораздо дешевле того варианта, где принтер вдруг становится мостом внутрь периметра.