请就这两个脚本的安全性提出专家意见:
[注意:这两个脚本的输出将是流水线的。它们不会被分配给任何变量。"]
首先:
Function GetFrom-SecureString([SecureString]$SecureString) {
[IntPtr]$valuePtr = [IntPtr]::Zero
try {
$valuePtr = [Runtime.InteropServices.Marshal]::SecureStringToGlobalAllocUnicode($SecureString)
return [Runtime.InteropServices.Marshal]::PtrToStringUni($valuePtr);
}
finally {
[Runtime.InteropServices.Marshal]::ZeroFreeGlobalAllocUnicode($valuePtr);
}
}
第二名:
Function Decode-SecureString([SecureString]$SecureString){
try{
$bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureString)
$length = [Runtime.InteropServices.Marshal]::ReadInt32($bstr, -4)
for ( $i = 0; $i -lt $length; ++$i ) {
[CHAR][Runtime.InteropServices.Marshal]::ReadByte($bstr, $i)
}
}
finally{
if ( $bstr -ne [IntPtr]::Zero ) {
[Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr)
}
}
}
我知道使用$cred.GetNetworkCredential().Password
并不安全,因为它首先将securestring转换为内存,许多人指出我使用编组。所以,我已经构建了上述两个脚本作为试用版,我想知道这两个脚本中是否有任何鲁莽的操作。
修改
我已经更新了我的第二个字符串,通过实现:
来清理BSTRfinally{
if ( $bstr -ne [IntPtr]::Zero ) {
[Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr) #Frees the BSTR.
}
}
但是,在管道中捕获的返回值似乎根本不安全,因为它在内存中也是如此,直到它被清理。
[注意:我还没有编写接受流水线值的脚本。]
使用securestring的重点似乎是通过将其解密回明文来销毁。好像我们永远不应该解密securestring。如果我错了,请纠正我。
答案 0 :(得分:0)
所选择的解密技术无关紧要,因为您仍在转换为纯文本。
即使秘密在内存中只存在很短的时间,但是什么阻止我使用调试技术从内存中读取它?
PowerShell有一个集成的调试器,可以进入代码并检查变量(Wait-Debugger
)。
使用变量,参数或管道输出的脚本可以通过使用aliassses或其他模拟技术覆盖/重新定义命令行开关来拦截。
您也容易受到意外披露的影响,例如,当您传递密码的脚本在使用-Verbose
等时记录它时。
在此aspet中使用管道或直接变量并不重要。这两者本身都不是更安全,都要求/导致在内存中以明文形式保密。
我会寻找一个选项来指定加密到目标的秘密值,完全不需要解密。