编写会被他人或计划任务执行的脚本、从网络分发脚本、在服务器上保存凭据、为运维开放受限远程入口时,需要系统性考虑安全边界。也适合审计“为什么这台机器上的脚本行为和其他机器不同”。
如果只是一次性本地命令,不需要引入签名和 JEA;但执行策略、下载来源和凭据处理仍然适用。
Get-AuthenticodeSignature 检查状态,Set-AuthenticodeSignature 用代码签名证书签名;文件被修改后签名立即失效。RemoteSigned 会据此要求签名。Unblock-File 只是移除标记,不会让内容变安全。PSCredential 和 SecureString 避免明文出现在变量和输出里,但不是密钥保管方案;同用户或同进程仍可能还原。优先用 SecretManagement、Windows 凭据管理器、gMSA 或托管身份。Invoke-Expression 执行拼接字符串、iex (iwr ...) 下载即执行、Add-Type 编译任意代码、把密码写进脚本或命令行,都是供应链和凭据风险。# 1. 先看各作用域的执行策略,理解现状而不是直接改成 Bypass
PS C:\> Get-ExecutionPolicy -List
# 2. 检查下载脚本的签名状态和签名者
PS C:\> Get-AuthenticodeSignature .\Deploy.ps1 | Format-List Status, StatusMessage, SignerCertificate
# 3. 用代码签名证书签名;签名后修改文件会使签名失效
PS C:\> $cert = Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert | Select-Object -First 1
PS C:\> Set-AuthenticodeSignature -FilePath .\Deploy.ps1 -Certificate $cert
# 4. 交互式获取凭据,避免把明文密码写进脚本
PS C:\> $cred = Get-Credential
PS C:\> Invoke-Command -ComputerName SRV01 -Credential $cred -ScriptBlock { whoami }
# 5. 查看当前语言模式,受限环境不应被脚本自行绕过
PS C:\> $ExecutionContext.SessionState.LanguageMode
# 6. 7.x 用 SecretManagement 读取机密,不把密码放进脚本
PS C:\> Get-Secret -Name DbPassword -Vault LocalStore
# 7. 转录会话输出;转录不是防篡改审计,敏感输出要另外处理
PS C:\> Start-Transcript -Path C:\Logs\session.txt
PS C:\> Stop-Transcript
# 8. 查看脚本块日志是否开启,定位“谁执行了什么代码”
PS C:\> Get-WinEvent -LogName 'Microsoft-Windows-PowerShell/Operational' -MaxEvents 20 |
>> Where-Object Id -eq 4104
Set-ExecutionPolicy Bypass 解决“脚本不能运行”不是修复,只是关闭护栏;恶意脚本同样可以绕过。应先确认脚本来源、签名和调用链。Unblock-File 只删除下载标记,不代表脚本可信。对来源不明的脚本,先读内容并在隔离环境验证,再决定是否执行。SecureString 当保险箱:它可以被同用户进程还原,ConvertFrom-SecureString 也可能导出可解密内容;真正机密应放受控的机密存储。-AsPlainText -Force 把明文转成 SecureString,只是换了个变量类型,明文仍然出现在命令历史和日志里。合上页面,先回答,再展开对照。
小程序版
微信扫码,随时查命令