你是否曾經下載一個 PowerShell 腳本,然後遇到下面這個臭名昭著的錯誤訊息?如果是的話,你需要使用 Set-ExecutionPolicy cmdlet 並參考這篇教程!

在這篇文章中,你將學習有關 PowerShell 執行原則的知識,以及如何使用 Set-ExecutionPolicy cmdlet 來管理這些原則。通過閱讀本文章,你將不僅知道如何運行腳本,還知道如何使用執行原則!
本教程是針對 Windows PowerShell 撰寫的,所有示範都是在 Windows PowerShell 中進行的。執行原則並不僅限於 Windows PowerShell,在 PowerShell 6+ 中的操作方式也非常相似。但是,如果你正在使用 PowerShell 6+,你可能會發現一些行為上的小差異。
執行原則是什麼?
如果你曾經遇到上面描述的錯誤,那麼你就遇到了一個執行原則。PowerShell 執行原則是一種安全機制,用於保護你的系統免受惡意腳本的運行。執行原則不會阻止你在控制台中以 shell 的形式運行 PowerShell 代碼,但是會限制腳本的執行。Microsoft 表示,執行原則在技術上並不是一種「安全」措施,而更像是一個你可以打開或關閉的門。畢竟,你可以輕鬆地繞過已定義的執行原則,這將在後面介紹。
執行策略基於信任。如果你信任一個腳本,很可能它不是惡意的。執行策略通常不會阻止所有腳本的執行。它們的主要目的(特別是在配置得更加嚴格時)是確保你正在運行的腳本是使用證書進行加密簽名的。
執行策略範圍
正如你所了解的,執行策略限制腳本的執行,但 PowerShell 可以在許多不同的上下文中執行腳本。PowerShell 在使用者已登錄的上下文或全局機器上下文中執行腳本,通過以 SYSTEM 身份運行的計劃任務,或在單個已打開的 PowerShell 控制台的範圍內執行。
為了應對所有這些情境,PowerShell 有五種不同的上下文或範圍,你可以定義執行策略。
- MachinePolicy – 此範圍僅限於單台計算機。它影響所有登錄到該計算機的用戶,由 Active Directory 群組策略對象設置。一旦定義,它優先於所有其他範圍。
- LocalMachine。這是影響所有電腦使用者的默認範圍,並存儲在HKEY_LOCAL_MACHINE註冊表子鍵中。使用
Set-ExecutionPolicy
設置執行策略時,此範圍為默認範圍。
LocalMachine的執行策略存儲在註冊表鍵HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell中。
- UserPolicy – UserPolicy範圍僅影響計算機上的單個用戶,由Active Directory群組策略對象設置。您無法使用
Set-ExecutionPolicy
更改此策略。 - CurrentUser。CurrentUser策略範圍僅為當前用戶設置執行策略,存儲在HKEY_CURRENT_USER註冊表中。您無法使用
Set-ExecutionPolicy
更改此策略。
CurrentUser的執行策略存儲在註冊表鍵HKEY_CURRENT_USER\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell中。
- Process – 此範圍定義了單個用戶的單個PowerShell會話的執行策略。與其他執行策略不同,此策略保存在名為
PSExecutionPolicyPreference
的環境變數中,而不是註冊表中。
執行策略類型
執行策略有不同的「安全等級」。這些等級決定了執行策略的嚴格程度。例如,您可以設置一個基本上什麼都不做的執行策略;它是禁用的,但另一方面,執行策略也可以完全禁用腳本執行。
讓我們從最不限制到最限制來介紹如何配置執行策略的安全等級。
不受限制
最不限制的策略是一個完全不受影響的策略;它是不受限制的。 不受限制的執行策略基本上是禁用的。當執行策略為不受限制時,用戶可以運行所有腳本,無論信任與否。
繞過
與不受限制類型相似,設置為繞過的執行策略不會阻止任何腳本。
儘管繞過和不受限制具有類似的效果,但繞過執行策略類型在技術上並不是一種類型。它完全跳過了定義的執行策略。
未定義
雖然不常用,但您可以通過將執行策略設置為未定義來基本上刪除執行策略。當您將執行策略設置為未定義時,PowerShell會從指定範圍完全刪除任何已分配的執行策略。
在非Windows計算機上,執行策略始終設置為不受限制,且無法更改。
當所有範圍都設置為未定義時,PowerShell基本上將所有範圍視為受限制。
RemoteSigned
如您之前所阅读的,执行策略与通过脚本上的数字签名赢得的信任有关。PowerShell还考虑脚本的来源。它是在您的本地计算机上创建的,还是来自互联网上的某个随机人?
在本地计算机以外的地方构建的脚本不应被默认信任。这就是为什么PowerShell提供了RemoteSigned执行策略的原因。RemoteSigned执行策略要求除本地计算机以外的地方编写的所有脚本都经过加密签名。
您可以使用
稍后在“RemoteSigned策略的工作原理”部分详细了解有关从互联网下载的文件的执行策略覆盖。
Unblock-File
cmdlet。稍后在“RemoteSigned策略的工作原理”部分详细了解有关这种行为的更多信息。
对于Windows Server,RemoteSigned被指定为默认策略。
AllSigned
如果您希望确保所有PowerShell脚本都经过加密签名,请将执行策略设置为AllSigned。与RemoteSigned类似,此执行策略将签名要求进一步强化,并强制执行所有脚本在执行之前都必须签名。
即使您已设置了AllSigned执行策略,仍然可以通过绕过它来规避执行策略,稍后您将了解更多信息。
Restricted
最嚴格的執行原則是受限制。當執行原則設置為受限制時,絕對不會執行任何腳本,無論它們是否受信任。這個原則基本上完全禁用了腳本執行。
另外,與較不嚴格的類型不同,受限制類型確保 PowerShell 格式和配置文件(PS1XML)、模塊腳本文件(PSM1)和 PowerShell 配置文件無法執行。
所有 Windows 客戶端默認設置為受限制執行原則。
從技術上講,微軟定義了第七種執行原則,稱為預設值,但該類型本質上是遠程簽署(Windows Server)和受限制(Windows 客戶端)的另一個標籤。
遠程簽署原則的工作原理
需要指出的一個特定情況是遠程簽署執行原則的工作方式。這個執行原則(正如您已經了解的)防止運行在本地計算機之外創建的腳本。
但是 PowerShell 如何知道腳本是在其他地方創建的呢?數據流。
理解和查詢 NTFS 數據流
當您在NTFS 文件系統上創建文件時,NTFS 將一個備用數據流(ADS)屬性應用於該文件。一個 ADS 有兩個文件屬性:$Data和zone.Identifier。PowerShell 使用zone.Identifier屬性來識別在其他地方創建的 PowerShell 腳本文件。
不同于其他属性如Compressed或Read Only,ADS属性在文件资源管理器中是隐藏的。但是,通过使用PowerShell,您可以检查这些数据流。
运行Get-Item
cmdlet,使用脚本路径和Stream
参数,如下所示。在这个例子中,Hello World.ps1是在本地计算机上编写的。请注意分配给Stream
属性的唯一属性是$DATA
,没有ADS属性。

