在cmd中执⾏powershell,我们都是这样:
< -file a.ps1
⾸先看⼀下⽆法加载ps1脚本的解决⽅法
事实上也是由于策略导致的解决⽅法主是开启对应的策略
set-ExecutionPolicy RemoteSigned
执⾏策略更改
执⾏策略可以防⽌您执⾏不信任的脚本。更改执⾏策略可能会使您⾯临 about_Execution_Policies
帮助主题中所述的安全风险。是否要更改执⾏策略?
[Y] 是(Y) [N] 否(N) [S] 挂起(S) [?] 帮助 (默认值为“Y”): y 回车就可以了
查看当前的策略
get-executionpolicy
PowerShell 脚本执⾏策略
sparkdev 2017-09-01
为防⽌恶意脚本的执⾏,PowerShell 中设计了⼀个叫做执⾏策略(Execution Policy)的东西(我更倾向于把它叫做脚本执⾏策略)。我们可以在不同的应⽤场景中设置不同的策略来防⽌恶意脚本的执⾏。本⽂主要是解释这些执⾏策略,因为笔者在学习的时候发现它们并不是那么清晰易懂。
PowerShell 提供了 Restricted、AllSigned、RemoteSigned、Unrestricted、Bypass、Undefined 六种类型的执⾏策略,接下来我们⼀⼀介绍。
Restricted
单词 Restricted 的意思是 "受限制的",所以这种执⾏策略主要是限制脚本的执⾏。说简单点就是:可以执⾏单个的命令,但是不能执⾏脚本。当执⾏策略为 Restricted 时运⾏脚本会收到下⾯的错误:
遗憾的是在 Windows 8, Windows Server 2012, and Windows 8.1 的系统中,Restricted 被设置为默认的执⾏策略。所以在这些环境中要执⾏ PowerShell 脚本的第⼀件事就是调整脚本的执⾏策略。⽐如设置成不会限制脚本执⾏的 Bypass:
1. Set-ExecutionPolicy -ExecutionPolicy Bypass
注意,设置脚本的执⾏策略需要管理员权限,因此你需要以管理员权限启动 PowerShell ,然后执⾏上⾯的命令。AllSigned
当前页面脚本发生错误Signed 在这⾥指有数字签名的脚本,也就是说 AllSigned 执⾏策略允许执⾏所有具有数字签名的脚本。当然我们也可以换个⾓度说:只能运⾏具有数字签名的脚本。据我所知我们能见到的绝⼤多数的 PowerShell 脚本是没有数字签名的。如果运⾏没有签名的脚本,会提⽰下⾯的错误:
接下来我们要搞清楚如何给⼀个 PowerShell 脚本签名(打上数字签名)?并且在 AllSigned 执⾏策略下执
⾏这个脚本。
给 PowerShell 脚本签名需要使⽤ Set-AuthenticodeSignature 命令,当然前提是你得拥有⼀个合法的数字证书。⽐如笔者使⽤的数字证书⽂件名为 test.pfx。先⽤数字证书⽂件构建⼀个证书对象:
1. $cert = Get-PfxCertificate -FilePath "test.pfx"
⼀般情况下都会为证书设置密码,所以这⼀步需要输⼊密码进⾏验证。然后为 demo.ps1 脚本⽂件签名:
1. Set-AuthenticodeSignature -FilePath "demo.ps1" `
2. -Certificate $cert -IncludeChain "All" `
3. -TimeStampServer "timestamp.verisign/scripts/timstamp.dll"
上图中最后⼀⾏中间列显⽰⽂件的前⾯状态为 Valid,表⽰已经签名成功。让我们再来看看 demo.ps1 脚本⽂件都发⽣了什么变化!打开demo.ps1 ⽂件的属性界⾯:
⽐原来多了⼀个 "Digital Signatures" 标签页,这⾥便是数字签名的信息。接着打开 demo.ps1 看看:
除了第⼀⾏脚本命令外,被添加了很多⾏的注释,这都是数字签名⼲的。
接下来我们在 AllSigned 执⾏策略下运⾏⼀下脚本 demo.ps1:
这次的提⽰是说你的系统还没有信任这个证书的持有者(笔者把证书持有者的信息打码了:)),要不要运⾏这个脚本?此时就需要⽤户做出判断了,如果选择 "Always run",不仅会执⾏该脚本,还会把该证书添加到信任列表中:
上图便是选择 "Always run" 之后证书管理器中的信息,笔者⽤来签名脚本的数字证书已经被添加到信任列表中了(就是右边红框中的证书信息)。⼀旦信任了这个数字证书,以后再执⾏由这个数字证书签名的脚本就不会再有提⽰了!
注意:数字证书的使⽤只是增添了⼀道安全机制,绝不意味着有数字签名的脚本就⼀定是安全可靠的。国内某证书颁发机构就因为没有底线乱发证书⽽被⾕歌、⽕狐等产品移出了信任列表。既然有这样的证书颁发机构存在,就会有⼈借机购买数字证书并给恶意的脚本签名,所以不能仅凭是否有数字签名来区分脚本是否可信。
RemoteSigned
从 Windows Server 2012 R2 开始,PowerShell 中默认的执⾏策略改成了 RemoteSigned。这个执⾏策略的意思是:当执⾏从⽹络上下载的脚本时,需要脚本具有数字签名,否则不会运⾏这个脚本。如果是在本地创建的脚本则可以直接执⾏,不要求脚本具有数字签名。
那么问题来了,PowerShell 是如何知道脚本是本地创建的还是从⽹络上下载下来的?
原来,在 Windows 提供的 API 中,有个枚举可以标识⽂件的来源。
1. public enum SecurityZone
2. {
3. NoZone = -,
4. MyComputer = ,
5. Intranet = ,
6. Trusted = ,
7. Internet = ,
8. Untrusted = ,
9. }
当浏览器或者 outlook 这样的⼯具从⽹络上下载⽂件时,应该通过 Windows 系统提供的 API 把这个枚举的值进⾏更新。让我们从⽹络上下载⼀个 powershell ⽂(其实可以是任何⽂件),⽂件名为 0Start.ps1,右键打开属性界⾯:
上图红框中的内容便是对相关属性的描述。我们还可以通过命令 notepad "0Start.sp1:Zone.Identifier" 在记事本中以⽂本的⽅式显⽰其属性:
这⾥显⽰的已经很清楚了,ZoneId=3 表明这个⽂件是从⽹络上下载的。
Unrestricted
这是⼀种⽐较宽容的策略,允许运⾏未签名的脚本。对于从⽹络上下载的脚本,在运⾏前会进⾏安全性提⽰:
但这仅仅是个提⽰,还是允许脚本执⾏的。
Bypass
Bypass 执⾏策略对脚本的执⾏不设任何的限制,任何脚本都可以执⾏,并且不会有安全性提⽰。
Undefined
Undefined 表⽰没有设置脚本策略。当然此时会发⽣继承或应⽤默认的脚本策略。
Execution Policy Scope
Scope 指执⾏策略的应⽤范围。原来我们可以给不同的应⽤范围设置执⾏策略。⽐如进程、当前⽤户和本机。
Get-ExecutionPolicy 和 Set-ExecutionPolicy 命令默认操作的都是本机的脚本执⾏策略。如果要获得当前⽤户的执⾏策略可以使⽤ -Scope 选项:
1. Get-ExecutionPolicy -Scope CurrentUser
同样如果仅修改当前⽤户的执⾏策略可以在 Set-ExecutionPolicy 命令中使⽤ scope 参数。
1. Set-ExecutionPolicy -ExecutionPolicy <PolicyName> -Scope CurrentUser
总结
很明显,PowerShell 精⼼设计了脚本的执⾏策略。遗憾的是在 Windows 8, Windows Server 2012, and Windows 8.1 的系统中,Restricted 被设置为默认的执⾏策略。这让学习 PowerShell 的新⼿们多少有些不知所措,因为所有⼈都会在第⼀次执⾏脚本时遭遇不能执⾏的问题。还好 MS 在新的系统中把默认的执⾏策略改成了 RemoteSigned,⾄少对新⼿来说更友好了。
发布评论