首页 > 解决方案 > 为什么在存储安全字符串时会这样做?

问题描述

这是否会以某种方式使其比仅使用安全字符串并将其存储在凭据中更安全?为什么有人会这样做?

$secVal = read-host  -AsSecureString -prompt "Enter xstoreuser password"
$strVal = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($secVal)
$dasPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($strVal)

然后稍后

psftp -l somelogin -pw $dasPassword -P 22 -b .\ftp.txt somehost

标签: powershellcredentials

解决方案


您展示的技术不是让命令安全 -相反

您需要做额外的工作才能从[securestring]实例中恢复纯文本密码,因为要将密码传递给外部程序,例如psftp.exe 您需要不安全的 纯文本表示,因为外部程序对 .NET 安全字符串一无所知

SecureString 的安全性如何?向您介绍 .NET 安全字符串及其一般限制。


顺便说一句:提取纯文本密码的命令可以通过 aux 稍微简化。[pscredential]实例:

# Returns the plain-text content of secure string $secVal:
(New-Object pscredential somelogin, $secVal).GetNetworkCredential().Password

如果目标程序支持,唯一安全的方法是完全避免使用纯文本密码,而是使用PKI方法(基于公钥和私钥)。


为了证明纯文本方法是不安全的(即使没有使用中间变量来存储未加密的密码):

# Create a [pscredential] instance with a secure-string password:
# Note: To make this demo self-contained, I'm converting *from* plain
#       text in order to construct the credential object.
#       Note that you should never do that in production code.
#       The need to specify -Force to do it is a reminder that it
#       normally shouldn't be done.
$cred = New-Object pscredential someuser,
          (ConvertTo-SecureString -AsPlainText -Force 'actualPassword')

# Open a new hidden window that passes the password *as plain text* to 
# `cmd /c echo` (and then waits for a keypress, to keep the process alive).
$ps = Start-Process -PassThru -WindowStyle Hidden cmd "/c echo $($cred.GetNetworkCredential().Password) & pause"

# Now inspect the process' command line using CIM (WMI):
(Get-CimInstance Win32_Process -Filter "ProcessID = $($ps.ID)").CommandLine

# Kill (stop) the sample process.
$ps | Stop-Process

以上产生"C:\WINDOWS\system32\cmd.exe" /c echo actualPassword & pause,说明明文密码确实可以通过其他进程获取。

您还可以使用GUI 方法来检查正在运行的进程的命令行:任务管理器 ( Taskmgr.exe),或者在没有潜在截断的情况下,SysInternals 的进程资源管理器 ( procexp.exe),但是,必须按需安装 - 请参阅此 ServerFault 答案


推荐阅读