循環するレース:潜在的な小さなバグ

夜にコンピューターで作業している若い女性。

潜在的な小さなバグ:CVE-2024-30089は、私が完全にアップデートされたWindows 11マシン(仮想化ベースのセキュリティーおよびハードウェア・セキュリティー緩和策が有効化された状態)をエクスプロイトするために使った微妙なカーネル脆弱性で、今年Pwn2Ownで初めて勝利を収めました。

この記事では、バグ・ハンティングに対する私の簡単なアプローチについて概説します。つまり、出発点を選択し、何かに気づくまで直感的に経路をたどるというものです。このバグは、ロジック・エラーにより確実に発生できるため、興味深いものです。このエラーは、プロセス間通信システム内の特定の状態で発生し、ユーズ・アフター・フリーを引き起こします。バグを見つけるには、考えられるさまざまな状態にわたってプログラムのコード・パスを比較する必要がありましたが、そのプロセスについて詳しく説明します。同様に魅力的なのは、バグの原因と、それに対するMicrosoftのアプローチです。これらのトピックについては、この投稿でも取り上げています。

0日間のハンティング:どこから始めるべきか。

脆弱性研究に関してよく寄せられる質問は、どのように始めればよいかということです。実際、ターゲットを選んでそれに実施することは、研究プロセスの中で最も困難なステップの1つかもしれません。ここで説明する脆弱性は、Microsoft Kernel Streaming Service(mskssrv.sys )にあります。サブシステムの概要については、このブログ記事をご覧ください。その中で、MSKSSRVサブシステムのいくつかの特性が、優れた攻撃対象領域となる可能性があること、特にそのプロセス間通信(IPC)メカニズムについて指摘しました。

MSKSSRVのコード・ベースはかなり小さく、私が発見したこのサブシステムの最後の脆弱性も、ゼロデイとして単独で悪用されました。また、他の研究者や企業から、この要因を監査するためのさらなる取り組みについても聞きました。このため、当初は私もよくある落とし穴に陥り、この攻撃対象領域にはこれ以上発見すべき脆弱性が存在しないと思い込んでしまいました。しかし、以前のブログ記事で提案したこともあり、直感を信頼して探し続けることにしました。

ロックロック:誰だ。

新しい研究のアイデアを得る優れた方法は、現在の研究に関する情報を常に把握することです。k0shlによる素晴らしいブログ記事を読み、特定の種類のバグを探すきっかけになりました。k0shlが発見した脆弱性では、オブジェクトの参照数が適切にロックされずに初期化および増加され、フリー・ウィンドウ後の使用が作成されます。k0shlのバグはユーザーランドのバグでありカーネルにはないにもかかわらず、脆弱なライブラリーのコーディング・スタイルは、以前にMSKSSRVドライバーを監査したときのことを思い出させました。

MS KSサーバー(MSKSSRV)は、FSStreamReg およびFSContextReg オブジェクトをVIA® ユーザーランド・プロセスとやり取りします。FSStreamReg およびFSContextRegは、どちらもベースFSRegObject クラスから派生しています。私は次のことに気づきました。FSContextReg はロックするvtable関数を実装しておらず、ベース・クラス(FSRegObject )の実装はnop命令です。これは、FSContextReg オブジェクトにはロック・メカニズムが実際には実装されていないことを意味します。逆に、FSStreamReg はミューテックスを利用したロック機能を実装します。ロック機構は、次の関数FSRendezvousServer::Closeでクリーンアップのためにオブジェクトにアクセスする際に使用されます。

FSRendezvousServer::Close関数のスクリーンショット

FSRendezvousServer::Close、FSRegObjectsのパスロックおよびアンロック処理

FSRegObject  基本クラスから派生したオブジェクトは2つありますが、一方のオブジェクトタイプは適切なロック機構を実装し、もう一方のオブジェクトタイプは実装していません。私はこの点を疑いました。自分の理論をテストするために、保護されていないFSContextRegオブジェクトへの参照を使用して、未定義の動作をトリガーしようと試みました。しかし、FSRegObjects のリストへのポインターを保持するグローバル FSRendezvousServer  オブジェクトのロック保護により、FSContextReg  オブジェクトにロック保護が欠如しているにもかかわらず、興味深いものをトリガーすることができませんでした。それでも、FSRegObjects の参照カウントシステムには何か「怪しい」点があると感じていましたが、それが何かは分かりませんでした。

