Каждый, кто администрирует сеть из десятка машин, рано или поздно упирается в одну и ту же стену. Пользователь приходит со словами "у меня пропал доступ к сетевой папке", и начинается ручное хождение по компьютерам, открытие графического диспетчера, клики по записям, ввод паролей мышкой. На пяти машинах терпимо. На пятидесяти это превращается в отдельную профессию. А ведь Windows давно носит в себе пару утилит, которые делают всю эту рутину одной строкой и позволяют разворачивать настройки скриптом сразу на парк техники.

Речь о хранилище учётных данных, которое в системе называется Credential Manager, а под капотом опирается на защищённое хранилище Windows Vault. Именно там операционная система держит логины и пароли для сетевых ресурсов, удалённых рабочих столов, веб-сайтов и отдельных приложений. Графическая оболочка показывает лишь верхушку этого механизма. Настоящая гибкость открывается из консоли, и держится она на двух командах с короткими именами cmdkey и vaultcmd.

Как устроено хранилище и почему сохранённый пароль безопаснее ручного ввода

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

%Systemdrive%\Users\<Имя>\AppData\Local\Microsoft\Vault\

Рядом, в файле политики Policy.vpol, хранится ключ шифрования, привязанный к учётной записи владельца. Из этой привязки растёт важное следствие: чужой профиль свои секреты вам так просто не отдаст.

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

Просмотр того, что уже хранится на машине

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

cmdkey /list

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

cmdkey /list:interactive

А если интересует конкретный сервер, в качестве цели подставляется его имя:

cmdkey /list:srv-01

Эти три варианта закрывают почти всю повседневную разведку. Привычка начинать любую операцию именно со списка спасает от случайного удаления нужной записи и даёт понять, в каком состоянии хранилище досталось вам от предыдущего владельца машины.

Создание записей для сетевых ресурсов

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

cmdkey /add:srv-01 /user:DOMAIN\Ivanov /pass:MyPa$$word

Здесь srv-01 это targetname, то есть имя компьютера или домена, с которым связывается учётная запись. Ключ user задаёт логин в формате домен и имя, pass передаёт пароль. После выполнения система сама будет подставлять эти данные при обращении к указанному узлу.

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

cmdkey /add:srv-01 /user:DOMAIN\Ivanov

Полное имя цели можно задавать и развёрнуто, вплоть до FQDN, если в сети несколько узлов с похожими короткими именами:

cmdkey /add:srv-01.contoso.local /user:CONTOSO\Ivanov /pass:MyPa$$word

Эта детализация снимает путаницу, когда Chelsea-сервер из одного отдела и сервер с тем же коротким именем из другого норовят перехватить чужие учётные данные. Чем точнее цель, тем предсказуемее поведение хранилища.

Учётные данные для удалённого рабочего стола и прочих сервисов

Простой ключ add годится для обычного сетевого входа. Но когда речь о терминальном сервере или ином сервисе, запись нужно создавать через ключ generic, иначе подсистема её попросту не найдёт. Для удалённого рабочего стола цель формируется со специальным префиксом termsrv:

cmdkey /generic:termsrv/SRV-RDP /user:Ivanov /pass:RdpPa$$word

Префикс termsrv это не прихоть, а способ, которым подсистема RDP ищет нужные учётные данные. Без него Windows не свяжет сохранённый пароль с попыткой подключения к удалённому столу, и окно ввода будет выскакивать снова и снова. Тот же ключ generic применяют для общих интерактивных учётных данных, не привязанных к одному узлу:

cmdkey /generic:interactive /user:user1 /pass:password1

Разница между add и generic тонкая, но принципиальная. Первый создаёт запись для сетевого входа в систему, второй общую учётную запись, которой пользуются отдельные сервисы и приложения. Перепутав их, легко получить ситуацию, когда пароль вроде бы сохранён, а нужный сервис его не видит.

Точечное и массовое удаление устаревших паролей

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

cmdkey /delete:srv-01

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

Удалять руками по одной это работа на полдня. Выручает старый цикл командной строки, который связывает вывод cmdkey с фильтром findstr. Чтобы вычистить разом все сохранённые пароли удалённого рабочего стола, применяется такая конструкция:

for /F "tokens=1,2 delims= " %G in ('cmdkey /list ^| findstr "target=TERMSRV"') do cmdkey /delete %H

