我個人寫過的 PowerShell 腳本可能有數百到上千支,數不清了,由於大部分的腳本都是自己個人使用為主,所以大多都不會特別對這些腳本進行數位簽章。但是對於金融業這種高度管制的企業或組織來說,其實 PowerShell 腳本是被嚴格禁止的,此時對你的 PowerShell 腳本進行數位簽章就顯的十分重要。除此之外,若你要發佈腳本給其他人使用,對腳本進行數位簽章也是一個很好的選擇,不但可以增加可信度,也可以確保腳本的完整性,不會被惡意竄改後重新散佈有問題的版本。這篇文章我將介紹如何對 PowerShell 腳本檔案進行數位簽章。
每次在 PowerShell 使用 GitHub Copilot CLI 的時候,他都經常會回我 bash
底下才有的命令,所以我最近設計了一支 ghcs.ps1 腳本,讓我在尋求 AI 建議時可以盡可能的以 PowerShell 為主,比較不會亂回答,實用性很高!👍
今天我就拿這個腳本來做數位簽章的示範!
新電腦使用 PowerShell 的起手式
這裡我以 Windows Sandbox 為例,快速打造一個全新的 Windows 環境,並且安裝好 PowerShell 7.x 版本。
# 安裝 Chocolatey
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
# 安裝 PowerShell 7.x, Windows Terminal, Git, GitHub CLI
choco install -y powershell-core microsoft-windows-terminal git gh
# 安裝 GitHub Copilot CLI
gh extension install github/gh-copilot
# 如果已經安裝過也可以用以下命令升級
gh extension upgrade gh-copilot
# 登入 GitHub 帳戶
gh auth login --web -h github.com
接著請下載 ghcs.ps1 腳本,並且放到你的 $HOME\Documents\PowerShell\Scripts
目錄下,若是全新的電腦,該目錄可能不存在,需要事先建立:
mkdir $HOME\Documents\PowerShell\Scripts
注意: 這裡的 $HOME
是 PowerShell 的環境變數,代表你的家目錄,通常是 C:\Users\你的使用者名稱
。
除此之外,你還可能需要設定一次 PATH
環境變數,讓你可以直接在 PowerShell 中執行 ghcs
這個指令:
理解 PowerShell 的執行原則
接著我們就可以開始執行 ghcs.ps1
這個腳本了,例如:
ghcs How to list all files?
不過,我們若在 Windows 10 或 Windows 11 第一次執行 PowerShell,通常都會遇到以下錯誤:
因為這個系統上已停用指令碼執行,所以無法載入 C:\Users\XXX\Documents\PowerShell\Scripts\ghcs.ps1 檔案。如需詳細資訊,請參閱 about_Execution_Policies,網址為 https://go.microsoft.com/fwlink/?LinkID=135170。
我在授課 Angular 前端開發課程時,也常常有許多學員遇到這個問題,這是因為 Windows Client 預設的執行原則是 Restricted
,也就是不允許執行任何 PowerShell 腳本,如下圖示:
可以透過以下命令查看不同 Scope 底下的執行原則為何:
Get-ExecutionPolicy -List
事實上,在不同的 Windows 版本中,執行原則有不同的預設值設定:
- Windows Client:
Restricted
(允許執行個別命令,但不允許執行腳本)
- Windows Server:
RemoteSigned
(允許執行本機編寫的腳本,但從遠端下載的腳本必須經過數位簽章)
- Windows Sandbox:
Undefined
(當所有 Scope 都是 Undefined
時,預設會是 Restricted
限制執行)
只要你是透過 Teams
或 Outlook
下載的 PowerShell 腳本,該檔案在儲存到 NTFS 檔案系統時,就會自動幫你加上一些隱形標記。若要移除這些標記,可以透過 Windows 內建的 Unblock-File Cmdlet 來解除封鎖。
由於 Restricted
直接從本機電腦的層級禁止了所有腳本執行,但你依然可以在 CurrentUser
這個各明確的 Scope 層級,將執行原則改成 RemoteSigned
,這樣就可以執行自己寫的腳本了:
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned
因此,你若是寫了一支 PowerShell 腳本,不但想要在自己的電腦上執行,也希望可以讓更多人使用的話,當使用者將執行原則設定為 RemoteSigned
時,你的 PowerShell 腳本要是沒簽章,同時使用者又是從網路上下載你的腳本,那麼他們即便下載也會無法執行的。
注意: 建議不要鼓勵使用者調低 PowerShell 的執行原則,設定為 Bypass
的安全風險極高,因為這樣會讓所有的腳本都可以執行,包括從網路上下載的惡意腳本。
對 PowerShell 腳本檔案進行數位簽章
由於我公司每年都會購買 GlobalSign 的 EV Code Signing 憑證,所以我這裡就以 GlobalSign 為例,示範如何對 PowerShell 腳本檔案進行數位簽章。
-
首先,你需要先安裝 GlobalSign 的驅動程式
因為 GlobalSign 的 EV Code Signing 憑證是透過 USB Token 來進行簽章的,所以你需要先安裝 GlobalSign 的 Safenet Drivers 驅動程式,讓你的電腦可以讀取 USB Token。
注意: 第一次拿到 USB Token 時,你需要先將 USB 進行初始化的操作,每個 USB Token 只需要設定一遍!
-
接著,取得 GlobalSign 的 EV Code Signing 憑證
因為 GlobalSign 的 EV Code Signing 憑證是透過 USB Token 來進行簽章的,你不能將憑證的金鑰匯出,所以你每次要進行簽章時,都需要將 USB Token 插在電腦上。然而,你必須先安裝好 Safenet Drivers 驅動程式,然後 USB 要插在電腦上,讓你的電腦可以讀取 USB Token 的資訊,並執行以下 PowerShell 命令:
$cert = Get-ChildItem -Path Cert:\CurrentUser\My -CodeSigningCert |
Where-Object { $_.Thumbprint -like "*28A7F86E813C879989426E401947473D7FDB911E*" } |
Select-Object -First 1
-
簽署指定 PowerShell 腳本檔案
Set-AuthenticodeSignature -FilePath "$HOME\Documents\PowerShell\Scripts\ghcs.ps1" -Certificate $cert -TimestampServer "http://timestamp.globalsign.com/tsa/r6advanced1"
簽署完畢後,會在檔案最下方出現一大堆像亂碼的簽章內容,這表示你的 PowerShell 腳本已經被數位簽章了。
-
驗證簽章是否有效
Get-AuthenticodeSignature "$HOME\Documents\PowerShell\Scripts\ghcs.ps1"
如此一來,我們的 PowerShell 腳本就已經被數位簽章了,這樣就可以讓其他人在下載執行時,就可以用來確認你這個腳本是由你所簽署的,並且沒有被竄改過。
相關連結