MS KSサーバーのIPC

前回のブログ記事で言及したように、MSKSSRVのプロセス間オブジェクト共有の側面は脆弱性への興味深い道筋であるため、さらに焦点を当てることにしました。サブシステムのIPCメカニズムは、次の図に示されています。

サブシステムのIPC機構の図

図1:MS KS Serverにおけるプロセス間通信

CreateFileをMSKSSRVデバイスVIA® ファイル・ハンドルを開くと、そのハンドルに対応するFILE_OBJECTが作成されます。このハンドルを使用して、プロセスは、DeviceIoControl関数を使用してデバイスにIOCTLを送信することにより、新しいストリームまたはコンテキスト・オブジェクトを初期化することができます。初期化プロセスは、lpInBuffer 引数をVIA® プロセスIDを指定することにより、どのリモートプロセスがオブジェクトを登録できるかを指定します。リモート・プロセスは、MSKSSRVデバイスへの新しいファイル・ハンドルを使用して、デバイスIOCTL VIA® オブジェクトを登録できるようになりました。FSRegObjectのポインターは以下に保管されます。

Irp->CurrentStackLocation->FileObject->FsContext2に保存されています。

FSRegObjectオブジェクトへの同じポインタがFSContext2に2回保管され、初期化プロセスによって使用されるFILE_OBJECT に1回保管され、登録プロセスによって使用されるFILE_OBJECT で1回使用されます。このようにして、FSRegObject オブジェクトへの参照をプロセス間で共有できます。たとえば、FSStreamRegオブジェクトを使用すると、図1に示すように、複数のプロセスがストリーム・フレーム・バッファーにアクセスできます。FSRegObject の参照数は1に初期化され、初期化が完了した後に再び増分されます。FSRegObject を登録すると、参照数が再び増加し、オブジェクトごとに合計3つの参照が行われます。

FSContextRegオブジェクトの初期化と登録の図

図2:FSContextRegオブジェクトの初期化と登録

バグの発見

そこで、以前に監査した内容をもう一度検討して、ロックの脆弱性を探すことにしました。 FSRendezvousServer::Close を呼び出す関数 FSRendezvousClose, が、要因のdispatch cleanup および close 関数ルーチン内で呼び出されます:

MS KSサーバー要因のDispatchCleanupとDipatchCleanupルーチンを使用したCodeBlockの製品の画面

コード・ブロック2:MS KSサーバーのDispatchCleanupおよびDipatchCleanupルーチン

ディスパッチ・ルーチンは、パッケージ化されたI/Oリクエストである1つ以上のタイプのIRPを処理します。Windowsでは、ファイルへのすべてのハンドル参照が閉じられた場合、対応するファイルシステム要因が IRP_MJ_CLEANUP  および IRP_MJ_CLOSE  リクエストを受け取ります。これは、要因の DispatchCleanup および DispatchClose 関数ルーチンによって処理されます。

MSKSSRVでは、 Irp->CurrentStackLocation->FileObject->FsContext2  に保管されているポインタが NULLではない場合、要因の DispatchCleanup 関数ルーチンと  DispatchClose 関数ルーチンの両方で FSRendezvousClose  が呼び出されます。私が以前に分析した FSRendezvousServer::Close で際立っていたのは、呼び出し元のプロセスIDやに対するさまざまなチェックです。すべてのカーネル・モード・コードは、ユーザー・モード所在地空間とは別の単一のカーネル所在地空間内で動作するため、プロセスのコンテキストが重要です。各プロセスには独自のユーザー・モード・メモリー・コンテキストがあり、カーネル・スレッドが実行されるプロセス・コンテキストによって、スレッドがユーザー所在地にアクセスする場合にどのプロセスのユーザー・モード所在地空間にアクセスするかが決定されます。次のコードは、呼び出しプロセスが初期化プロセスまたは登録プロセスであるかどうかをチェックします。

FSRendezvousServer::Close関数のスクリーンショット

コード・ブロック3:FSRendezvousServer:: Close、FSRegObjectsのプロセス・チェック

プロセス固有の情報はFSRegObject に保管されます。  保管先:

Irp->CurrentStackLocation->FileObject->FsContext2


