Windows PowerShell阻隔惡意程式碼

Don Jones

回想 Windows Vista 還在 Beta 測試階段時,有關當時剛剛推出的一個新命令列命令介面程式碼的傳聞甚囂塵上,這個命令介面叫做 Monad (沒錯,它就是後來的 Windows PowerShell)。當時有許多主流媒體都在報導「第一個 Windows Vista 病毒」。事實上,

這個「病毒」只是一個沖著 Monad 而來的概念驗證 (proof-of-concept ) 惡意指令碼。為了執行這個指令碼,Monad 本身還經過特別的設定 (因為這個指令碼無法在預設值下運作)。而且,在媒體報導之前,Microsoft 早已宣布 Monad 不會隨 Windows Vista® 一起發行。總之,整個事件根本就是一場大烏籠 (至少不是普通的烏籠)。

只是,隨著 Windows PowerShellTM 人氣水漲船高 (下載率已超過百萬次),它被有心人士用來建立惡意程式碼的機率也越來越大。能夠在 Windows PowerShell 當中撰寫有潛在破壞力的指令碼,已經是不爭的事實;任何一個管理工具 — 包括 Windows PowerShell、cmd.exe 和 VBScript 在內 — 都有可能被用於歧途。因此您不能再假設 PS1 檔永遠人畜無害。

幸好,Windows PowerShell 在預設的情況下不會執行任何指令碼,如果真的要執行惡意指令碼,也得靠您幫忙才行。那麼這個月就讓我做做預測,看看這件事會不會發生囉。我這麼做不是要讓 Windows PowerShell 難看 — 我認為 Microsoft 所設計的指令碼命令介面,已經足以防範許多風險。但是為了幫助您做好更萬全的準備,全力阻絕潛在攻擊,這個問題仍有探討的必要。

預設的安全環境

值得注意的是,Windows PowerShell 是 Microsoft 繼有名的「高可信度電腦運算」(Trustworthy Computing) 計劃以來首度設計的語言。安全性大師 Michael Howard (《Writing Secure Code》一書的作者) 可說是 Windows PowerShell 小組的安全性夥伴。他的任務是協助大家儘可能撰寫出最安全的程式碼,最重要的是,儘可能設定出最安全且現買現用的命令介面。

首先,讓我們快速檢閱 Windows PowerShell 的初始安全性設定。在預設的情況下,即使您按兩下有 PS1 副檔名的檔案,命令介面也不會執行它。這個副檔名與「記事本」有關。事實上,命令介面在預設的情況下根本不會執行任何指令碼,這全拜一種名叫「執行原則」的內建功能所賜,這項功能負責指定執行指令碼的條件。它在開箱使用時的設定是「限制」,也就是說,所有的指令碼一律禁止執行,命令介面只能用於互動式用途。不過,您可以使用 Set-ExecutionPolicy 指令程式碼,或者透過 Microsoft 所提供的一種群組原則系統管理範本 (ADM 檔) 來更改執行原則 (這個 ADM 檔可以在 go.microsoft.com/fwlink/?LinkId=102940 取得)。[圖 1] 所示的就是您可以設定的執行原則。

[圖 1] 選擇安全的執行原則

[圖 1]** 選擇安全的執行原則 **(按影像可放大)

執行原則只有幾種例外。明確的說,即使設為「限制」,它還是容許命令介面匯入少數由 Microsoft 所提供的 XML 設定檔,讓它們與命令介面一起安裝。這些檔案的用途是提供特定的功能,像是 Microsoft® .NET Framework 型別的延伸模組,以及適用於大部分 .NET 物件類型的預設格式化配置。換句話說,它們絕對是您希望命令介面在啟動時載入的檔案。

這些檔案都可以包含而且也的確包含了執行程式碼,因此它們都有 Microsoft 的數位簽章。這些簽章在遭到篡改之後就會失去作用,即使真的有用,命令介面也不會在啟動時匯入這些檔案。這種設計可以抵禦企圖插入惡意程式碼的惡意程式,保護檔案的安全。

當然啦,即使不更改執行原則的限制設定,它也會阻止您自己的 Windows PowerShell 設定檔指令碼在啟動時執行。Windows PowerShell 在預設情況下並不會建立設定檔指令碼,但它會在四個特定的位置搜尋特定的檔名,只要找到這些檔案,就會在命令介面啟動時跟著執行它們 (隨同 Windows PowerShell 一起安裝的文件,會詳細列出設定檔指令碼所用的資料夾和檔案名稱)。這個設定檔就是我接下來要討論的探索主題關鍵。

修改執行原則

本月指令程式碼

Set-AuthenticodeSignature 的搭檔是 Get-AuthenticodeSignature。這個指令程式碼是為了檢查有數位簽章的指令碼而設計,它詳細提供了簽章的相關資料。您只要指向有疑問的檔案,不e光會看到檔案有沒有被簽署,也會知道簽章有沒有被更動,或是檔案是以哪一種憑證被簽署等相關資訊。這個指令程式碼除了使用 Windows PowerShell 指令碼之外,也會使用經過簽署的執行檔,例如:

