SEブログ

【PowerShell】スクリプトに署名する方法について

 

こんにちは!SE ブログの相馬です。

 

 

今回は、スクリプトに署名を付けて、特定のスクリプトのみ動作する方法について書きました。

 

 

 

実行ポリシーについて

 

 

PowerShell には実行ポリシーというものがあります。PowerShell ではどんなスクリプトでも実行ができるわけではありません。むしろ、PowerShell のデフォルト設定では、Restricted という状態になっておりこれではいかなるスクリプトでも実行する事が許可されていません。

 

 

理由としては、スクリプトによってコンピューターを攻撃したりする事ができてしまうので、セキュリティ的に PowerShell は実行ポリシーという機能を付ける事で、環境に合わせて実行ができるスクリプトをレベル別に許可するようにしました。

 

 

という事で、実行ポリシーを Restricted から変更する場合ですが、いくつか種類があります。以下の記事に詳しく書いてありますので見て頂ければと思います。

 

 

【PowerShell】実行ポリシーを変更する

 

 

 

実行ポリシーを変更する

 

 

実行ポリシーが Restricted になっている状態で、PowerShell を実行すると、以下の画像のように「スクリプトの実行が無効になっているため…」という内容が表示され、スクリプトが実行できません。ですので、これをどの実行ポリシーに変更するか、考えなくてはなりませんが、ここでは AllSigned に変更します。

 

 

 

 

AllSigned の内容は上の記事を引用すると以下のとおりです。

 

スクリプトは実行できますが、デジタル署名が付いてなければなりません。

(そのスクリプトをローカル PC で書いても同じです。)

未署名のスクリプトを実行すると、実行を許可するか拒否するか確認ダイアログが表示されます。

(ユーザーが許可を選べば実行します。)

 

という事で、デジタル署名が付いているスクリプトのみ実行ができます。では、どうやってデジタル署名を付けるのかをこの記事で説明します。

 

 

 

デジタル署名

 

 

ではどうやってデジタル署名を作るのかみてゆきましょう。検証目的で自己証明書を作るには New-SelfSignedCertificate コマンドレットを使います。

 

 

New-SelfSignedCertificate | Microsoft Developer Network

 

 

補足:この記事は検証目的で自己証明書を作っています。本番環境では証明書は企業のルート証明書で署名するのが一般的かと思います。

 

$mycert = New-SelfSignedCertificate -Subject "CN=PS CodeSigning" `
-KeyAlgorithm RSA -KeyLength 2048 -Type CodeSigningCert `
-CertStoreLocation Cert:\LocalMachine\My\

 

 

 

では、$mycert を実行して、証明書が生成されたか確認します。

 

$mycert


# 実行結果

PSParentPath: Microsoft.PowerShell.Security\Certificate::LocalMachine\My

Thumbprint Subject 
---------- ------- 
C06ECB6E4FDEA841CC7133DBBA11CB4C6F3C5EF2 CN=PS CodeSigning

 

 

 

自己証明書を以下の Move-Item コマンドレットでルート証明書に移動します。

 

Move-Item "Cert:\LocalMachine\My\$($mycert.Thumbprint)" Cert:\LocalMachine\Root

 

 

 

スクリプトに署名するには、thumbprint が代入されている変数を以下のように書けば簡単にできます。

 

$myrootcert = "Cert:\LocalMachine\Root\$($mycert.Thumbprint)"

 

 

 

これで以下の方法で スクリプトに署名ができるようになりました。

 

set-AuthenticodeSignature \Users\Stuart\Desktop\test.ps1 $mycert


# 実行結果

ディレクトリ: C:\scripts

SignerCertificate Status Path 
----------------- ------ ---- 
C06ECB6E4FDEA841CC7133DBBA11CB4C6F3C5EF2 Valid hello.ps1

 

 

 

これでスクリプトが正しく署名されました。但し、ここで署名したのは信頼できる証明書プロバイダではなく、あくまでも自己証明書です。

 

 

それでは、署名されたスクリプトが AllSigned の実行ポリシーでも動くかどうか、確認しましょう。その前に実行ポリシーを AllSigned に変更しておきます。

 

PS C:\WINDOWS\system32> Set-ExecutionPolicy AllSigned

 

 

 

では署名されたスクリプトを実行してみましょう。実行すると以下のようなメッセージが表示されますので、[一度だけ実行する] をクリックします。

 

 

 

PS C:\WINDOWS\system32> C:\scripts\hello.ps1
Hello World!

 

 

 

やっと問題なく実行ができましたね。そこで署名されたスクリプトファイルの中身ってどうなんでしょう。

 

 

 

署名されたスクリプトファイルの中身

 

 

実行はこんなかんじで、ものすごい多くの文字列が書いてあります。これが署名になっています。

 

 

 

実際、ファイルの中身を変更して実行してみましたところ、セキュリティエラーが発生して実行できませんでした。

 

PS C:\WINDOWS\system32> C:\scripts\hello.ps1
C:\scripts\hello.ps1 : ファイル C:\scripts\hello.ps1 を読み込めません。ファイル C:\scripts\hello.ps1 の内容は、承認されていないユーザーまたはプロセスによって変更された可能性があります。ファイルのハッシュが、デジタル署名に保存されているハッシュと一致しません。このスクリプトは指定されたシステムでは実行できません。詳細については、Get-He
lp about_Signing を実行してください。。
発生場所 行:1 文字:1
+ C:\scripts\hello.ps1
+ ~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : セキュリティ エラー: (: ) []、PSSecurityException
+ FullyQualifiedErrorId : UnauthorizedAccess

 

 

 

 

以上になります。いかがでしょうか。

 

 

署名されたスクリプトのみ実行する環境でなければ特に必要はないですが、どのような方法で署名して実行されるのかが、ここで把握できました。また、今回は検証環境での方法で自己証明書を使ってやりましたが、実際は企業のルート証明書などを使用するかと思います。

 

 

では最後までお読みいただきありがとうございました!