This post is also available in: English (英語)

概要

近年、攻撃者がリモートデスクトッププロトコル(RDP)を悪用してセキュリティの甘いサーバーやエンタープライズネットワークにアクセスするケースが増えています。また2017年以降RDPはランサムウェアを使用するマルウェア攻撃の重要な攻撃ベクトルにもなっています。セキュリティ専門家もRDPの脆弱性を検出して攻撃を防ぐためのシグネチャを作成しており、このプロトコルには多くの注目が向けられています。

RDPはMicrosoftによるプロプラエタリなプロトコルで、ネットワークトラフィックを暗号化するための動作モードをいくつかサポートしています。残念ながら、暗号化されてRDPコンテンツが非表示になるとRDP用シグネチャの作成はむずかしくなりますが、復号用の秘密鍵ファイルを用意したテスト環境があればWiresharkのRDPトラフィックを含むパケットキャプチャ(pcap)を復号できるようになります。

そこで本稿では、テスト環境を用意して復号用秘密鍵でRDPトラフィックを復号する方法について解説します。

前提条件

本講座は以下の条件を満たした場合にもっとも高い学習効果を期待できます。

  • VirtualBoxやVMwareなど2台のWindowsホストを実行できる仮想環境があること
  • RDPをセットアップして使用する方法を理解していること
  • RDPクライアントがあること(本稿ではWindows 10 Professionalを実行するホストを使用)
  • RDPサーバーがあること(RDPを有効にした別のWindowsホストかFreeRDPを実行するWindows以外のホストを用意する)
  • これら2台のホスト間のネットワークトラフィックがキャプチャ可能であること(仮想環境内でやるのがもっとも容易)
  • Wiresharkバージョン3.0またはそれ以降があること
  • ネットワークトラフィックの基礎知識があること

全体的な手順

全体的な手順はおおまかに次の7つに分けられます。

  • 手順1: 2台のホストがある仮想環境をセットアップします。1台はRDPクライアントとして、もう1台はRDPサーバーとして機能させます。
  • 手順2: RDPクライアントからForward Secrecy暗号を削除します。
  • 手順3: RDPサーバーの秘密鍵を取得します。
  • 手順4: RDPサーバーとWindowsクライアント間のRDPトラフィックをキャプチャします。
  • 手順5: Wiresharkでpcapを開きます。
  • 手順6: Wiresharkに秘密鍵を読み込みます。
  • 手順7: RDPデータを調べます。

手順1: 仮想環境をセットアップする

この種の分析で最も一般的に使われる仮想環境はVirtualBoxとWindows/Linux用VMware Workstationの2つでしょう。Mac OSではVMWare Fusionも使われています。VirtualBoxは無料ですが、VMwareは商用製品です。

本講座では仮想環境上で仮想マシン(VM)をセットアップする部分についてはふれません。本稿で利用したラボ環境の基本構造は図1の通りです。

RDPトラフィックの復号に関する本講座で使用されるラボのセットアップには、仮想化環境を実行する物理ホスト、仮想LAN、RDPクライアントとして機能するWindows VM、およびRDPサーバーとして機能するWindows VMが含まれます。
図1 本講座で使用したラボ環境の基本構造

今回のラボ環境には2つのWindows10ホストが含まれています。1台はRDPクライアントとして、もう1台はRDPサーバーとして機能するものです。仮想LAN上でこれら2台のホストの間にRDPセッションを張り、そのネットワークトラフィックをキャプチャしていきます。

手順2: RDPクライアントからForward Secrecy暗号を削除する

暗号化アルゴリズムのなかにはForward Secrecy(「前方秘匿性」とも呼ばれる。以下、「FS」と表記)を提供するものがあります。これらの種類の暗号化アルゴリズムは、SSL/TLS接続用にセッション鍵を複数作成します。こうした暗号アルゴリズムを利用されてしまうと、RDPサーバーから1つ秘密鍵をもらっただけではSSL/TLSトラフィックを復号できません。そこで、RDPクライアントでFSをサポートする構成オプションを削除しておく必要があります。

本講座用で私たちが用意したRDPクライアントはWindows 10 Professionalを実行するホストです。このホストには組み込みのRDPクライアントがあります。