初期化または登録時にドライバーは、特定のリソースをどのプロセスが使用するかを決定し(

EPROCESS

オブジェクト、イベント・オブジェクト、その他)、呼び出し元のプロセスIDを確認して解放する必要があります。プロセスが初期化プロセスまたは登録プロセスである場合は、それらのプロセス固有の参考情報に対してさらにクリーンアップが行われます。

この点に着目した理由として、一般的にすべてのDispatchルーチンは、いくつかの例外を除いて、任意のプロセス・コンテキストで実行されることがあります。つまり、システムはDispatch作業を実行するスレッドを選択します。どのスレッドを選択するかは任意です。DispatchCleanup が、最終処理を終了したプロセスのコンテキスト内で呼び出されていることを発見しました。したがってこの場合、プロセスIDチェックは理にかなっています。しかし、DispatchClose任意のプロセス・コンテキストから呼び出されます。つまり、IRP_MJ_CLOSE リクエストの成果としてFSRendezvousServer::Close が呼び出される場合、それは任意のプロセス・コンテキストからのものとなり、プロセスIDチェックの目的が損なわれます。これは、何かがおかしいと気付く大きな手がかりでした。

さらに、Windows OSの主要な機能として、ハンドルを他のプロセスと共有することができます(子プロセスの継承またはDuplicateHandle API関数を使用)。共有ファイル・ハンドルをVIA® 、他のプロセスも同じFILE_OBJECT とやり取りできます。

共有MS KSサーバー・デバイス・ハンドルの図

図3:共有MS KSサーバー・デバイス・ハンドル

これにより、DispatchCleanup  中のプロセス・コンテキストが初期化プロセスでも登録プロセスでもない可能性もあります。これらのハンドルのいずれかが複製されて別のプロセスに共有されており、そのプロセスが最後にハンドルを閉じている場合、DispatchCleanup  は、その外部プロセス(初期化プロセスまたは登録プロセスではない)のコンテキスト内で呼び出されます。

FILE_OBJECTに対する外部プロセスの最終処理の図

図4:FILE_OBJECTを終了する外部プロセスの最後の処理

ファイル・ハンドルが閉じられているときに、関数FSRendezvousServer::Closeが2回呼び出される可能性があることに気づきました(IRP_MJ_CLEANUPリクエスト用に1回、IRP_MJ_CLOSE リクエスト用に1回、Code Block2)。その関数には、FSRegObject::Releaseへの呼び出しが2回ある可能性があります(Code Block 4)。参照数が0まで減少すると、オブジェクトをデリファレンスし、メモリーを解放します。つまり、FSRegObject::Release はハンドルのために最大4回呼び出すことができます。さらに、FILE_OBJECT FSContext2 ポインターをVIA® 同じFSRegObjectを指すファイル・ハンドルが2つあります。つまり、FSRegObject::Release  を同じオブジェクトに対して最大8回(ハンドルごとに4回)呼び出す可能性があります。オブジェクトの元の参照数が3つだけの場合、デリファレンス数が多すぎることによりユーズ・アフター・フリーがトリガーされる可能性があります。いずれにせよ、それが私の考え方です。プログラム構造により、理論上の最大デリファレンス数に達するのをおそらく回避できることはわかっていましたが、おそらくまだ十分ではありません。この時点で、私は何か重要な手掛かりを見つけたと感じ、さらに調査することにしました。

FSRegObject::Release のスクリーンショットは、FSRendezvousServer::Close から 2 回呼び出される可能性があります。

コードブロック4: FSRegObject::Release は FSRendezvousServer::Close から二度呼び出される可能性があります

一般に、オブジェクトへの参照数よりも多くのデリファレンスをすることは、ユーズ・アフター・フリーが発生する唯一の方法ではありません。ただしこの場合、FSRegObject が解放されていれば、その参照数がゼロになったことを確認できます。有効なFSRegObject が最後にIRP_MJ_CLEANUP/CLOSE IRPリクエスト中にアクセスされるのは、FSRegObject::Release への呼び出しにあります。したがって、use-after-freeが可能な場合、FSRegObject::Release の呼び出しは、常に オブジェクトがすでに解放された後に発生します。呼び出し中に、オブジェクトは再びデリファレンスされます。そのため、デリファレンス数のカウントは、この特定のケースのuse-after-freeを見つけるための優れたヒューリスティックです。

