この記事の目的
Powershellから"/"(スラッシュ)を含むパスのレジストリキーを作成する方法を記載します。
なぜ必要だったのか?
Triple DESやSSLv2といった暗号方式、プロトコルは脆弱性があるため現在は無効化することが推奨されています。
複数のWindows Serverに対してレジストリエディタを使用してこれらを無効化するのは面倒かつ危険と考え、Powershellで定型的に実行することを考えました。
Powershellでレジストリを変更することはそれほど難しくはありませんが、ある暗号方式のレジストリだけ正しく変更できませんでした。
どのようにやろうとしたのか?
以下の暗号方式、プロトコルの無効化を検討しました。
- Triple DES
- SSLv2
- SSLv3
- RC4
上記に対応するレジストリキーはデフォルトでは存在しません。
よって、レジストリキーを作成してから無効化する必要があります。
以下のようなコマンドでレジストリキーを作成しようとしました。1
New-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\Triple DES 168"
New-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Server"
New-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 3.0\Server"
New-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\RC4 128/128"
New-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\RC4 40/128"
New-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\RC4 56/128"
Triple DES、SSLv2、SSLv3は正しく作成できましたが、RC4はエラーが発生しました。
New-Item : 指定したパスにレジストリ キーが存在しません。
発生場所 行:1 文字:1
+ New-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNE ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (HKEY_LOCAL_MACH...Ciphers\RC4 128:String) [New-Item]、ArgumentException
+ FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.NewItemCommand
何が問題だったのか?
RC4のレジストリキーの他レジストリキーとの違いはパスに"/"が存在することです。
Powershellは階層のセパレータとして""(バックスラッシュ)と"/"(スラッシュ)両方をサポートします。
ここでは"RC4 128/128"という階層のキーを作成したいのですが、Powershellは
New-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\RC4 128/128"
というコマンドが
HKLM: -> SYSTEM -> ...省略... -> Ciphers -> RC4 128/128
というパスにしたいのか
HKLM: -> SYSTEM -> ...省略... -> Ciphers -> RC4 128 -> 128
というパスにしたいのか判断ができません。
このような場合、Powershellでは前者のパスが存在する場合はそちらを使用し、存在しない場合は後者のパスを使用しようとします。
今回はレジストリキーを作成するところからですので、前者のパスは存在しません。
よって後者のパスを使用しようとしますが、存在しない"RC4 128"というキーの中に"128"というキーを作成しようとしているので前述のエラーになります。
これは"/"をエスケープしても意味がありません。
どうしたのか?
結論としては以下のコマンドで正しく作成できました。
$key = (Get-Item HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\).OpenSubKey('Ciphers', $true).CreateSubKey('RC4 128/128')
コマンドレットでは無理だったので、.NETのメソッドを用い、"Ciphers"をOpenSubKeyで開いて、さらに"RC4 128/128"をCreateSubKeyで作成します。
当然、"Ciphers"までが存在することが前提です。
より汎用性を持たせるのであれば一つずつキーが存在することを確認し、存在しないキーを作っていく処理にする必要があります。
今回はRC4のレジストリキーがこのような形だったため難儀しましたが、もし自分でレジストリキーを作成する場合は"/"を含まないキー名にした方が思わぬ問題を生まずに済むと思われます。
参考
上記問題に直面した際にMicrosoftフォーラムで質問し、その際にいただいた回答をもとに上記対応方法をまとめました。
https://social.msdn.microsoft.com/Forums/ja-JP/5fa54921-242d-4435-9c3d-a3a9ae11f4c2/powershell?forum=powershellja
回答いただいた方々に感謝いたします。
-
実際にはレジストリキーが存在する場合、しない場合の条件分岐等がありますが簡略化して書いています。 ↩