1. 程式人生 > >PowerShell 腳本執行策略

PowerShell 腳本執行策略

做出 繼承 pan 腳本文件 dll ren computer -exec define

為防止惡意腳本的執行,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:

Set-ExecutionPolicy -ExecutionPolicy Bypass

註意,設置腳本的執行策略需要管理員權限,因此你需要以管理員權限啟動 PowerShell ,然後執行上面的命令。

AllSigned

Signed 在這裏指有數字簽名的腳本,也就是說 AllSigned 執行策略允許執行所有具有數字簽名的腳本。當然我們也可以換個角度說:只能運行具有數字簽名的腳本。據我所知我們能見到的絕大多數的 PowerShell 腳本是沒有數字簽名的。如果運行沒有簽名的腳本,會提示下面的錯誤:

技術分享

接下來我們要搞清楚如何給一個 PowerShell 腳本簽名(打上數字簽名)?並且在 AllSigned 執行策略下執行這個腳本。
給 PowerShell 腳本簽名需要使用 Set-AuthenticodeSignature 命令,當然前提是你得擁有一個合法的數字證書。比如筆者使用的數字證書文件名為 test.pfx。先用數字證書文件構建一個證書對象:

$cert = Get-PfxCertificate -FilePath "test.pfx"

一般情況下都會為證書設置密碼,所以這一步需要輸入密碼進行驗證。然後為 demo.ps1 腳本文件簽名:

Set-AuthenticodeSignature -FilePath "
demo.ps1" ` -Certificate $cert -IncludeChain "All" ` -TimeStampServer "http://timestamp.verisign.com/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 中,有個枚舉可以標識文件的來源。

public enum SecurityZone
{
    NoZone = -1,
    MyComputer = 0,
    Intranet = 1,
    Trusted = 2,
    Internet = 3,
    Untrusted = 4,
}

當瀏覽器或者 outlook 這樣的工具從網絡上下載文件時,應該通過 Windows 系統提供的 API 把這個枚舉的值進行更新。讓我們從網絡上下載一個 powershell 文(其實可以是任何文件),文件名為 0Start.ps1,右鍵打開屬性界面:

技術分享

上圖紅框中的內容便是對相關屬性的描述。我們還可以通過下面的命令在記事本中以文本的方式顯示其屬性:

技術分享

這裏顯示的已經很清楚了,ZoneId=3 表明這個文件是從網絡上下載的。

Unrestricted

這是一種比較寬容的策略,允許運行未簽名的腳本。對於從網絡上下載的腳本,在運行前會進行安全性提示:

技術分享

但這僅僅是個提示,還是允許腳本執行的。

Bypass

Bypass 執行策略對腳本的執行不設任何的限制,任何腳本都可以執行,並且不會有安全性提示。

Undefined

Undefined 表示沒有設置腳本策略。當然此時會發生繼承或應用默認的腳本策略。

Execution Policy Scope

Scope 指執行策略的應用範圍。原來我們可以給不同的應用範圍設置執行策略。比如進程、當前用戶和本機。
Get-ExecutionPolicy 和 Set-ExecutionPolicy 命令默認操作的都是本機的腳本執行策略。如果要獲得當前用戶的執行策略可以使用 -Scope 選項:

Get-ExecutionPolicy -Scope CurrentUser

同樣如果僅修改當前用戶的執行策略可以在 Set-ExecutionPolicy 命令中使用 scope 參數。

Set-ExecutionPolicy -ExecutionPolicy <PolicyName> -Scope CurrentUser

總結

很明顯,PowerShell 精心設計了腳本的執行策略。遺憾的是在 Windows 8, Windows Server 2012, and Windows 8.1 的系統中,Restricted 被設置為默認的執行策略。這讓學習 PowerShell 的新手們多少有些不知所措,因為所有人都會在第一次執行腳本時遭遇不能執行的問題。還好 MS 在新的系統中把默認的執行策略改成了 RemoteSigned,至少對新手來說更友好了。

PowerShell 腳本執行策略