MicrosoftはFSをサポートする構成オプションの削除方法の詳細を『トランスポート層セキュリティ (TLS) を管理する』、『Prioritizing Schannel Cipher Suites(Schannel暗号スイートの優先順位付け)』という2つの記事で公開しています。以下は私たちが実際に行った内容を1ステップずつ説明したものです。

Windowsの検索ボックスに「gpedit.msc」と記入し、グループポリシー管理コンソールを検索します。「gpedit.msc」が [最も一致する検索結果] に表示されるので、この項目を右クリックしてコンテキストメニューから [管理者として実行] をクリックします(図2参照)。

Windowsの検索ボックスに「gpedit.msc」と入力してグループポリシー管理コンソールを検索し、「gpedit.msc」が [最も一致する検索結果] に表示されたら、この項目を右クリックして、コンテキストメニューから [管理者として実行] をクリックします。
図2 Windows 10 Professionalで管理者としてグループポリシーエディターを起動する

コンソールの左ペインを次の順にクリックして展開します(カッコ内は日本語のUI表記)。

  • Computer Configuration (コンピューターの構成)
  • Administrative Templates(管理用テンプレート)
  • Network(ネットワーク)
  • SSL Configuration Settings(SSL 構成設定)

図3は、[SSL Configuration Settings(SSL構成設定)] まで展開したところを示しています。

スクリーンショット内の大きい黒矢印は、ファイルシステム内の [SSL構成設定] の場所を示しています。
図3 [SSL Configuration Settings(SSL構成設定)] まで展開したところ
[SSL Configuration Settings(SSL構成設定)] の下にある [SSL Cipher Suite Order(SSL 暗号の順位)] という項目をダブルクリックします(図4参照)。

図4 [SSL暗号の順位] まで展開したところ
図4 [SSL Cipher Suite Order(SSL 暗号の順位)] まで展開したところ
[SSL Cipher Suite Order(SSL 暗号の順位)] 以下の [Enabled(有効)] オプションをクリックします(図5参照)。

大きい黒矢印は [SSL暗号の順位] を有効化するためにクリックする場所を示しています。スクリーンショットの中の説明「このポリシー設定は、Secure Socket Layer(SSL)で使用する暗号を決定します。このポリシー設定を有効にした場合、指定されている順位で SSL 暗号が優先されます。」
図5 [SSL Cipher Suite Order(SSL 暗号の順位)] を有効にしたところ

次に暗号リストの上にカーソルを置いて右クリックし、コンテキストメニューから [Select All(すべて選択)] を選んでリスト全体を選択します(図6参照)。

このスクリーンショットで示すとおり、次の手順で暗号リスト全体を選択している。
図6 暗号リストを選択

リスト全体を選択した後、右クリックしてコンテキストメニューから [Copy(コピー)] を選択し、リストをコピーします(図7参照)。

図のように暗号のリストをコピーします。
図7 暗号リストをコピーしているところ

コピーした暗号リストを任意のテキストエディタ(メモ帳など)にペーストします。「Diffie-Hellman Ephemeral(ECDHE)」ないし「Digital Signature Algorithm(ECDSA)」暗号を使う、楕円曲線暗号をサポートしている暗号アルゴリズムをすべて削除します。つまり名前に「ECDHE」と「ECDSA」のいずれかまたは両方を含むエントリを、すべて削除する必要があります。以下の図8の例からわかるとおり、これらの暗号アルゴリズムはすべて連なって配置されているのでテキスト内で簡単に削除できます。

名前に「ECDHE」または「ECDSA」のいずれかまたは両方を含む項目を削除して楕円曲線暗号をサポートする暗号アルゴリズムを削除します。この図からわかるように、これらの暗号アルゴリズムはすべて連番で配置されているのでテキスト内で簡単に削除できます。
図8 「ECDHE」と「ECDSA」のいずれかまたは両方を含むエントリを削除する

図8で更新した暗号のリストは以下の通りです(訳注: 日本語環境で行う場合、暗号アルゴリズムの区切りにはカンマのかわりに読点(、)が使用されます)。

TLS_AES_256_GCM_SHA384,TLS_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_3DES_EDE_CBC_SHA,TLS_RSA_WITH_NULL_SHA256,TLS_RSA_WITH_NULL_SHA,TLS_PSK_WITH_AES_256_GCM_SHA384,TLS_PSK_WITH_AES_128_GCM_SHA256,TLS_PSK_WITH_AES_256_CBC_SHA384,TLS_PSK_WITH_AES_128_CBC_SHA256,TLS_PSK_WITH_NULL_SHA384,TLS_PSK_WITH_NULL_SHA256