唯一残された作業は、オブジェクトがいつ解放されてアクセスされたかを記録しながら、可能性のあるプログラムの状態をトレースすることでした。私はこれを、IRP_MJ_CLEANUP/CLOSE リクエスト中のプログラム・ロジックを頭の中でエミュレートして行いました。各リクエストは、考えられる各ケースごとに対応するDispatch関数(Code Block 2)で始まります。。

以下に、どのプロセスがハンドルへの最終的なリファレンスを閉じているかに基づいた状態を示します。各エントリーは、対応するプロセスが最終処理を閉じた場合に発生するFSContextRegオブジェクトのデリファレンスの数を表します。注: HANDLE #1(ハンドルの初期化)とHANDLE #2(ハンドルの登録)の間には機能上の違いはありません。 FileObject->FSContext2 フィールドは、対応するハンドルによって表される両方のFILE_OBJECT で同じメモリを指します。

考えられる各 MSKSSRV IPC ステートの fsContextReg参照解除のスクリーンショット

可能なMSKSSRV IPC状態ごとのFSContextReg参照解除

成功です。最終的に、次の4つのデリファレンスが成果:外部プロセスで2つ、初期化(および登録)プロセスで2つです。最初は3つだけ参照され、これはユーズ・アフター・フリーが可能であることを意味します。また、FSStreamReg オブジェクトでも同じ作業を繰り返しましたが、コード内のメモリー・リークのバグにより、FSStreamReg オブジェクトが登録された後に解放することは実際には不可能です。

脆弱性

上記で概説した仮想マシンの知能演習を行っているときに、問題を発見しました。プロセスが初期化プロセスまたは登録プロセスである場合、適切なクリーンアップが行われ、Irp->CurrentStackLocation->FileObject->FsContext2  に保管されているポインターは NULL に設定されます。以下のコード・ブロックは、呼び出し元が初期化プロセス中である場合に、これが発生する場所を示しています。

FSRegObject::CloseInitProcess のスクリーンショットでは、FSContext ポインタが NULL に設定されています

コード・ブロック5: FSRegObject::CloseInitProcess は、FSContextポインタをNULLに設定します

これは、DispatchClose  (SrvDispatchClose、Code Block 2)の IRP_MJ_CLOSE  リクエストの完了中に、FSRendezvousClose  は再度呼び出されないことを意味します。

ただし、呼び出しプロセスが外部プロセスの場合は、クリーンアップは行われず、FSRegObject::Release  は関数の終わり近くで一度呼び出されます。FileObject->FsContext2  が NULLではないため、後続の IRP_MJ_CLOSE  リクエスト中に FSRendezvousServer::Close  が再度呼び出され、FSRegObject::Release への別の呼び出しが発生します。

ここで、FSContextRegオブジェクトを初期化および登録したプロセスによって2番目のハンドルが閉じられると、オブジェクトは保管されているすべてのプロセス参考情報をクリーンアップして空になります。このため、FSRendezvousServer::Close(Code Block 4)内で FSRegObject::Release  が2回呼び出されます。追加のデリファレンスは、オブジェクトが空になった際に追加の初期化参照を考慮するために機能します。

これにより、1つのFSContextRegオブジェクトに合計4つのデリファレンスが生じ、ユーズ・アフター・フリーが発生することがわかります。

CVE-2024-30089の図

図5:CVE-2024-30089の図

ここまで読んできた読者は、なぜ異質のプロセスが両方のハンドルを最後に閉じることができないのか疑問に思うかもしれません。これは、4つのデリファレンスにつながるようにも見えるからです。オブジェクトが破棄されて解放される前に、グローバルのFSRendezvousServer オブジェクトに保管されているリストからのリンクが解除されます。FSRendezvousServer::Close の冒頭で、FSContext2 のポインタはリストの有効なメンバーであるかどうかがチェックされます。この場合、オブジェクトは関数の終了時にFSRegObject::Releaseへの2回目の呼び出しで解放されます。FSRendezvousServer::Close への4回目の呼び出し中に、オブジェクトはすでにリストからリンク解除されており、無効なオブジェクトになっているため、使用できません。use-after-freeをトリガーするためには、オブジェクトが検索され、FSRendezvousServer::Close で検証された後である必要があります。以下のコード・スニペットは、この脆弱性によって獲得できる、use-after-freeのプリミティブを示しています。

