【问题标题】:Powershell: Safely Decoding SecureStringPowershell:安全解码 SecureString
【发布时间】:2018-02-19 11:50:40
【问题描述】:

请就这两个脚本的安全性发表您的专家意见:

[注意:这两个脚本的输出将被管道化。它们不会被分配给任何变量。"]

第一:

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 是不安全的,因为它首先将安全字符串转换为内存,并且许多人向我指出要使用编组。所以,我把上面的两个脚本构建为试用版,我想知道这两个脚本是否有什么鲁莽的操作。

编辑:

我已经更新了我的第二个字符串以通过实施来清理 BSTR:

finally{
    if ( $bstr -ne [IntPtr]::Zero ) {
  [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr) #Frees the BSTR.
    }
}

但是,在管道中捕获的返回值似乎根本不安全,因为它也在内存中,直到它被清理。

[注意:我还没有编写将接受流水线值的脚本。]

使用安全字符串的意义似乎被解密回明文破坏了。好像我们永远不应该解密安全字符串。如果我错了,请纠正我。

【问题讨论】:

  • 请详细解释您所说的“更安全”是什么意思。
  • 他们仍然将 SecureString 转换为内存......不可能不发生这种情况。你的策略应该是确保一旦不再需要它就从内存中删除。为此,我建议选项 1,但由于它是一个函数,您可能会在某处捕获输出,因此返回的值可能会存在于某处,直到它被垃圾收集
  • @arco444 你的策略应该是确保一旦不再需要它就从内存中删除。为此,我建议选项 1 选项 1 创建不可变的托管 string 对象。您如何建议将其从内存中删除?
  • 解密SecureString 的问题是你不能在这样做之后强行覆盖内存中的纯文本String 副本(它是一个托管的String 对象)。如果您确实需要将SecureString 解密为纯文本,那么这是您将不得不忍受的限制。

标签: powershell securestring


【解决方案1】:

选择的解密技术无关紧要,因为您仍在转换为明文。

即使秘密只在内存中短暂存在,是什么阻止我使用调试技术从内存中读取它?

  • PowerShell 有一个集成调试器,可以单步执行代码并检查变量 (Wait-Debugger)。

  • 可以通过覆盖/重新定义命令行开关、使用别名或其他模拟技术来拦截使用变量、参数或管道的脚本输出。

  • 您也容易受到意外泄露的影响,例如,当您传递秘密的脚本在使用 -Verbose 等时记录它时。

在这个 aspet 中使用管道或直接变量无关紧要。两者本质上都不安全,两者都需要/导致在内存中以纯文本形式保存秘密。

我会寻找一个选项来指定加密到目标的秘密值,完全绕过解密的需要。

【讨论】:

  • 投反对票的原因是什么?我的回答有什么不对吗?
  • 我没有投反对票。顺便说一句,如果我想保持安全性,我似乎不应该将安全字符串解密为纯文本。
  • 请注意,即使您不解密它,任何知道密文并且可以在同一帐户下运行代码(阅读:有权访问解密密钥)的人都可以解密它。
猜你喜欢
  • 2012-09-13
  • 1970-01-01
  • 2016-03-01
  • 2011-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多