表1 FS暗号アルゴリズムを削除して更新されたリスト

テキストエディタで変更後のテキストをすべて選択してからコピーします。その後、グループポリシー管理コンソールに戻り、コピー元の全テキストが選択された状態であることを確認してから、更新した暗号リストをSSL暗号スイートフィールドに貼り付けて元のリストを上書きします。[Apply(適用)] ボタンをクリックし、続けて [OK] をクリックしてウィンドウを閉じます。これでリストが更新されたので、グループポリシーエディターを閉じます。

この手順を実行したら、次はRDPサーバーの秘密鍵を取得する必要があります。

手順3: RDPサーバーの秘密鍵を取得する

FreeRDPはRDPサーバーとして使える選択肢の1つです。FreeRDPはこのGitHubリポジトリで入手できます。ビルド手順はこちらから入手できます。サーバーをビルドするときは必ずWITH_SERVER = ONフラグを設定してください。サーバーをビルドしたら、サーバーに秘密鍵を与えるかFreeRDPに付属している秘密鍵を使用する必要があります。

本講座では、Windows 10 Professionalを実行するもう1台のホストをRDPサーバーとして使用しています。次に、ホストのオペレーティングシステムから秘密鍵を抽出します。

2台目のWindowsホストがRDPサーバーとして機能するよう、RDPを有効にします。Windows 10 Professionalを実行しているホスト上でRDPを有効にするには、[スタート] メニューからWindows の[Settings(設定)] に移動し、[System(システム)] アイコンを選択します(図9参照)。

この図のように、2台目のWindowsホストがRDPサーバーとして機能するようにシステムアイコンを選択してRDPを有効にする
図9 Windowsのシステム設定にアクセスしているところ

[System(システム)] を開いたら、[Remote Desktop(リモートデスクトップ)] を選択し、[Enable Remote Desktop(リモート デスクトップを有効にする)] スイッチをクリックします(図10参照)。

大きな黒矢印は、リモートデスクトップを選択する場所と、リモートデスクトップを有効にするスイッチをクリックする場所を示しています。
図10 Windows 10 ProfessionalでRDPを有効にしているところ

2台目のWindowsホストをRDPサーバーとして設定した後は、オペレーティングシステムから秘密鍵を抽出します。

サーバーの秘密鍵を抽出するには、JailbreakかMimikatzを使います。今回はJailbreakを使います。

Jailbreakは、iSECPartnersが作成した、サーバーのRDP証明書をエクスポートできるツールです。エクスポートされた証明書からは秘密鍵を抽出できます。

Jailbreakを使うためにさきほど立てたRDPサーバー上にこのGitHubリポジトリから以下のJailbreakバイナリをダウンロードしておきます。

  • EasyHook64.dll
  • jailbreak64.exe
  • jailbreakhook64.dll
  • jbstore2_64.exe

注: 上記のファイルは、2021年3月4日時点にダウンロードしたものをWindows 10 Professional 64ビットホスト上で使用しています。GitHubページのスクリーンショットを以下の図11に示します。

3月4日に撮影されたJailbreak GitHubページのスクリーンショット。ここでは、ダウンロードしたJailbreakバイナリを示しています。
図11 jailbreakバイナリのGitHubページ

Jailbreakのバイナリをダウンロードしたら、図12で示すように管理者権限でコマンドプロンプトを開きます。

大きな黒矢印は、管理者権限でコマンドプロンプトを開く方法を示しています。
図12 コマンドプロンプトを管理者として実行するところ

コマンドプロンプト上でダウンロードしたJailbreakバイナリのあるディレクトリに移動します。このディレクトリから次のコマンドを実行します。

32ビットバージョンのWindowsを実行している場合はかわりに次のコマンドを実行します。

RDPサーバーとして機能するWindowsホストで64ビット用コマンドを実行する例については、以下の図13を参照してください。

このスクリーンショットは、RDPサーバーとして機能するWindowsホストで64ビット用コマンドを実行する例を示しています。
図13 コマンドプロンプトからJailbreakを実行しているところ