コードUAFプリミティブ・パスの画面

コード・ブロック6:UAFプリミティブ・パス

攻撃の複雑さ

この脆弱性の セキュリティー・アップデート・ガイドでは、CVSSスコアは「エクスプロイテーション [is] More Likely」であり、この脆弱性に対する攻撃の複雑性は「Low」です。Microsoft社はそのスコアリングについて詳細な説明を提供していませんが、私は他の脆弱性をパッチする際にいくつかのパターンに注目してきました。脆弱性がこのスコアを獲得したのは、ロジック・エラーに起因しており、確実にトリガーできるためです。図5に概説されているステップに従うことで、攻撃者はコード・ブロック6に示されている無料使用後のシナリオを一貫してトリガーすることができます。ただし、これは、実際にこれを活用するのが簡単という意味ではありません。エクスプロイテーションの手順の詳細なウォークスルーについては、このシリーズの次の部分で説明します。

振り返り

バグがどのように発生したかを理解することは、安全な開発手法に対する事前対応的なアプローチを培う上で重要です。脆弱性がどのようにして導入されたかを突き止めるために、私はWinbindexから入手した要因の過去のバージョンを分析し、FSRendezvousServer::Close  関数のロジックに違いがないかを探しました。

脆弱性のセクションで、このバグの根本的な原因は、設定されていない、

Irp->CurrentStackLocation->FileObject->FsContext2


NULL

呼び出すプロセスが外部プロセスである場合驚くことに、mskssrv.sysの初期バージョンには、まさに次のようなコード行がありました。

FSRendezvousServer::Close の初期バージョンの、FsContext2がNULL に設定された場合の、コードのスクリーンショット

コード・ブロック7:FSRendezvousServer::Close、FsContext2の初期バージョンはNULLに設定されています

上記のコード・ブロックでは、前のプロセスIDチェックの成果に関係なく、FileObject->FsContext2  は明示的に NULL に設定されています。これにより、後続の IRP_MJ_CLOSE  リクエストで FSRendezvousServer::Close  が再度呼び出されることがなくなり、追加の参照が発生することがなくなります。奇妙です。ではなぜこの行のコードが削除されたのでしょうか。バグが最初に特定された後のバージョンの関数を見てみましょう。

機能フラグ・チェック内でFSContext が NULLに設定されているスクリーンショット

コード・ブロック8:主要な機能フラグ・チェック内でFsContextをNULLに設定する

上記のコード・ブロックは、主要な機能フラグのチェックを示しています

Feature_Servicing_TeamsUsingMediaFoundationCrushes


主要な機能フラグはさまざまな機能と実験を切り替えるWindowsのコンポーネントですが、それらについてはあまり公開されていません。以前のブログ記事では、脆弱性パッチに機能フラグがどのように使用されているかについて説明しました。主要な機能フラグは、正式に採用される前に機能をテストするために使用されることがあります。この場合であれば

Feature_Servicing_TeamsUsingMediaFoundationCrushes

主要な機能が有効になると、FileObject->FsContext2 NULLに設定されていないため、脆弱性が発生します。この主要な機能は、Windows 10インストールではデフォルトで有効になっていることが確認されています。Windows 11およびCode Block 1に示されているように、この主要な機能 flagの条件文は存在せず、ポインターはNULL に設定されていないため、これも脆弱です。

 

その主要な機能名から、ビデオ会議ソフトのMicrosoftTeamsの主要な機能を調べてみました。アプリケーションがMSKSSRV機能を使用して、プロセス間でメディア・ストリームを共有できることを確認しました。ストリームのハンドル共有が原因でTeamsがクラッシュした可能性があります。さらなる研究のための興味深いテーマは、Teamsがプロセス全体でMSKSSRVデバイスをどのように共有しているのか、また、適切なクリーンアップを実行するとアプリケーションがクラッシュする可能性がある理由を調査することです。

パッチ

シリーズのこの部分では、パッチを含む脆弱性自体に焦点を当てています。私が提案した修正はMicrosoft Teamsのクラッシュを引き起こすように思えたので、このバグのパッチを調べることに特に興味を持っていました。ここで重要なのは、現時点では、実際のアプリケーションがMSKSSRVドライバーをどのように使用しているかについては、まだ検証していません。このコンテキストがないと、システムがなぜそのように設計されているのかという理解に盲点が生じます。このバグに対する完全なパッチには、ある程度のベース・コードの再構築が必要で、IPCシステムがどのように機能するように意図されているかについて詳細が明らかになることもあります。また、Microsoftの開発者から安全なコーディングの実践に関する洞察を得たいと考えていました。