现在,在从互联网下载的脚本上运行相同的命令。注意现在Get-Item
返回一个完全不同的对象,具有Stream
为Zone.Identifier
的属性。

一旦您知道文件有ADS,您可以使用Get-Content
命令来查找zone。区域定义文件的来源。
Get-Content
将返回一个代表文件来源区域的ZoneId
值。

可能的区域值包括:
执行策略优先级
如上所述,同时存在许多不同的执行策略。所有这些执行策略合并起来,决定了当前会话的设置。当存在多个执行策略时,必须具有优先级。
策略优先级是PowerShell应用于不同范围设置的顺序。某些执行策略比其他执行策略具有更高的优先级。
當您執行Get-ExecutionPolicy -List
時,您將找到當前生效的所有執行政策,按照從最低到最高的優先順序排列。例如,因為MachinePolicy的優先順序較低,所以LocalMachine和CurrentUser的政策將覆蓋它。

與執行政策一起工作
瞭解執行政策的背景足夠了,現在讓我們深入研究如何與它們一起工作!要使用PowerShell的執行政策,您有兩個命令可供使用:Get-ExecutionPolicy
用於查找當前定義的政策,以及Set-ExecutionPolicy
用於設置新的政策。
獲取當前分配的政策
在您開始更改執行政策之前,您需要了解您正在使用的內容。為此,您可以使用Get-ExecutionPolicy
命令。此命令會列舉計算機上當前分配的所有政策。
當您在PowerShell控制台上直接運行Get-ExecutionPolicy
命令而不帶任何參數時,它將顯示設置為當前PowerShell會話的執行政策。

要查看設置為特定範圍的執行政策,請使用Scope
參數並指定您想查看結果的範圍名稱。

要查看所有範圍及其執行政策,請使用如下所示的List
參數。

更改執行政策
一旦您知道目前分配了什麼執行原則,您也可以對其進行更改。要在單台計算機上更改策略,您可以使用Set-ExecutionPolicy
命令。但是,如果您在組織中,您可能希望批量更改策略。如果是這種情況,如果您在Active Directory域中,您始終可以使用Group Policy來更改策略。
使用Set-ExecutionPolicy
首先讓我們來看看如何使用Set-ExecutionPolicy
命令更改策略。為此,以管理員身份打開PowerShell。
現在運行Set-ExecutionPolicy
命令,並提供單個參數(ExecutionPolicy
),該參數提供執行原則的名稱。
然後,PowerShell會詢問您是否要更改執行原則。如果是,輸入Y或A,然後按Enter。

