WebサイトやWebアプリのセキュリティの要である「SSL/TLS」は、SSL 3.0以前のレガシーなプロトコルの脆弱(ぜいじゃく)性が問題視され、より新しいプロトコルに移行することが求められてきました。SSLの後継であるTLS 1.0/1.1も脆弱性があることが明らかになり、最近ではTLS 1.2以降を要求するWebサイトやサービスも増えてきています(例:2019年7月下旬のTwitterサービスなど)。今回は、TLS 1.2以降への移行の影響で失敗するようになった「Invoke-WebRequest」コマンドレットの回避策について。
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
筆者は「Windows Sysinternals」のユーティリティーの更新版を素早く手に入れられるように、自作のWindows PowerShellスクリプト「updatesysinternalssuite.ps1」を作成し、利用しています。作成したスクリプトは、「TechNetスクリプトセンター」で公開しています。
このスクリプトはWindows PowerShell 5.0以降で動作します。「Invoke-WebRequest」コマンドレットは、Windows PowerShell 3.0以降で利用できますが、zipファイルの展開に利用している「Expand-Archive」コマンドレットはWindows PowerShell 5.0以降から利用できるようになったものだからです。
現在、公開されているスクリプトは、本稿で説明する問題への対応を含む修正版になります。修正前のスクリプトは、2018年10月前半までは問題なく機能していました。それが2018年10月後半、突然、「Invoke-WebRequest:接続が切断されました:受信時に予期しないエラーが発生しました。」というエラーが表示されるようになりました(画面1)。
調査してみると、Invoke-WebRequestコマンドレットによるファイルのダウンロード元「https://live.sysinternals.com/」サイトが、TLS 1.2を要求するようになったことが分かりました。しばらく前から常時SSLサイトになったため、HTTP接続はできません。TLS 1.0以前やTLS 1.3(Windows 10 バージョン1903から追加)ではHTTPS接続できず、TLS 1.2のHTTPS接続のみを受け付けるようにサイト側が変更されたのです。
ちなみに、当時使用していたWindowsのバージョンはWindows 10 バージョン1803でした。そして、Windows 10 バージョン1809以降のInvoke-WebRequestは、エラーなしで問題なく動作します。
Windowsは、「Windows 7」と「Windows Server 2008 R2」でTLS 1.1/1.2に標準対応しました。ただし、TLS 1.1/1.2を利用するには、追加の設定が必要になる場合があります。必要な設定については以下の公式ブログのアーカイブにまとめられていますが、Windowsのバージョン、.NET Frameworkのバージョン、使用するアプリの組み合わせによって、TLS 1.2に対応させる方法はさまざまです。
Windows PowerShellのInvoke-WebRequest(Windows PowerShell 3.0以降で利用可能)は、.NET Framework上で動作するアプリケーションといえます。
今回は、Windows 10 バージョン1803以前のInvoke-WebRequest(およびInvoke-RestMethod)の、使用されるセキュリティプロトコルによる接続エラーの解消方法に焦点を当てて、サポート対象のWindowsの全バージョンについてまとめました。なお、対象のWindowsでサポートされる.NET Framework 4.5.2以降がインストールされ、最新の更新プログラムが適用済みであることを前提とします。
Invoke-WebRequestは、.NET Frameworkの「Net.ServicePointManager」の「SecurityProtocol」プロパティに設定されているプロトコルバージョンを使用して、HTTPS接続を行おうとします。Windows PowerShellで以下のコマンドラインを実行すると、システムのSecurityProtocolプロパティの設定を参照することができます(「PS:¥>」はプロンプトであり入力する必要なし)。また、「[enum]::GetNames([Net.SecurityProtocolType])」を実行すると、システムで利用可能なプロトコルバージョンのリストを確認できます。
PS:¥> [Net.ServicePointManager]::SecurityProtocol PS:¥> [enum]::GetNames([Net.SecurityProtocolType])
Windows 10 バージョン1803以前の場合、1行目のコマンドラインはシステムの既定値を変更していない限り、「Ssl3, Tls」を返します。つまり、Windows 10 バージョン1803以前のInvoke-WebRequestは、SSL 3.0またはTLS 1.0を使用してHTTPS接続しようとします。そのため、TLS 1.1以降のサイトに接続しようとすると、エラーで失敗します。
Windows 10 バージョン1809以降では、次の値を返します。Windows 10 バージョン1809以降のInvoke-WebRequestでTLS 1.2のみのサイトへの接続がエラーにならないのは、既定の設定がより安全なプロトコルを使用するように変更されたからです。
Windows Sysinternalsのサイトから接続エラーを回避して「Process Explorer」(Procexp.exe)をダウンロードするには、以下のようにTLS 1.2の使用を明示的に指定してから実行します(画面2)。
PS:¥> [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 PS:¥> Invoke-WebRequest -uri https://live.sysinternals.com/procexp.exe -outfile .¥procexp.exe
この方法は公式ブログのまとめには直接書いていませんが、アプリ側で“ServicePointManager.SecurityProtocol プロパティに明示的に指定”する方法になります。現在(修正版)の「updatesysinternalssuite.ps1」には、1行目にこのコマンドラインを追記してあります。
TLS 1.0、TLS 1.1またはTLS 1.2から、より最適なプロトコルを利用させたい場合は、以下のように記述します。
PS:¥> [Net.ServicePointManager]::SecurityProtocol = @([Net.SecurityProtocolType]::Tls,[Net.SecurityProtocolType]::Tls11,[Net.SecurityProtocolType]::Tls12)
この方法は、TLS 1.1/1.2に標準で対応しているWindows 7とWindows Server 2008 R2以降の全てに共通で使える方法です。後述しますが、Windows Server 2008についても、TLS 1.1/1.2をサポートする更新プログラムがインストール済みであれば使える方法です。
Windows 10 バージョン1803以前で接続エラーを回避するもう一つの方法は、システムの既定のSSL 3.0/TLS 1.0(Ssl3, Tls)から、Windows 10 バージョン1809と同じTLS 1.0以降(Tls, Tls 1.1, Tls 1.2)に変更する方法です。
Copyright © ITmedia, Inc. All Rights Reserved.