残念ながら、脆弱性の原因となったロジック・エラーは、2024年6月のセキュリティー・アップデートでパッチが適用され、直接対処されませんでした。代わりに、アクセス・トークン・チェックが脆弱なコード・パスの前に追加されました。関数 FSRendezvousServer::InitializeContext によって処理される初期化コンテキストIOCTLについては、以下のコードを参照してください。

IOCTL関数のスクリーンショットは、機能フラグの確認から始まり、呼び出し元プロセスがフレーム・サーバーであるかどうかを確認します

コード・ブロック9:IOCTL関数は主要な機能のチェックから始まり、呼び出しプロセスがフレーム・サーバーであるかどうかをチェックします

上記の関数は、主要な機能が有効かどうかを確認することから始まります。これはおそらく、パッチに対応する主要な機能のフラグでしょう。主要な機能が有効なら、KsIsCurrentProcessFrameServer  は必ずTRUEを返し、そうでない場合、NTSTATUS  の値 STATUS_ACCESS_DENIED  が返されます。

では、KsIsCurrentProcessFrameServer について見てみましょう。

KsIsCurrentProcessFrameServerが呼び出し元スレッドのアクセストークンに対してSIDチェックを実行しているスクリーンショット

コード・ブロック10:KsIsCurrentProcessFrameServerが呼び出しスレッドのアクセス・トークンのSIDチェックを実行

この機能は、呼び出しスレッドのトークンを2つの特定のセキュリティー識別子(SID)に照合してチェックします。SIDはグループNT SERVICE\FrameServer のトークンに対応します。いずれかのSIDが呼び出しスレッドのアクセス・トークンで有効になっている場合、脆弱な関数コードが実行できます。

これを見た後、私はadmin-to-kernelバグがまだ存在している可能性があると疑いました。最終的に、メモリー破損の問題はまったく解決されませんでした。私は、元のエクスプロイトに少し変更を加えることで、これを確認しました。管理者ユーザーは、FrameServer サービスを開始し、サービスへのハンドルを開き、そのハンドルを使用してエクスプロイト・プロセスを作成できます。完全にパッチが適用されたシステム上で、完全なカーネルR/Wプリミティブを取得することができました。

Microsoft社は、アドミニストレーターからカーネルへの境界をセキュリティーの境界とは考えていないが、同様のバグは、脅威アクターによってカーネルのR/Wプリミティブを獲得し、EDR(エンドポイントの検知と対応)の目くらましやルートキットのオペレーションに使用するために使用されてきました。このプリミティブでどんなことができるのか興味がある人は、FuzzySecと並んだ私のBlackHatでの講演をチェックしてください。

結論と次のステップ

この投稿では、Pwn2Ownの取り組みのうち脆弱性の研究の部分に焦点を当てました。その取り組みは、特権昇格のために悪用できる0デイ・カーネル脆弱性を発見するというものでした。この投稿では、他の研究から着想を得て、バグの発見に失敗し、新しい角度を決め、疑わしいものを見つけ、最終的に脆弱性がどこにあるかを特定するという過程の概要を説明します。バグが特定され解放後の使用というプリミティブがあるので残りは簡単に進みますマイクロソフトはそう考察しているようです、このバグの数は「エクスプロイテーションが発生しやすい」攻撃の複雑さは「低」と評価しました。彼らは正しいのでしょうか。次の部分では、エクスプロイテーション・ストラテジーについて説明し、シリーズ・タイトルの意味を明らかにします。

謝辞

Andréa Piazza、素晴らしいダイアグラムのために

Emma Kirkpatrick、Windowsのセキュリティー・モデルを辛抱強く説明してくれた。

オフィスでミーティングをするビジネスチーム

IBMお客様事例

お客様のビジネス課題(顧客満足度の向上、営業力強化、コスト削減、業務改善、セキュリティー強化、システム運用管理の改善、グローバル展開、社会貢献など)を解決した多岐にわたる事例のご紹介です。