Разберём, что тут происходит. Команда cmdkey /list отдаёт весь перечень, findstr оставляет лишь строки терминальных подключений, а цикл for разбивает каждую такую строку на токены и передаёт имя цели обратно в cmdkey /delete. Вертикальная черта экранируется крышечкой, иначе интерпретатор поймёт её не так, как задумано внутри скобок. Если же нужно снести вообще все сохранённые пароли, фильтр меняется на общее слово Target:

for /F "tokens=1,2 delims= " %G in ('cmdkey /list ^| findstr Target') do cmdkey /delete %H

Одна строка способна за секунду привести хранилище в чистое состояние. Применять её стоит с холодной головой, ведь вместе с мусором улетят и рабочие записи. Зато при диагностике загадочных блокировок в Active Directory именно такая чистка часто разрывает порочный круг неудачных входов. Маленькая, но важная деталь: внутри bat-файла знак процента перед переменной нужно удваивать, иначе цикл, безотказно отработавший в открытой консоли, в скрипте молча ничего не сделает:

for /F "tokens=1,2 delims= " %%G in ('cmdkey /list ^| findstr Target') do cmdkey /delete %%H

На этом удвоении спотыкались, наверное, все, кто хоть раз переносил рабочую команду из консоли в скрипт.

Утилита vaultcmd и заглядывание внутрь схем хранилища

Там, где cmdkey управляет записями, vaultcmd позволяет рассмотреть само устройство хранилища. Эта утилита поставляется в составе Windows начиная с седьмой версии и работает с хранилищами на уровне их структуры. Перечень доступных хранилищ выводит первая команда:

VaultCmd /list

Список схем, по которым раскладываются записи, показывает вторая:

VaultCmd /listschema

А содержимое конкретного хранилища открывает третья, с указанием его имени в кавычках:

vaultcmd /listcreds:"Windows Credentials"

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

vaultcmd /listcreds:"Учётные данные для Интернета"

И здесь кроется типичная ловушка. Имя хранилища в кавычках зависит от языка системы. Обращение к русскому хранилищу через английское имя выдаст ошибку "Недопустимое хранилище: элемент не найден". На неё постоянно напарываются при переносе скриптов между машинами с разными языковыми настройками. Когда vaultcmd жалуется, первым делом стоит проверить именно язык и точное написание имени, а не искать поломку в самой утилите.

Резервное копирование базы и перенос на другую машину

Графический диспетчер умеет одну вещь, которую консольные утилиты напрямую не дают. Через классический диалоговый интерфейс управления сохранёнными именами и паролями доступны резервное копирование и восстановление всей базы Credential Manager. Сам диалог вызывается командой:

rundll32.exe keymgr.dll,KRShowKeyMgr

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

PowerShell тоже не остаётся в стороне. На нём строят скрипты, которые проходят по выводу cmdkey, выдёргивают имена целей и пакетно их обрабатывают. Простой пример, собирающий список целей в переменную для дальнейшей обработки:

$creds = cmdkey /list | Select-String "Target:" | ForEach-Object { ($_ -split "Target: ")[1] }

Дальше по этому списку можно пройти циклом и удалить или пересоздать записи на множестве машин через средства удалённого управления. По сути PowerShell здесь выступает обёрткой над теми же cmdkey и vaultcmd, добавляя удобный разбор текста и ветвления логики.

Практические сценарии, ради которых всё это затевалось

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

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

cmdkey /add:fileserver /user:DOMAIN\user /pass:secret
net use Z: \\fileserver\share /persistent:yes

Без предварительно сохранённой записи диск каждый раз будет требовать аутентификацию, и автоматизация рассыплется. Отдельная боль это диагностика блокировок в Active Directory, когда старый сохранённый пароль тихо стучится в контроллер домена с устаревшими данными, копит неудачные попытки и в итоге запирает живого человека. Здесь массовая чистка через цикл с findstr срабатывает как точная хирургия: убрали мусорные записи, и блокировки прекратились.

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

Windows прячет в себе немало таких неприметных утилит, которые делают жизнь администратора заметно проще, но многие из них остаются в тени графических оболочек. Пара cmdkey и vaultcmd ровно из этого ряда. Стоит один раз разобраться с их ключами, и управление сохранёнными паролями из утомительной возни мышкой превращается в несколько отточенных строк, которые одинаково хорошо работают и на одной машине, и на целом парке техники.