このコマンドを実行すると、ローカルマシンの証明書マネージャーが開きます。左ペインから[Remote Desktop(リモートデスクトップ )]、[Certificates(証明書)]フォルダの順に展開します。この図では証明書が示されています。証明書が複数ある場合は有効期限が最も後の証明書を選択します。証明書を右クリックし、[All Tasks(すべてのタスク)] を選択してから [Export(エクスポート)] を実行します(図14参照)。

証明書を右クリックし、[すべてのタスク] を選択してから [エクスポート] を実行します。
図14 RDP証明書のエクスポート
証明書をエクスポートするときは忘れずに [Yes, export the private key(はい、秘密キーをエクスポートします)] オプションを選択しておきます(図15参照)。

スクリーンショットには次のように書かれています。「秘密キーのエクスポート: 秘密キーを証明書と一緒にエクスポートすることができます。秘密キーはパスワードで保護されています。秘密キーを証明書と一緒にエクスポートする場合は、パスワードを入力する必要があります。証明書と一緒に秘密キーをエクスポートしますか?」大きな黒矢印は、秘密鍵が証明書と一緒にエクスポートされるようにするために何を選択すべきかを示しています。
図15 証明書と一緒に忘れずに秘密鍵をエクスポートさせる

今回のホストの場合、証明書のエクスポート形式として選択できるのはPKCS #12 (.PFX) ファイル形式のみでした(図16参照)。

WiresharkでのRDPトラフィックの復号に関する本講座で使用されたホストの場合、ここに示されているように、証明書をPKCS#12(.PFX)ファイルとしてのみエクスポートできた
図16 今回の場合証明書は.pfxファイルとしてのみエクスポート可能

証明書にはパスワードが必要です(図17参照)。さいわいとくにパスワードの複雑性については要件がなかったので、1文字のパスワードを使用しました。

証明書にはパスワードが必要さいわいとくにパスワードの複雑性については要件がなかったので、1文字のパスワードを使用した
図17 エクスポートには証明書用のパスワードが必要

これでようやく証明書を秘密鍵と一緒にエクスポートできました(図18参照)。

図のように、秘密鍵を使用して証明書をエクスポートしました。
図18 証明書のエクスポートを完了したところ

Jailbreakを使わずにMimikatzでサーバー証明書を抽出することもできます。Mimikatzを使用してRDPサーバー証明書を取得する手順は、こちらのGitHubを参照してください。

今回は証明書をJailbreakで取得したので、Linuxホストにこの証明書を移してOpenSSLで秘密鍵を抽出します。まずは次のOpenSSLコマンドでPEM形式でキーを抽出します。

秘密鍵からパスフレーズを削除するため次のコマンドも実行します。

これでRDPサーバーの秘密鍵を得られました(図19参照)。

黒い矢印と「秘密鍵」というコールアウトでサーバーの証明書から秘密鍵を抽出した場所を示しています。
図19 証明書から抽出されたサーバーの秘密鍵

サーバーの秘密鍵を使用する前に、2台のWindowsホスト間でRDPセッションをキャプチャし、pcapとして保存する必要があります。

手順4: RDPトラフィックをキャプチャする

同じ仮想環境に2台のWindowsホストがある場合、dumpcaptcpdump、Wiresharkなどのツールを使って、プロミスキャスモードでVLAN内のネットワークトラフィックをキャプチャすることができます。キャプチャを開始したら、Windowsクライアント上からリモートデスクトップ接続アプリでRDPサーバーとして機能するもう1台のWindowsホストにログインします。ここでのRDPサーバーのホスト名はDESKTOP-USER1PCです。

この図ではWindowsクライアントがRDPによりRDPサーバーとして機能するもう1台のWindowsホストにログインしています。
図20 リモートデスクトップ接続アプリでRDPサーバーにログインする

pcapをキャプチャしながら、DESKTOP-USER1PCにログインし、ドキュメントを開いたり、Webをブラウジングするなどの一般的なタスクを実行します。

pcapをキャプチャしながら、DESKTOP-USER1PCにログインして、たとえばドキュメントを開く、Webをブラウジングするなどの基本的なタスクを実行します。
図21 リモートデスクトップ接続してからいくつか一般的なデスクトップタスクを実行する

