最高に誰得なエントリです。
PowerShellの起動時に読まれるps1xmlファイル
で触れましたが、PowerShell 1.0~5.0ではpowershell.exeの起動時に$PSHOME
にある*.format.ps1xml
と*.types.ps1xml
を読み込み、オブジェクトの書式設定やオブジェクトの型に対する追加情報を設定します。
そして、先の記事の以下の引用についてなのですが、
これらのファイルは V2 のサイド バイ サイド インストールをサポートするためにまだ存在するので、ファイルの内容を変更した場合、V5 には影響がなく、影響を受けるのは V2 だけです。 これらのファイルの内容を変更するシナリオはサポートされていないことに注意してください。
ここを読んだ時に最初に「ps1xmlファイルは変更不可では?」という疑問がありました。
というのも$PSHOME
にあるps1xmlファイルは署名付きで改ざんできないはずという記憶があったからです。
ps1xmlファイルの署名
ps1xmlファイルの署名を改めて調べてみました。
結果、PowerShell 1.0 ~ 4.0では$PSHOME
にあるps1xmlファイルはすべて署名付きでした。
下図はPowerShell 4.0のtypes.ps1xml
の例です。最後に署名がついているのがわかります。
これがPowerShell 5.0では署名がなくなりました。
PowerShell 5.0で完全に自由にps1xmlファイルを変更可能になったという感じです。
無視されるps1xmlファイルの署名
実は、署名はついてはいるのですが、組み込み済みのスクリプトの署名を検証するのは実行ポリシーがAllSigned
の場合のみなので、事実上$PSHOME
にあるps1xmlファイルは改変可能だったりします。*1
ただ、$PSHOME
にあるps1xmlファイルだけは特別扱いされているのではないか?(ps1xmlファイルは実行ポリシーの如何に関わらず常に署名が検証されるのでは?)と思い、試しに適当なps1xmlファイルを変更してみました。
その結果、予想とは真逆にPowerShell 2.0からは実行ポリシーがAllSigned
でもps1xmlの署名は一切検証されないことがわかりました。
勿論ユーザーが自分で作ったカスタムps1xmlファイルはAllSigned
であればちゃんと署名の検証がなされます。
$PSHOME
にあるps1xmlファイルだけが一切検証されません。
以下の図はPowerShell 4.0の環境でFileSystem.format.ps1xml
を変更してみたものです。実行ポリシーがAllSigned
でGet-AuthenticodeSignature
の結果がHashMismatch
と検証に失敗しているにも関わらずPowerShellはエラー無く実行できてしまっています。
ps1xmlに対する変更も普通に反映されました。
PowerShell 1.0では実行ポリシーがAllSigned
であれば署名の検証が行われ、PowerShellの起動時にエラーが出ます。
ps1xmlファイルのアクセス権
で、事実上改変可能とはいえ署名を一切見ないというのはセキュリティ的に如何なものかと思ったのでもう少し調べてみました。
するとPowerShell 1.0と2.0以降では$PSHOME
にあるps1xmlファイルのアクセス権の付き方がまるで別物になっている事がわかりました。
PowerShell 1.0ではAdministrators
であればps1xmlファイルに対してフルアクセス権を持っています。
下図はtypes.ps1xml
の場合です。
これがPowerShell 2.0以降では、TrustedInstaller
がファイルの所有権とフルアクセス権を持っておりその他のユーザーはAdministrators
であってもReadOnlyとなっています。
この状態からだと一度所有権を取らないとアクセス権の変更ができず中身を変えることもできません。
どうやらPowerShell 2.0からは署名の検証をしない代わりにファイルのアクセス権を強化することでps1xmlファイルを保護する方針に変わったと思われます。(もしかしたら単純にOSのアクセス権強化なだけかもしれませんが...)
まとめ
ここまでの話をまとめると以下の様になります。
PowerShell 1.0
- PowerShell 1.0では
$PSHOME
にあるps1xmlファイルの署名は検証の対象となります。(実行ポリシーがAllSigned
の場合のみ) $PSHOME
にあるps1xmlファイルはAdministratorsであれば変更できます。
PowerShell 2.0 ~ 5.0
- PowerShell 2.0 ~ 5.0では
$PSHOME
にあるps1xmlファイルの署名は一切検証されません。 - ユーザーが自作したps1xmlファイルの署名は検証の対象となります。(実行ポリシーが
AllSigned
の場合のみ) $PSHOME
にあるps1xmlファイルはAdministratorでも基本的に変更できません。(ファイルの所有権を変えれば変更可能になる)
PowerShell 5.1 ~
- PowerShell 5.1からは
$PSHOME
にあるps1xmlファイルは使われなくなります。
最後に
ここからは完全に私見です。
PowerShellがリリースされた当初は実行ポリシーがAllSigned
の運用が広まり普通に署名付きスクリプトが使われる未来を想定していたのでは?という気がします。*2
しかしながら、現実には実行ポリシーはRemoteSigned
で運用されることが大勢となりps1xmlファイルの署名が意味を成さなくなったためアクセス権を強化することによる保護に切り替えたのではないかと思います。
加えてPowerShell起動時のパフォーマンス向上のためにps1xmlファイルの署名の検証がされなくなり、最終的にはファイルを使うこと自体を止めたのだと思います。
最高に誰得なエントリでしたが何気なく調べた結果が結構面白いことになったので私は満足です。