PowerShellの実行ポリシー(ExecutionPolicy)
PowerShellには実行ポリシーというものがあって、何も設定していないと.ps1
のスクリプトファイルの実行がブロックされます。
.\poetry-template.ps1 : このシステムではスクリプトの実行が無効になっているため、
ファイル poetry-template.ps1 を読み込むことができません。詳細に
ついては、「about_Execution_Policies」(https://go.microsoft.com/fwlink/?LinkID=1
35170) を参照してください。
発生場所 行:1 文字:1
+ .\poetry-template.ps1 hoge
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : セキュリティ エラー: (: ) []、PSSecurityException
+ FullyQualifiedErrorId : UnauthorizedAccess
実行ポリシーをどうするかは悩みどころです。
Set-ExecutionPolicy RemoteSigned
って設定すればいいよ、と書いてある記事も多いですがちょっと待った!
おそらくそれは適切な設定でない場合が多いです。
本記事では、実行ポリシーについて調べたり実際に動かして確かめてみたりしたことを書きます。
ただし、セキュリティに関わることなので設定変更はご慎重に。
本記事のターゲットは「個人PCで趣味程度に開発している一般Windowsユーザー」です。
企業PCの場合は(基本的に)設定いじらないか上司や情シスに確認を。
個人PCでも自己責任で!
結論から
※個人のPCであるという前提の上で
一回のみの実行なら、
powershell -ExecutionPolicy RemoteSigned .\test.ps1
1スコープのみのスクリプト利用であれば、
Set-ExecutionPolicy RemoteSigned Process
# 現在のスコープでのみ(今開いているpowershellを閉じるまで)実行が有効になる
頻繁にpowershellスクリプトを利用する場合は、
Set-ExecutionPolicy RemoteSigned CurrentUser
# 現在のユーザーで実行が有効になる
の設定で良い場合が多そう。
ただし、実行ポリシー変更によるセキュリティリスクはしっかり理解しておくこと。
利用用途によって適切な設定は異なります。
少なくとも公式ドキュメントは読みましょう。
実行ポリシーの種類
改めて公式ドキュメント。
実行ポリシーは厳しい順に Restricted
(デフォルト), AllSigned
, RemoteSigned
, Unrestricted
, Bypass
です。
こちらのQiita記事の表がわかりやすいですね。
引数 ローカル リモート Restricted × × AllSigned 署名付きのみ〇 署名付きのみ〇 RemoteSigned 〇 署名付きのみ〇 Unrestricted 〇 〇
スコープは狭い順に、Process
(現在のセッションのみ), CurrentUser
(現在のユーザーのみ),LocalMachine
(現在のコンピュータすべて) です。(MachinePolicyとUserPolicyはグループポリシー関係ですが、本記事では扱いません。)
狭いスコープの実行ポリシーが優先されます。
できるだけ実行ポリシーが厳しい&狭いスコープの方がセキュリティ的には良いですよね。
利便性とセキュリティはトレードオフなところがあるので、どのレベルにしておくかはご自身の環境に合わせた設定が必要です。
確認方法・設定方法
Get-ExecutionPolicy
で現在のポリシーを確認できます。
> Get-ExecutionPolicy
RemoteSigned
Get-ExecutionPolicy -List
でスコープごとのポリシーを確認できます。
> Get-ExecutionPolicy -List
Scope ExecutionPolicy
----- ---------------
MachinePolicy Undefined
UserPolicy Undefined
Process Undefined
CurrentUser RemoteSigned
LocalMachine Undefined
上から見ていって最初にUndefinedではないポリシーが適用されます。(↑の例はRemoteSigned)
すべてUndefinedの場合は(普通のwindowsPCなら)Restrictedになります。
次にポリシーの設定方法です。
CurrentUser
スコープでRemoteSigned
にしたい場合は以下の通り。
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
第一引数、第二引数の順を守っていればオプション名の省略も可能です。
Set-ExecutionPolicy RemoteSigned CurrentUser
スコープのデフォルトはLocalMachine
です。
そしてLocalMachine
スコープのポリシー変更には管理者権限が必要です。
セキュリティ的には緩いポリシーはできるだけ狭いスコープに抑えたいので、必要ないのであれば緩いポリシーはLocalMachine
ではなくCurrentUser
で設定した方がよいですね。
全ユーザーに対して実行ポリシーを適用させたい意図があるならLocalMachine
でもいいですが、おそらく現在のユーザーに設定を適用させたい場合がほとんどだと思います。
つまり、少なくとも
Set-ExecutionPolicy RemoteSigned
はやめて、
Set-ExecutionPolicy RemoteSigned CurrentUser
にしましょう。(Set-ExecutionPolicy RemoteSigned CurrentUser
の是非はこれ以降の章で検証)
Python公式ドキュメントに実行ポリシーに関する記述あり
セキュリティに関わる重要な項目。
できれば信頼できる機関がどう判断しているのか参考にしたいところです。
Python公式ドキュメントでpowershellの実行ポリシーに関する記述を見つけました。
venvの項目です。(venv: 公式が提供するPythonの仮想環境)
venvで仮想環境をアクティブにするとき、powershellではActivate.ps1
を実行する必要があります。
なので、何かしら実行ポリシーを変更する必要があるのです。
Note On Microsoft Windows, it may be required to enable the Activate.ps1 script by setting the execution policy for the user. You can do this by issuing the following PowerShell command:
PS C:> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
See About Execution Policies for more information.
Windowsユーザーは実行ポリシーをCurrentUser
スコープでRemoteSigned
にするよう書いてありますね!
RemoteSigned
よりも実行ポリシーが厳しいAllSigned
については以下の記事が非常に参考になります。
ただ、venvの用途を考えるとAllSigned
やProcess
スコープで運用するのは、(できなくはないが)少し厳しいでしょう。
venvを使う場合はCurrentUser
スコープのRemoteSigned
で設定するのは適切だと思います。
大手がそう言っているからと言ってそれが正しいとは限りませんが、何の判例がないよりはマシです。
「頻繁に新しいps1ファイルを実行する必要がある場合、Set-ExecutionPolicy RemoteSigned CurrentUser
と設定するのはある程度妥当かもしれない」と一旦考えてみます。
その上で、RemoteSigned
で何が防げてRestricted
と比べて何が防げなくなったのかはきちんと確認しておきましょう。
RemoteSignedについて調査
公式ドキュメントではRemoteSigned
について以下のように書かれています。
RemoteSigned
Windows サーバー コンピューターの既定の実行ポリシー。
スクリプトを実行できます。
電子メールやインスタント メッセージング プログラムを含むインターネットからダウンロードされたスクリプトと構成ファイルに、信頼できる発行元からのデジタル署名が必要です。
ローカル コンピューターで記述され、インターネットからダウンロードされていないスクリプトにデジタル署名は必要ありません。
コマンドレットを使用するなどして、スクリプトのブロックが解除されている場合は、インターネットからダウンロードされ、署名されていないスクリプトを Unblock-File 実行します。
インターネット以外のソースから署名されていないスクリプトを実行し、悪意のある可能性がある署名付きスクリプトを実行するリスクがあります。
https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_execution_policies?view=powershell-7.3#remotesigned
要約すると、
- 署名付きは実行可能
- 署名なしでローカル作成は実行可能
- 署名なしでインターネットからダウンロードされたものは実行できない
ということになります。
ほんとにRemoteSigned
ではインターネットからダウンロードされたものは実行できないのか試してみました。
ローカルで作成した ps1 を実行してみる
まずローカル作成のps1ファイルを実行してみましょう。
Write-Output "hello world!"
> .\test.ps1
hello world!
これは普通に実行できるはずですね。
ps1 を git clone して実行してみる
GitHubにps1ファイルが入ったリポジトリを作成。
これをcloneして実行ポリシーRemoteSigned
で実行してみると…
エラーが発生することなく実行できてしまいました。
git clone はインターネットからダウンロードした判定にならないんですね。
ps1 をダウンロードして実行してみる
今度はcloneではなく、Download ZIP でローカルに落として解凍してps1ファイルを実行してみたところ…
今後はエラーが出ました。いわゆるダウンロードで落としたものはちゃんとブロックしてくれてそうですね。
.\poetry-template.ps1 : ファイル C:\Users\hoge\Downloads\project-from-template-script-master\project-from-template-scr
ipt-master\poetry-template.ps1 を読み込めません。ファイル C:\Users\hoge\Downloads\project-from-template-script-master\
project-from-template-script-master\poetry-template.ps1 はデジタル署名されていません。このスクリプトは現在のシステムで
は実行できません。スクリプトの実行および実行ポリシーの設定の詳細については、「about_Execution_Policies」(https://go.mic
rosoft.com/fwlink/?LinkID=135170) を参照してください。
発生場所 行:1 文字:1
+ .\poetry-template.ps1
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : セキュリティ エラー: (: ) []、PSSecurityException
+ FullyQualifiedErrorId : UnauthorizedAccess
もしこのインターネットからダウンロードされたファイルのブロックを解除したい場合は、Unblock-Fileというコマンドを使うと良いようです。
ブロックを解除すると、ローカルで作成したファイルと同じ判定になります。
zipで落としたps1ファイルも
Unblock-File poetry-template.ps1
でブロック解除すると、RemoteSigned
の状態でも実行できるようになりました。
なるほど…。
メールから ps1 をダウンロード?
そういえば公式ドキュメントには、
電子メールや…からダウンロードされたスクリプト…
と書いてあったので、自分宛てにps1ファイルを送ってそれをダウンロードして確かめてみようと思ったのですが…
セキュリティ上の理由によりブロックされました。
Gmail では、ウイルスや不正なソフトウェアからユーザーのアカウントを保護するため、次のようなファイルは添付できません。
特定のファイル形式。これには、圧縮されている場合(.gz や .bz2 など)や、アーカイブに格納されている場合(.zip や .tgz など)も含まれます
まず送ることができませんでした。
Gmailではps1ファイルを普通には送ることができないみたいですね。
でもそれはGmailがちゃんとしているからであって、他のところからは送信できたりすると思うので注意。
今回検証しませんでしたが、おそらく電子メールからダウンロードしたps1ファイルもRemoteSigned
でブロックしてくれるんだと思います。
GUIで実行してみる
今までpowershellからCUIで実行しようとしていましたが、GUI(つまりダブルクリックなど)で実行しようとしたらどうなるでしょうか?
(windows11 で確認したので windows10 ではちょっと違う挙動になるかもしれません)
メモ帳が開きましたね。
ps1ダブルクリックはデフォルトではメモ帳で開くだけみたいです。
右クリックメニューに「PowerShellで実行」があります。
こちらは予想通りスクリプト自体を実行するものですが、実行できるかどうかは実行ポリシーに準じます。
実行ポリシーにそぐわない場合は、一瞬powershellが立ち上がるのですが中身が実行されずにそのまま終了します。
そもそもRestricted
ってどこまで防げるのか?
Restricted
は一番厳しい実行ポリシーであり、すべてのps1ファイルが実行できなくなると公式ドキュメントには書いてあります。
前の章のRemoteSigned
で実行できた、「ローカルで作成したps1ファイル」も「git clone したps1ファイル」もRestricted
で試してみると確かに実行できませんでした。
では、Restricted
にしていたら絶対にps1ファイルを実行できないのでしょうか?
答えは No です。
実は結構簡単に回避できちゃう
こちらのQiita記事には、ショートカットやバッチファイルでps1ファイルを実行する方法が書いてあります。
簡単に説明すると、ショートカットやバッチファイルで一時的に実行ポリシーを緩くした状態でpowershellを立ち上げてps1ファイルを実行している感じです。
同じような手順で、例えばPythonからもps1ファイルを実行可能です。
ここに危ないps1ファイルがあるとします。
Write-Output "Your computer has been infected with a virus!"
これをRestricted
のときに普通に実行しようとするとエラーが出ます。
> Get-ExecutionPolicy
Restricted
> .\danger.ps1 .\danger.ps1 : このシステムではスクリプトの実行が無効になっている
ため、ファイル C:\Users\hoge\Downloads\temp\danger.ps1 を読み込む
ことができません。詳細については、「about_Execution_Policies」(htt
ps://go.microsoft.com/fwlink/?LinkID=135170) を参照してください。
発生場所 行:1 文字:1
+ .\danger.ps1
+ ~~~~~~~~~~~~
+ CategoryInfo : セキュリティ エラー: (: ) []、PSSecu
rityExcep tion
+ FullyQualifiedErrorId : UnauthorizedAccess
次はPythonのos.system()
で実行しようとします。
import os
os.system("powershell .\danger.ps1")
> Get-ExecutionPolicy
Restricted
> python .\main.py
.\danger.ps1 : File C:\Users\hoge\Downloads\temp\danger.ps1 canno
t be loaded because running scripts is disabled on this system. Fo
r more information, see about_Execution_Policies at https:/go.micr
osoft.com/fwlink/?LinkID=135170.
At line:1 char:1
+ .\danger.ps1
+ ~~~~~~~~~~~~
+ CategoryInfo : SecurityError: (:) [], PSSecurityEx
ception
+ FullyQualifiedErrorId : UnauthorizedAccess
これもブロックされました。
ここまではOKですね。
では先ほどのQiita記事のように実行ポリシーオプションをつけてみて実行します。
import os
os.system("powershell -ExecutionPolicy RemoteSigned .\danger.ps1")
> Get-ExecutionPolicy
Restricted
> python .\main.py
Your computer has been infected with a virus!
実行できてしまいました!
今回はPythonのコードは一行しかないのでps1ファイルを実行しようとしていることは丸わかりですし、danger.ps1なんて名前のファイルは明らかに実行してはいけないとわかります。
しかし、複数ファイルかつ何百行のPythonプログラムに1行だけ入っていたらどうでしょうか?
ps1ファイルが複雑にネストされた場所に置かれていたらどうでしょうか?
上記の通り実行ポリシーオプションをつけてなければブロックできますが、悪意を持って実行させようとしているなら当然ただ十文字程度加えるだけの実行ポリシーオプションをつけないことはないでしょう。
それに、サイバー攻撃の手口はそんな単純なものばかりではなく、色々な手法を使って対策を回避してきます。powershellを使ったものだとファイルレスマルウェアとか。
要するに、実行ポリシーの設定だけではpowershellに関するセキュリティリスクを完全に排除することはできないというわけです。
きちんと対策・運用するならそれ以上の措置が必要でしょう。
一般社団法人ソフトウェア協会のセキュリティ委員会が母体の「Software ISAC」がPowerShellの悪用に対する措置等について詳しく書いてくれています。
個人PCでもこのサイト通りにきっちり管理しても良いとは思います。
ただ、個人と企業(組織)では抱えてるセキュリティリスクの大きさに差があるでしょう。その上、一般ユーザーが上記内容を理解して設定・運用するのは少し難しいでしょう。(企業でもここまできっちり管理しているのは全体の何%くらいなんだろうか…)
結局実行ポリシーは意味あるの?
もちろんあります。
確かに実行ポリシーだけで完全な防御は無理です。
しかし、「多角的に対策をとる」というのがセキュリティの基本です。
本記事で紹介した範囲でも、
- Gmailでのps1ファイル送信を禁止することで、そもそも悪意あるスクリプトの流布を防ぐ
- 実行ポリシーによってよくわからないまま実行することを防ぐ
- ダブルクリックで実行できないようにすることで、1クッション置かせる
- 特に拡張子表示設定をオフにしてると、
資料.docx.ps1
の表示が資料.docx
になるのでスクリプトファイルと知らずに引っかかってダブルクリックしてしまう人が多そうです
- 特に拡張子表示設定をオフにしてると、
といったように複数の対策が取られていますよね。
実行ポリシーによってどれだけ自分のPCが守られるかは本人のセキュリティ意識や使い方などによりますが、少なくともこの記事を見に来た人の大多数が、ps1を意識的にか無意識的に実行しようとして実行ポリシーの警告・エラーを受けて来ているんだと思います。
すべての脅威から完全に守ることはできませんが、一部の脅威をブロックすることができ、そして実行ポリシーが高いほどブロックできる割合も高くなります。
改めて、どうしたらいい?
※個人のPCであるという前提の上で
一回のみの実行なら、
powershell -ExecutionPolicy RemoteSigned .\test.ps1
1スコープのみのスクリプト利用であれば、
Set-ExecutionPolicy RemoteSigned Process
# 現在のスコープでのみ(今開いているpowershellを閉じるまで)実行が有効になる
頻繁にpowershellスクリプトを利用する場合は、
Set-ExecutionPolicy RemoteSigned CurrentUser
# 現在のユーザーで実行が有効になる
で良い場合が多いのではないかなと思います。
Pythonの公式ドキュメントでもRemoteSigned
が使われているように、
色々な点を考慮すると、個人PCであればRemoteSigned
が利便性とセキュリティのバランスの良いのではという判断です。
もちろん実行ポリシーを高く保つに越したことはありません。
ご自身の利用用途等に応じて適切な実行ポリシーを設定しましょう。
もう少し実行ポリシーが高いAllSigned
を保ちたい場合はこちら記事が参考になりますし、
ガチガチに固めたい場合はこちらの記事を参考にすると良いと思います。
適切な実行ポリシーを設定した上で、でもそれだけではpowershellリスクを完全に排除できないことを理解し、基本的なセキュリティ対策を取りましょう。
powershell関わらず下の項目はごくごく一般的なセキュリティ対策です。
- 信頼できないサイトからダウンロードしない
- 信頼できないメールのURLや添付ファイルを開かない
- 信頼できないファイルを実行しない
- ウイルス対策ソフトを導入する
- ソフトウェアを最新の状態に保つ
最後に
powershellの実行ポリシーについて、調べたりしたことをまとめました。
「とりあえずSet-ExecutionPolicy RemoteSigned
やSet-ExecutionPolicy RemoteSigned CurrentUser
にしとけば良い」みたいな記事はたくさんあるけど、実際にセキュリティリスク的にどうなのかなどについて書いてある記事がなかなかなかったので本記事を書きましたが、もし誰かの参考になれば幸いです。
また、私自身全然セキュリティの職というわけでもなければセキュリティ関連を専攻しているわけでもないので、もし間違った記述やよろしくない記述がありましたら、コメントで教えていただけると助かります。