Безопасно ли использовать аргумент пароля в команде Windows?

Представьте, что у нас есть программа или скрипт, который может принимать аргумент пароля (или другую конфиденциальную информацию):

> program.exe /password:secret

Для Linux лучшие практики обычно не рекомендуют указывать пароль непосредственно в командной строке из-за потенциальных проблем безопасности (пароль может появиться в файле истории оболочки и таблице процессов системы):

$ ./program.sh --password 'secret' &
[1] 4152

$ cat /proc/4152/cmdline 
/bin/sh./program.sh--passwordsecret

Однако при поиске я не вижу такой же активной рекомендации для Windows.

При написании программ и сценариев для Windows, должны ли мы предоставить альтернативное средство для ввода пароля помимо аргумента параметра командной строки, чтобы избежать непреднамеренного раскрытия пароля?

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

Меняются ли последствия для безопасности при запуске программы из пакетного файла или сценария PowerShell, который передает пароль в качестве аргумента программе?

$password = # prompt for password 
program.exe /password:$password

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

2 ответа

Решение

Исторически Windows не сохраняла историю команд между сеансами, только внутри сеанса. Это было верно для командной строки и для PowerShell.

Как отметил Bill_Stewart, Windows PowerShell в Windows 10 и Windows 2016 по умолчанию включает PSReadline, который сохраняет историю команд между сеансами. Вы можете увидеть это, посмотрев файл здесь: (Get-PSReadLineOption).HistorySavePath,

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

Если вы должны предложить это, у вас также должен быть способ получить подсказку программы во время выполнения.

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

Эта проблема двоякая: строки являются неизменяемыми в.Net, что означает, что вы не можете просто изменить строку пустыми или случайными символами, чтобы очистить ее в памяти (вы на самом деле создадите новую строку), и, кроме того, вы не может контролировать, когда конкретный объект будет обрабатываться сборщиком мусора, поэтому вы не можете явно удалить его.

Вот почему SecureString класс существует, но не все могут использовать это.

В PowerShell есть PSCredential объект, который хранит имя пользователя в виде простого текста и пароль в виде SecureString, Это всегда должно использоваться в PowerShell и должно быть предпочтительным типом аргумента (вместо отдельного имени пользователя и пароля).

Большинство команд в PowerShell, для которых требуются учетные данные, принимают его как объект этого типа.

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

На мой взгляд, все же предпочтительнее использовать PSCredential возражать в этих ситуациях, вплоть до того момента, пока вам не понадобится текстовая версия. Это помогает поддерживать стандартизацию этого типа как во встроенной / "официальной" емкости, так и в пользовательских командах.

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

Чтобы более прямо ответить на мой вопрос, вот небольшое дополнение к отличному ответу briantist:

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

Мы можем использовать инструментарий управления Windows для извлечения аргументов командной строки в PowerShell и других программах, подобных тем, которые созданы на.NET. Вот пример использования PowerShell:

PS> Get-WmiObject Win32_Process -Filter 'Name = "program.exe"' | Select-Object CommandLine

C:\program.exe /password:secret

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

Снимок экрана диспетчера задач с аргументом пароля в виде простого текста

Как написал в своем ответе briantist, программы и сценарии, которые мы пишем, должны предоставлять альтернативные средства для ввода конфиденциальной информации помимо аргументов командной строки. Сценарии PowerShell могут безопасно передавать эту информацию между сценариями, используя PSCredential или же SecureString объекты.

Другие вопросы по тегам