Open Automation Software 社は最近、同社の OAS エンジンに存在する複数の脆弱性に対処するパッチをリリースしました。
Cisco Talos は、Open Automation Software 社と協力して、ユーザーがこれらのパッチを使用できるようにした上で問題を公表しました。バージョン 19 で修正プログラムがリリースされたので、このタイミングでこれらの脆弱性のいくつかを詳しく掘り下げていこうと思います。影響度が低いと見られる一握りのバグが、さまざまな悪意のあるアクションを実行するためにどのように連続してエクスプロイトされ、基盤となるシステムにアクセスするまでに至る可能性があるのかについて説明します。
バックグラウンド
OAS Platform はさまざまな専用デバイスとアプリケーション間のデータ転送を簡素化します。複数のベンダー製品の接続や、製品とカスタムアプリケーションの接続など、さまざまな接続を可能にします。デフォルトでは、プラットフォームは TCP/58727 で構成することができます。
脆弱性
この調査では、8 件の脆弱性を発見しました。そのうちの 5 件についてはこちらで取り上げています。技術的な詳細については、以下の各脆弱性のレポートをご覧ください。
TALOS-2023-1769 | TALOS-2023-1770 | TALOS-2023-1771 | TALOS-2023-1772 |
TALOS-2023-1773 | TALOS-2023-1774 | TALOS-2023-1775 | TALOS-2023-1776 |
デフォルトの構成を使用した認証バイパス
TALOS-2023-1769(CVE-2023-31242)
OAS エンジンをインストールする際、デフォルトでは、アプリケーションの管理者ユーザーは設定されません。管理者ユーザーがいないと、新規ユーザー作成など、本来は有効なログイン情報を必要とするような特定の機能へのアクセスにも、認証が必要なくなります。また、管理者ユーザーを作成しても、OAS エンジンの再起動の前に構成を保存しないと、変更は失われてシステムがデフォルトの状態に戻るため、認証情報は無視されます。
盗まれた U_EP を使用した認証バイパス
TALOS-2023-1770(CVE-2023-34998)
特権リクエストが正規の管理者から OAS エンジンに送信されると、トラフィックは暗号化されずに回線上に送信されます。そのため、クライアントと OAS エンジン間のトラフィックを傍受できる攻撃者なら、有効な U_EP の認証情報を入手できます。そうすると、攻撃者がその認証情報を使用し、細工して正常に処理される特権リクエストを作成できるようになります。取得された U_EP は、関連するユーザーアカウントが削除されるまで有効なまま残ります。
ファイルの上書き
TALOS-2023-1771(CVE-2023-32615)
OAS の構成ツールには、実行中の構成を OAS エンジンのサーバーのディスクに保存する機能があります。この情報が保存される時、ユーザーはパスとファイル名を指定しますが、その際には、基盤となる OAS のユーザーアカウント権限の制約しか適用されません。指定したファイルがすでに存在する場合、ファイルの内容が構成のデータに置き換えられます。
適切な入力チェックのないユーザー追加
TALOS-2023-1772(CVE-2023-34317)
OAS エンジンの機能および関連データへのアクセスは、OAS エンジンのアプリケーションユーザーを使用して制御されます。
アプリケーションの管理者ユーザーは、さまざまな権限レベルのユーザーをアプリケーションに追加できます。これらのユーザーは、基盤となるシステム上ではなく、OAS エンジン内だけに存在します。ユーザーを追加する時に、入力されるユーザー名の値にはフィルタ処理が行われないため、 ユーザー名としてはふさわしくない多種多様な文字を入力して実行中の構成に保存することが可能です。
ディレクトリの表示
TALOS-2023-1774(CVE-2023-32271)
保存された構成をディスクからロードする機能や実行中の構成をディスクに保存する機能は、OAS の構成ツールを通じて、認証済みのアプリケーションユーザーに開示されます。
ユーザーは、構成管理ツールに付随するリモートファイルブラウザで、リモートシステム上に存在するファイルを確認することができます。
攻撃の解説
これらの脆弱性を組み合わせることで、OAS エンジンを実行しているユーザーとして、基盤となるシステムにアクセスすることが可能になります。
このシナリオでは、攻撃者は次のことができます。
- 有効な認証情報にアクセスする。
- SSH サーバーの証拠をファイルシステムから探す。
- 実行中の OAS の構成に SSH キーを保存する。
- 実行中の構成をディスクに書き込む。
OAS エンジンとの通信
攻撃者は、システムのエクスプロイトに必要なリクエストを行う前に、OAS の構成ユーティリティで使用されているプロトコルを把握する必要があります。リクエストは、Client_Send と OASPacket の 2 つの関連する Protobuf の構造体から成り、それが連結されて、デフォルトでは TCP/58727 経由で OAS エンジンに送信されます。リクエストに対するレスポンスは、Client_Send Protobuf を Server_Send に置き換えて、同様のフォーマットで配信されます。
Server_Send Protobuf は以下の形式をとります。後続の Client_Send を送信する場合は、Handshake フィールドと Offset フィールドを保持する必要があります。
message Server_Send { int32 Version = 1; int32 OASVersion = 2; int32 Handshake = 3; int32 Offset = 4; int32 Length = 5; }
Client_Send Protobuf は以下の形式をとります。Version は 0x01、Length は OASPacket Protobuf のバイトでのサイズです。
message Client_Send { int32 Version = 1; int32 ClientHandshake = 2; int32 Handshake = 3; int32 Length = 4; }
ClientHandshake フィールドと Handshake フィールドは、リプレイ攻撃を防ぐために設けられたと思われるクライアントサーバー間のハンドシェイクで使用されます。ClientHandshake は、ランダムに生成される 0x3FFFEC75 以下の値で、後続のリクエストのハンドシェイク処理で使用されます。Handshake は、以前の Server_Send のレスポンスから Handshake フィールドを取り出し、同じレスポンスの Offset フィールドを加え、0x12CB および以前の Client_Send リクエストの ClientHandshake フィールドの値を引き、最後に 0x888 を加えて計算される値です。わかりやすく式で表すと以下のとおりです。
handshake = server_send_handshake + server_send_offset - 0x12CB - previous_client_send_handshake + 0x888
OASPacket Protobuf は以下の形式をとります。LDCMode、LDCHost、SendingGUID は必ずしも必要ではありません。Version は 0x01、CommandNumber は送信されるリクエストの種類を定義し、DataAsBytes はリクエストデータを記述する一連のシリアル化された Protobuf です。
message OASPacket { int32 Version = 1; int32 LDCMode = 2; int32 CommandNumber = 3; string LDCHost = 4; string SendingGUID = 5; bytes DataAsBytes = 6; }
多くのリクエストは、カスタムタイプの U_EP のフィールドを含みます。このフィールドは、特権リクエストの認証に使用される、シリアル化されたログイン情報のコピーを含みます。U_EP Protobuf は以下の形式をとります。Version は 0x01、Seed はログイン情報を暗号化するために使用されるランダムな値です。
message U_EP { int32 Version = 1; int32 Seed = 2; bytes DataAsBytes = 3; }
DataAsBytes フィールドは、以下の形式のシリアル化され暗号化された User_EncryptedPassword Protobuf を含みます。
message User_EncryptedPassword { string Username = 1; string EncyprtedPassword = 2; }
攻撃者は、ここで述べた一般的な構造と後述するリクエスト固有の構造を組み合わせることにより、OAS エンジンとの通信を狙いどおりに複製できます。
認証のバイパス
OAS エンジンと正常に通信するために必要なリクエストの多くは認証を必要とします。現時点でこの認証要件をバイパスするには、デフォルトの構成を悪用する方法と、有効な認証情報を再利用する方法の 2 つのオプションがあります。
オプション 1:デフォルトの構成の悪用
アクセスに必要なリクエストには認証が必要なので、まず有効な U_EP の認証情報を取得する必要があります。
有効なログイン情報を取得する最も簡単な方法は、TALOS-2023-1769 で公開された脆弱性を使用することです。この脆弱性は、OAS エンジンがデフォルトの構成のままで動作している場合にのみエクスプロイト可能です。問題の標的に脆弱性があるかどうかは、Version を 0x01 に設定し、CommandNumber を 0x13F に設定した OASPacket が使用して判断できます。正常に送信されると、サーバーは以下のフォーマットでレスポンスを返します。
message Version_Runtime_License { int32 Version = 1; bool Runtime = 2; string LicenseString = 3; string MtcExpirationString = 4; bool NetCore = 5; bool WinOS = 6; bool LinuxOS = 7; string AssemblyVersion = 8; string BaseDirectory = 9; bool EnableActiveDirectory = 10; string ActiveDirectoryEntry = 11; string ActiveDirectoryFilter = 12; }
サーバーに TALOS-2023-1769 に関する脆弱性がある場合は、MtcExpirationString フィールドに「Create an Admin User」という文字列が含まれます。この状態では、サーバーが U_EP の認証情報を一切検証しないので、U_EP フィールドに何らかの値が入っている限り、認証されていないユーザーによる特権リクエストも許可されます。
管理者ユーザーがすでに作成されている場合、OAS エンジンは TALOS-2023-1769 に関する脆弱性がないので、別のアプローチが必要になります。その場合は、TALOS-2023-1770 で公開された脆弱性が、有効な U_EP を取得する代替手段になります。
オプション 2:U_EP の利用
この脆弱性は、特権リクエストなどの正当な構成のリクエストが OAS エンジンに送信された場合に発生します。これらのメッセージのほとんどは、TALOS-2023-1770 で公開されたように、クリアテキストで送信されます。例外は、OAS Platform 内の User_EncryptedPassword という、U_EP の認証情報内のフィールドです。User_EncryptedPassword は、認証するユーザー名と関連する暗号化されたパスワードを含むデータブロックであり、以下に示すように、U_EP の認証情報の DataAsBytes フィールドに AES で暗号化されシリアル化されたデータのブロックとして提供されます。
message U_EP { int32 Version = 1; int32 Seed = 2; bytes DataAsBytes = 3; } message User_EncryptedPassword { string Username = 1; string EncyprtedPassword = 2; }
User_EncryptedPassword を復号し、生のユーザー名と暗号化されたパスワードにアクセスすることも可能ですが(TALOS-2023-1776 )、そのようなことをしなくても認証はできます。
正当な U_EP が構築されると、値がランダムに生成され、このデータブロックの Seed フィールドに保存されます。この Seed はその後、User_EncryptedPassword データの暗号化に用いられる AES キーの構築に使用されます。このプロセスが正式なツールによって実行されると、通常は新しい構成セッションごとに U_EP の値が変わりますが、それで前のセッションが終了することはありません。
攻撃者がネットワークトラフィックの傍受や古いトラフィックキャプチャの取得などの方法を使って正当な構成のトラフィックにアクセスすると、U_EP のデータブロックを抽出できます。そうすれば、関連するユーザーが OAS エンジン内に存在する限り、認証を成功させることができます。
ファイルシステムの探索
認証されたメッセージの送信に成功すると、TALOS-2023-1774 で公開された脆弱性を利用して、ファイルシステムを探索することができます。
ここからさまざまなアプローチが考えられますが、今回の詳細調査では、/etc/ssh/ に sshd_config ファイルが存在し、OAS ユーザーのホームディレクトリに .ssh ディレクトリが存在することを確認していきます。存在した場合、システム上で SSH サーバーが有効になっている可能性が高いことが示唆されます。
このためには、Version を 0x01 に設定し、CommandNumber を 0x0F に設定した OASPacket を使用します。それに加えて、DataAsBytes フィールドに、有効な U_EP を含むシリアル化された Browse_File Protobuf、設定された GetDirectories と GetFiles のフラグ、目的の場所の絶対パスに設定された DirectoryPath、および任意のファイルタイプを示すアスタリスクを含む FileExtension フィールドを入力されている必要があります。
message Browse_File { int32 Version = 1; U_EP UEP = 2; bool GetDrives = 3; bool GetDirectories = 4; bool GetFiles = 5; string DirectoryPath = 6; string FileExtension = 7; }
送信に成功すると、OAS エンジンはタイプ別に整理されたすべてのデータを含む結果を Browse_File_Result Protobuf に入れて返信します。
message Browse_File_Result { bool Success = 1; optional string ErrorString = 2; repeated string Drives = 3; repeated string Directories = 4; repeated string ShortDirectories = 5; repeated string Files = 6; repeated string ShortFileNames = 7; }
新しい SSH キーのアップロード
SSH サーバーが稼働していることをある程度確実に確認できたら、TALOS-2023-1771 と TALOS-2023-1772 を利用して新しい SSH キーをアップロードし、続いて基盤となるシステムにアクセスすることができます。
OAS エンジンが提供する専用のファイルアップロード機能は存在しないため、より工夫を凝らす必要があります。TALOS-2023-1772 で公開された不適切な入力検証の脆弱性と、TALOS-2023-1771 で公開されたファイル名の外部制御の脆弱性を組み合わせることで、代用のファイル アップロード プロセスを作成することが可能です。
💡この手法は、このシナリオでは機能しますが、ファイルのできあがりを完全に制御することはできないということに注意する必要があります。そのため、ほとんどのアプリケーションで破損ファイルとみなされる可能性があります。
OAS エンジンに新しいアプリケーションユーザーを追加すると、実行中の OAS エンジンの構成にユーザーの詳細が取得されて書き込まれます。このプロセスでは、入力された値がユーザー名として妥当な文字だけを含んでいるかどうかの検証は行われません。さらに、ユーザー名の長さに制限がありません。
制御する SSH 公開鍵全体を新しいエントリのユーザー名として提供することにより、この検証の欠如を悪用し、実行中の OAS の構成に保存されている目的のファイルデータを取得することができます。
このためには、Version を 0x01 に設定し、CommandNumber を 0x88 に設定した OASPacket を使用します。さらに、DataAsBytes フィールドに、Version 番号、有効な U_EP、および公開鍵データの入った String 値を含む、シリアル化された String Protobuf を入力されている必要があります。
message String { int32 Version = 1; U_EP UEP = 2; string String = 3; }
実行中の構成にキーが保存されていれば、それをトリガーにして、構成をディスクに保存することで、任意のファイル(この場合は OAS ユーザーの authorized_keys ファイル)に書き出すことができます。ファイルには SSH サーバーには無意味な大量の OAS の構成情報が含まれていますが、ユーザー名として提供された公開鍵は、改行文字で囲まれている限り、正常に解釈されます。
このためには、Version を 0x01 に設定し、CommandNumber を 0x74 に設定した OASPacket を使用します。また、DataAsBytes フィールドには、Version 番号、有効な U_EP、そして今回は構成が書き込まれるべきファイルへの絶対パスを含む String 値をシリアル化した String Protobuf で再び満たす必要があります。
message String { int32 Version = 1; U_EP UEP = 2; string String = 3; }
すべてが意図したとおりに動作し、標的で SSH サーバーが稼働していれば、SSH 経由で OAS エンジンを実行している基盤である OS のユーザーとしてログインできます。
緩和策
Cisco Talos は、この解説記事および関連する脆弱性を公表する前に、Open Automation Software 社と協力し、パッチがバージョン 19 で公開されたことを確認しています。すべてのユーザーに、最新バージョンへのアップグレードを推奨します。
これらの脆弱性のエクスプロイトを検出できる Snort カバレッジ (SID 61991 ~ 61994、62003、62004)については、Snort.org から最新のルールセットをダウンロードしてください。Talos Intelligence の Web サイトにも、Talos による最新の脆弱性アドバイザリ を常時掲載しています。
本稿は 2024 年 01 月 31 日に Talos Group のブログに投稿された「OAS Engine Deep Dive: Abusing low-impact vulnerabilities to escalate privileges」の抄訳です。