PS C:\Program Files\Microsoft Office\Office12>
Get-AuthenticodeSignature excel.exe | Format-List *

我可以藉由執行這個命令,得知執行檔已由 Microsoft Corp. 使用 Microsoft 程式碼簽署憑證授權單位 (Microsoft Code Signing CA) 所發出的憑證加以簽署。

命令結果

命令結果  (按影像可放大)

我要強調的一點是,在預設的情況下,就算不是不可能,也很難讓 Windows PowerShell 執行任何程式碼,更別提惡意程式碼了。除非您修改執行原則,否則惡意指令碼想要作怪根本門兒都沒有。所以這個專欄並不是要警告您 Windows PowerShell 有安全漏洞之虞,只是要跟您分享保護系統的最佳作法。

執行原則的設定下限是「沒有限制」,這個設定可以容許所有的指令碼在毫無限制或問題的情況下執行 — 基本上它所提供的,與 VBScript 和批次檔多年來所提供的不良案例沒什麼兩樣。將命令介面設為「沒有限制」,就等於敞開大門邀請惡意指令碼進屋搞破壞。如果因為您選擇了「沒有限制」設定,而被指令碼進門痛宰一頓的話,那麼在您抱怨解說病毒如何肆虐環境的同時,不妨問問自己為什麼要主動引狼入室。

說真的,即使您設了「沒有限制」,Windows PowerShell 還是會努力偵測您從網際網路下載的指令碼,並且在執行之前提出警告。但重點是,把執行原則設為「沒有限制」,絕對不是明智之舉。

簽署指令碼

如果要容許指令碼執行的話,最安全的執行原則應該是 AllSigned 了。這個設定正如其名,它只執行含有未遭篡改之數位簽章的指令碼,而且這個數位簽章並非一般傳統簽章,而是以受信任憑證所建立的簽章。而要簽署指令碼,必須先取得 Class III 數位憑證 — 說得更明確一點,就是 Microsoft Authenticode 程式碼簽署憑證。這類憑證可以從貴公司的內部公開金鑰基礎架構 (PKI) 取得 (如果有的話),或者向商業憑證授權單位 (CA) (如 CyberTrust、Thawte 和 VeriSign) 購買。

如果您想知道您的電腦上是否有安裝任何可以用來簽署指令碼的憑證,可以使用下面這個指令程式碼:

Get-ChildItem CERT: -recurse –codeSigningCert

當您將憑證安裝在 Windows® 電腦之後,便可以使用 Set-AuthenticodeSignature 指令程式碼來建立和套用數位簽章,這時候指令碼尾端會出現一系列看起來像亂碼的註解行。有的指令碼編輯器會讓您選擇將簽章套用到指令碼檔,有機會在儲存指令碼時自動簽署它,將很方便。

AllSigned 是在實際執行環境中使用的最佳執行原則。雖然它無法徹底阻擋惡意指令碼,但它可以確保惡意指令碼經過簽署,萬一發生什麼事情,您也能夠追蹤到指令碼的作者 (假設您將 Windows 電腦設定為只信任值得信任的憑證授權單位,不過這就稍微超出本專欄的討論範圍了)。有趣的是,Windows Script Host (WSH) 5.6 及更新版也可以用類似的 TrustPolicy 設定加以設定,同樣也需要數位簽章,我就見過幾位系統管理員使用這個設定。

好了,我再把本文重點簡單扼要的帶過一遍。如果您把執行原則設為「限制」,就可以把惡意指令碼擋在門外,不過善意指令碼也同樣無法執行。如果您把執行原則設為 AllSigned,命令介面就會接受經過簽署的指令碼。其實這樣也並無不妥,因為很少有惡意指令碼作者願意在他們的工作上使用經過驗證、可以追蹤的身分。但是「沒有限制」的設定就相當危險了,如果您一定要用它的話,肯定會落到被某個惡意指令碼痛宰的下場 (請注意,我並未把「沒有限制」設定歸類為一種弱點,畢竟它已經明白告訴您它是一隻真正的狼,而不是披著羊皮的狼,所以您在使用這項設定時,原則上就應該明白後果是什麼了)。

從後門潛入

其實您還有另一種執行原則設定可以選擇:RemoteSigned。我相信最近系統管理員最常用的就屬它了,因為一般認為它比「沒有限制」安全,但又沒有 AllSigned 這麼麻煩。RemoteSigned 並不需要本機指令碼的簽章。只要是您本機磁碟機上的 PS1 檔,都可以在不簽署的情況下執行。但是遠端指令碼 — 尤其是使用 Internet Explorer® 或 Outlook® 從網際網路下載的指令碼 (這兩個應用程式會把下載的檔案標上特殊旗標) — 就非得經過簽署才能執行。