某些PowerShell命令需要運行多個其他任務才能操作。如果在上面的示例中您輸入Y
,PowerShell可能會提示您繼續每個步驟。如果按A
,它將繼續進行所有後續步驟。
運行Set-ExecutionPolicy
而無需提示
默認情況下,執行 Set-ExecutionPolicy
時,系統會提示您是否要更改執行原則。您可以通過在命令中添加 Force
參數來跳過此提示。使用 Force
參數將抑制所有確認提示。

通過註冊表設置 PowerShell 執行原則
由於大多數執行原則存儲在註冊表中(不包括 Process),您也可以直接通過註冊表更改原則。
要通過註冊表更改執行原則:
- 打開 Windows 註冊表編輯器(regedit)或您選擇的註冊表編輯工具。
2. 導航到您想要更改的執行原則範圍的註冊表鍵。
LocalMachine – HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell
CurrentUser – HKEY_CURRENT_USER\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell
3. 右鍵單擊註冊表鍵,創建一個名為 ExecutionPolicy 的新字符串值。
4. 雙擊新創建的 ExecutionPolicy 字符串值,並輸入所需的執行原則名稱(Restricted、RemoteSigned、AllSigned、Unrestricted 或 Undefined)。
5. 在相同的键中创建另一个字符串值,称为Path。 Path字符串值表示PowerShell引擎的路径。确保Path值为C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe,指向Windows PowerShell引擎。

CurrentUser执行策略覆盖LocalMachine策略。如果在注册表中设置了CurrentUser策略,并尝试通过Set-ExecutionPolicy
更改执行策略,默认情况下会将策略设置为LocalMachine范围,PowerShell将返回下面显示的错误。

通过组策略设置PowerShell执行策略
如果您在具有Active Directory的组织中,您不希望在所有Windows计算机上运行Set-ExecutionPolicy
cmdlet。相反,您可以使用组策略批量管理策略。
通过GPO管理执行策略:
创建组策略对象
- 在域控制器或域加入的工作站上打开组策略管理应用程序。

2. 展开Domains —> <your Active Directory forest> —> Group Policy Objects。

3. 右键单击Group Policy Objects,然后单击New。
4. 給你的 GPO 起個名字。在這個教程中,GPO 被稱為 PowerShell Execution Policy。

5. 右鍵單擊新建的 GPO,然後單擊 Edit。
6. 導航到 Computer Configuration\Policies\Administrative Templates\Windows Components\Windows PowerShell。

7. 在右窗格中打開設置,打開 Turn on Script Execution 設置。

8. 在 Turn on Script Execution 方塊中,選擇 Enabled 選項。現在你可以選擇下面顯示的任何一個選項:
9. 現在更改 Execution Policy 為你想要的策略。
- Allow only signed scripts – 當受信任的發行者簽署時,允許所有腳本執行。
- Allow local scripts and remote signed scripts – 允許運行本地腳本,但從互聯網下載的腳本應該由受信任的發行者簽署。
- Allow all scripts – 允許運行所有腳本。

指定群組策略對象
一旦創建了 GPO,就該將其指定給目標計算機。為此,必須將 GPO 分配給 Active Directory 組織單元 (OU)。
如果你不是創建新 GPO,而是編輯現有的 GPO,那麼該 GPO 可能已經被分配給一個 OU。
- 在群組原則管理中,通過以下步驟導航到您選擇的 OU:域 —> <您的 Active Directory 樹狀結構> —> <您的 OU>。
2. 在 OU 上按右鍵,選擇連結現有 GPO…。

3. 選擇剛創建的 GPO(PowerShell 執行原則),並按確定。

現在您應該看到 GPO 已分配給 OU,如下所示。

此時,您可以等待定義的群組原則刷新間隔,或在目標計算機上運行gpupdate命令以強制刷新。
鎖定本地策略更改
一旦生效了更改執行原則的 GPO,本地用戶將無法通過本地 PowerShell 控制台更改該策略。如果他們嘗試,將會收到錯誤提示,如下所示。

完全繞過執行原則
如前所述,執行原則不一定是一種安全措施。為什麼呢?因為您可以通過幾種不同的方式完全繞過它。
使用-ExecutionPolicy Bypass
參數
不同于其他执行策略,Bypass策略通常不在PowerShell控制台中设置,而是传递给以管理员身份运行的powershell.exe引擎。
例如,要运行名为Hello World.ps1的脚本,完全跳过任何执行策略,请调用powershell.exe,使用Bypass
参数并提供文件路径如下所示。

阅读脚本和执行原始代码
您还可以通过首先阅读脚本的内容,然后将该内容直接传递给PowerShell引擎来绕过任何执行策略。这样做会逐个运行每个命令,而不是一次运行整个脚本。
如下所示,执行策略设置为Restricted,但通过阅读脚本并传递给powershell.exe,它仍然有效。
这种方法类似于在PowerShell编辑器(如PowerShell ISE或Visual Studio Code)中打开脚本,选择一行并按F8键。

结论
到目前为止,您应该了解有关PowerShell执行策略的所有内容。尽管它们在技术上不是安全措施,但您仍应根据组织政策在组织中管理它们。