1分ほどそうしてタスクを実行した後で、リモートデスクトップ接続アプリからログオフし、VLANでのネットワークトラフィックキャプチャを停止します。

手順5: Wiresharkでpcapを開く

WiresharkでRDPセッションのpcapを開きます。ですが、Wiresharkの表示フィルタで「rdp」をフィルタリングしても、RDPトラフィックが暗号化されているために何も表示されません。図22は、pcapでRDPをフィルタリングしたときに表示される空白のページを示しています。

RDPトラフィックは暗号化されているのでpcapでRDPをフィルタリングしても列が空白になる。
図22 RDPトラフィックは暗号化されているためRDP情報を求めてフィルタリングしても何も表示されない

ここでサーバーの秘密鍵を使ってWiresharkのRDPトラフィックを復号してやるとこれとはまったく違う結果になります。

手順6: Wiresharkに秘密鍵を読み込む

今回キャプチャしたpcapsの場合、RDPサーバーであるDESKTOP-USER1PCのIPアドレスは「10.3.4.138」で、RDPトラフィックは「3389/tcp」経由で発生しています。WiresharkでRDPトラフィックを適切に復号するにはこの情報が必要になります。

Windows/Linux の場合は [編集]、[設定] の順に開きます。Mac OS の場合は [Wireshark]、[Preferences] の順に開きます。図23に示すとおりに[Protocols]セクションを展開します。

WiresharkでRDPトラフィックを復号するには、IPアドレスとポート情報が必要In Wireshark, we used the Preferences window and expanded the Protocols section as shown.
図23 Wiresharkの [設定] から [Protocols] セクションに移動したところ
[Protocols] をスクロ―ルしていき、Wireshark 3.xの場合は「TLS」という項目を選択します(Wireshark 2.xでは「SSL」という項目を選択します)。 [RSA keys list] の横に [Edit] ボタンがあるので、この [Edit] ボタンをクリックした後、[+] ボタンをクリックして、使っているRDPサーバーのIPアドレス(例: 10.3.4.138)、RDPのポート(3389/tcp)、プロトコル(TPKT)、秘密鍵ファイルを保存した場所へのファイルパス(例: /home/xubuntu-user/Desktop/server.key)を順に指定します。ここでの例を図24に示します。

この [Edit] ボタンをクリックした後、[+] ボタンをクリックし、使っているRDPサーバーのIPアドレス(例: 10.3.4.138)、RDPのポート(3389/tcp)、プロトコル(TPKT)、秘密鍵ファイルを保存した場所へのファイルパス(例: /home/xubuntu-user/Desktop/server.key)を指定します。
図24 TLSセクションに移動し、秘密鍵をRSA keys listに追加する(Wireshark 2.x の場合は SSL セクションと読み替える)
WiresharkでRDPトラフィック復号用の秘密鍵を設定後、もう一度pcapを確認すれば、今度はずっとよい結果が得られます。

手順7: RDPデータを調べる

秘密鍵を読み込ませてからRDPをフィルタリングします。すると今度は列の表示が空白ではなくなり、図25に示すように複数の結果が得られます。

秘密鍵を読み込んだのでRDPトラフィックの復号が可能になっています。このスクリーンショットは、RDPをフィルタリングしても列表示が空白ではなくなったことを示しています。
図25 秘密鍵がWiresharkに読み込まれた後で同じパケットキャプチャのRDPアクティビティを表示したところ

セキュリティ専門家がRDPの脆弱性や攻撃の発見のためにシグネチャを書くさいは、図25で明らかになったような情報が業務上重要になります。

結論

本稿ではRDPセッションのトラフィック復号にあたってどのように環境を整えればよいかについて見ていきました。これにはWindows 10 Professionalを実行するホストを2台仮想LAN環境に用意するのがいちばん簡単でしょう。クライアント側でForward Secrecy暗号アルゴリズムを削除してから、RDPサーバーとして機能させるWindowsホストの側で秘密鍵を抽出し、ネットワークトラフィックのpcapをキャプチャし、セッション終了後にサーバーの秘密鍵を使ってRDPトラフィックを復号しました。

こうした環境があれば、セキュリティ専門家は、RDPの脆弱性や攻撃を検出するシグネチャを作成しやすくなるでしょう。

『Wiresharkによるパケット解析講座』シリーズの以前の講座は以下から確認してください。

Enlarged Image