不過,RemoteSigned 設定可能會給您一種錯誤的安全感。首先,不套用特殊旗標而下載遠端指令碼是很容易的事。舉個例說,非 Microsoft 的瀏覽器通常都不設定這類旗標,大部分非 Microsoft 的電子郵件用戶端也是。注意了,只要未設定這個旗標,Windows PowerShell 就會把下載的指令碼視同本機指令碼 — 也就是說不需要簽章。還是那句老話,我不認為這是什麼大不了的弱點。因為您必須實際下載指令碼,開啟 Windows PowerShell,然後以手動方式執行指令碼,這樣才能執行它。這些步驟光是要哄騙一般人都不太容易了,更何況是系統管理員,他們應該更清楚狀況才對,而且通常系統管理員還是網路上唯一有安裝 Windows PowerShell 的使用者。

但是,RemoteSigned 有一道很明顯的「後門」,足以讓惡意程式碼乘虛而入。您還記得那些 Windows PowerShell 設定檔指令碼吧?如果它們存在的話,無論是由您還是由惡意程式碼所建立,只要 Windows PowerShell 一執行,它們就跟著執行。而且只要採用 RemoteSigned 執行原則,設定檔指令碼 (它們是本機指令碼) 就不需要簽署。

下面就是一個案例:

  1. 有的惡意程式會進入您的系統,建立一個命令介面設定檔指令碼,或者把惡意程式碼插入現有的設定檔指令碼中。惡意程式碼通常會利用您的登入使用者帳戶執行,而這個帳戶通常都具有修改設定檔指令碼的權限。
  2. 您在開啟 Windows PowerShell 時,並不知道您的設定檔指令碼已被建立或修改成含有惡意程式碼的指令碼。所以當程式碼一執行,就大事不妙了。如果您又有使用系統管理員憑證開啟 Windows PowerShell 的嗜好,那傷害就更大了 — 其實這也是很常見的作法,因為您在使用命令介面時,必須具備系統管理員權限,才能執行需要命令介面的工作。

因此設定檔就等於開了一道後門,讓自定程式碼和惡意程式碼在神不知鬼不覺的情況下潛入,而 RemoteSigned 執行原則就容許這種情況發生。

保護設定檔

要保護設定檔的好方法只有一個:使用 AllSigned 執行原則。只要一採用 AllSigned,即使是您的設定檔指令碼都必須經過數位簽署;否則 Windows PowerShell 不會在啟動時執行它們。設定檔指令碼經過簽署之後,只要有人惡意修改它們,就會中止數位簽章而無法執行 — 其實 Windows PowerShell 也會在啟動時警告您這個問題。對於需要容許指令碼執行的實際執行環境來說,AllSigned 確實是唯一安全的執行原則設定。

其實還有另一種方法,不過它比較複雜,而且比較不可靠。您可以為 Windows PowerShell 所尋找的上述每一種檔案,建立空白的設定檔指令碼檔案。不過,請使用新的使用者帳戶 (我稱它「設定檔編輯器」) 來建立這些檔案,並且設定檔案的 NTFS 權限,這麼一來,只有設定檔編輯器帳戶才能修改它們,其他帳戶只有唯讀權限。

以後除非要編輯您的設定檔,否則千萬不要以設定檔編輯器帳戶登入您的電腦,這麼一來,您的一般使用者帳戶就無法修改您的設定檔指令碼了。不止如此,任何在您以一般帳戶登入時執行的惡意程式碼,都無法修改這些指令碼。但是萬一惡意程式碼正好在您以設定檔編輯器登入時執行,那可怎麼辦呢?這個嘛,反正您也知道您要以設定檔編輯器的身分登入編輯設定檔指令碼,多少應該提高一點警覺吧。

您也可以佈下自己的安全網,也就是依照我剛剛的描述,建立一個以嚴格檔案權限控制的全部使用者設定檔指令碼。然後在這個指令碼中撰寫程式碼,以 Get-AuthenticodeSignature 指令程式碼檢查命令介面所尋找的其他設定檔上的數位簽章。這時候,您自然而然就會要求設定檔指令碼具備簽章,而放過其他指令碼。

但是 AllSigned 執行原則遠比其他方法更能徹底保護您的設定檔。我的建議是,只要是連接到您網路的電腦,都必須將執行原則設為「限制」,而且最好由群組原則套用。這樣可以覆寫任何本機設定,並且確保新網域電腦自動設定為禁止指令碼。而在必須容許指令碼執行的電腦上,則採用另一種設定 AllSigned 執行原則的群組原則。雖然所有的指令碼都必須一一簽署,不過接下來就歌舞昇平了,因為您很清楚能夠在您環境中執行的指令碼,絕對不是由身分不明的作者所撰寫。

Don Jones 是 SAPIEN Technologies 的指令碼語言大師,也是《Windows PowerShell:TFM》(SAPIEN Press,2007 年) 一書的作者。如果您想與他聯絡,可以前往 www.ScriptingAnswers.com

© 2008 Microsoft Corporation and CMP Media, LLC. 保留所有權利;未經允許,嚴禁部分或全部複製.