Kubernetes Threat Matrixの再構築およびFalcoによる攻撃検知の検証

メルカリのセキュリティチームでインターンをしている赤松宏紀(@hi120ki)です。
私はセキュリティチームの中でも、インフラセキュリティなどを担当しているSecurity Engineering Team(紹介記事)にて8月中旬からの一ヶ月半、Kubernetesのランタイムセキュリティ監視ツールであるSysdig SecureFalcoの再検証に取り組みました。

本記事では、再検証によって獲得した、下記の知見について紹介します。
・ Microsoft社が公開しているThreat matrix for Kubernetesに不足している攻撃手法の検討
・ Falcoへの攻撃検知ルールのコントリビュート
・ Falcoの検知回避手法と対策
・ Falcoによる攻撃検知の効果と限界

また実施したタスクの内容の他に、インターンをする中で感じたメルカリでセキュリティエンジニアとして働く上で求められる視点や働き方などもお伝えしたいと思います。メルカリのインターンシップや新卒入社に興味がある方の参考になれば幸いです。

Sysdig Secure・Falcoの紹介とタスクのスコープ

FalcoはカーネルモジュールかeBPFによって、カーネルで実行されたシステムコールを収集し、事前に設定したルールによって攻撃を検知するOSSです。
OSSとして管理されているルールはGitHub上のFalcoレポジトリで公開されており、重要なファイルへのアクセスや不審なプログラムの実行やネットワークアクセスなどを検知できます。

またFalcoはシステムコールをカーネル内で収集するため、コンテナ上の仮想化されたプロセスが実行した処理の収集ができます。そのためコンテナやKubernetes上での攻撃を検知するツールとして知られています。

Sysdig SecureはOSSであるFalcoを中心に主に以下のセキュリティ機能を提供している有償のSaaSです。
・ Falcoによる攻撃検知
・ コンテナ内の挙動の記録とフォレンジック
・ コンテナイメージスキャン
・ Kubernetes audit logの監査

メルカリでは多くのサービスをKubernetes(Google Kubernetes Engine)上で運用しており、Kubernetesクラスタへの攻撃の検知・攻撃の痕跡の記録のためにSysdig Secureを2020年より採用しています。2020年の導入時にはメンターの末澤裕希(@rung)さんが脅威モデリングを行い、他社製品との機能比較を経て採用されました。

そして現在、導入から約2年が経過しKubernetesのセキュリティの脅威情報が整い、Sysdig Secureからも新機能がリリースされていることから、脅威モデリングを再度実施し、Sysdig Secureの新機能・更新されたFalcoルールの評価、そして脅威モデリングの中で見つかった既存ルールではカバーされていない攻撃手法を検知する新たなルールを作成し、本番環境への導入と検証までを行いました。

メルカリでは有償SaaSであるSysdig Secureを主に利用していますが、本記事の「Falcoの攻撃検知ルールの更新」章以降の検知エンジンの説明に関して、Sysdig Secure特有の事項ではなく、Sysdig Secureに含まれるオープンソースのFalcoに関する詳細を紹介します。

Kubernetesクラスタに対する脅威モデリング

脅威モデリングとは対象のシステムのセキュリティ上の脅威を洗い出すことで、システムの設計時によく実施されます。しかし今回は既に稼働しているKubernetesクラスタを対象とし、攻撃者がどのようにKubernetesクラスタに対し攻撃の足がかりを作り展開していくのかに注目しました。
Kubernetesクラスタに対する脅威モデリングにあたってはMicrosoft社が公開しているThreat matrix for Kubernetesを参考にしました。このThreat matrixは、サイバー攻撃の手法をまとめたMITRE ATT&CKに記載されている攻撃手法のうちKubernetesに適用できるものを抽出し、更に新たな攻撃手法を追加したものです。Initial Accessから始まりExecution・Privilege Escalation・Credential Access・Discovery・Lateral Movementというような攻撃者によるKubernetesクラスタの攻撃ライフサイクルの中での行動が記載されています。
なお、脅威モデリングにおいて、MicrosoftのThreat matrix for Kubernetesでは不足している攻撃手法を、適宜MITRE ATT&CKのContainers Matrixなどを参考にし独自に補足しました。例えば侵入後の権限確認行動やConteiner socketのマウント、潜在的なContainer Escapeの危険性があるCapabilityの付与、Container Escape Exploitの実行などを追加しています。

上記をもとに脅威モデリングを行い作成したThreat matrixはこのようになります。

緑色の攻撃手法はThreat matrix for Kubernetesから付け足したもので、詳細は下記の通りです。

  • Execution
    • Debug by ephemeral container : 攻撃者がKubernetesへのアクセス権限を持っている場合、従来のkubectl execに加えて新たに追加されたkubectl debugにより、Ephemeral containerを介したコンテナ内での任意コード実行が可能です
  • Privilege Escalation
    • Too much capability : CAP_SYS_ADMINといった特定のCapabilityをコンテナへ付与することでコンテナエスケープの危険が高まります。コンテナエスケープされた場合、ホストでの操作が可能となります
    • Weak AppArmor Profile : コンテナ内部での挙動を制限するAppArmorプロファイルを無効化することででコンテナエスケープの危険が高まります。コンテナエスケープされた場合、ホストでの操作が可能となります
    • Mount container socket : コンテナランタイムへアクセスできるSocketをマウントすることで、コンテナ内部から他のコンテナを操作したり、ホストの操作が可能となります
    • Sharing Host Namespaces : ホストのNamespaceを共有することによってコンテナ内部からHost Networkのアクセスや、Host PIDなどを利用でき、権限昇格に繋がります
    • Kernel exploit to escape container : カーネルの脆弱性を突く攻撃コードによってコンテナエスケープされ、ホストでの操作が可能となります
  • Credential Access
    • Read process environment variables : 環境変数を読み取られた場合、様々なシークレット情報や設定値が窃取される危険があります。シークレット情報を窃取された場合、他リソースへのアクセスなどに繋がります
  • Discovery
    • Checking pod settings inside container : コンテナ内部のファイルシステム等を調査することで、コンテナにどんな権限が与えられているのかを判別します
    • Install discovery tool outside container : ネットワークスキャンツールなどを外部からインストールされた場合、侵入拡大のためのKubernetes環境の調査に繋がります

さらにそれぞれの攻撃手法に対して具体的な攻撃コードを作成しました。そして攻撃手法・具体的な攻撃コード・参考文献をスプレッドシートにまとめ、Threat matrixとスプレッドシートを見るだけで攻撃の再現と検証ができるようにしました。

このような脅威モデリングを行いThreat matrixを作成することで攻撃手法の網羅を目指しました。攻撃のライフサイクル全体において攻撃者はInitial Access・Execution・Privilege Escalationといった様々な攻撃手法を駆使して侵入を広げると想定できます。
次章のFalcoの攻撃検知ルールの更新においては、そのような攻撃の各フェーズで検知できるようなルールセットを作成することを目指しました。

Falcoの攻撃検知ルールの更新

脅威モデリングにおいて作成したそれぞれの攻撃コードを検証用のKubernetesクラスタ上で実行し、Falco・Sysdig Secureの既存機能・新機能でそれぞれ検知できるかを確認し、Falcoの新規ルールの作成や既存ルールの不備の修正を行いました。

作成した新規ルールの例としては、Threat matrixに新たに追加した攻撃手法のRead process environment variablesの検知ルールを作成しました。このルールでは、SSRFやPath traversalの脆弱性がある場合に環境変数を読み出すためにアクセスされる、/proc/self/environ/proc/1/environファイルの読み込みを検知します。
一般的に環境変数には他のリソースへアクセスするためのクレデンシャルやアプリケーションの設定値などの重要な情報が格納されます。
また、Linuxのファイルシステムでは/proc以下のファイルから様々なインターフェイス情報を取得でき、その中でも/proc/[pid]/environはpidを指定してそのプロセスに設定されている環境変数を読み出すことができるファイルです。

kind: Pod
apiVersion: v1
spec:
  containers:
    - name: ssrf-poc
      env:
      - name: MY_SECRET
        value: 8c2886dca39e7b692cb378e704072ad4

たとえば、このようなmanifestで環境変数にMY_SECRETという機密情報を追加したPodを作成し、攻撃によって/proc/self/environファイルを読み出すとPodに設定した機密情報であるMY_SECRETを盗み出すことができます。

KUBERNETES_PORT=tcp://10.24.0.1:443
KUBERNETES_SERVICE_PORT=443
...
MY_SECRET=8c2886dca39e7b692cb378e704072ad4

今回作成したルールは、多くの環境でも有用と考え、オープンソースのFalcoルールにPull Requestを作成しマージされました。(Add new rule that detect retrieving environment variables from /proc files #2193 – Falcosecurity/Falco)

この他にも既存ルールの不備やバグの修正など9件のPull Requestを作成し、Falcoチームが持つ知見もフィードバックしてもらいつつ、適宜コミュニケーションを取りながらコントリビュートしました。

Falcoの検知回避手法と対策

今回、脅威モデリングをもとに検知ルールを再検証しましたが、その中でFalcoの検知を回避する手法についても調査しました。
その中で森田浩平(@mrtc0)さんのHow to Bypass Falcoという記事にて紹介されていたSymbolic linkファイルの/proc/self/rootを用いたファイルパス検知回避手法に注目しました。

Linuxでファイルに関する操作をする場合、そのファイルをオープンするopenatシステムコールが実行されます。openatシステムコールの第2引数にはファイルパスが格納され、例えばcat ../etc/shadowコマンドを実行するとこのようにopenatシステムコールが呼び出されます。

openat(AT_FDCWD, name=../etc/shadow, flags=1(O_RDONLY))

そして、このopenatシステムコールの引数のファイルパスをパース(..や.を使わない)した絶対パスをFalcoではfd.nameというパラメーターで提供します。たとえば、Read sensitive file trusted after startupというルールでは、このfd.nameによって認証情報が格納されている/etc/shadowファイルなどへの読み取りを検出しています。

また、Symbolic linkとは、あるファイルやディレクトリへのパスを指すリンクのことで、例えばUbuntuにおいて、findコマンドによってデフォルトで存在しているSymbolic linkファイルの例は下記のとおりです。

# find / -type l -xtype d -ls 2> /dev/nul
  1554024      0 lrwxrwxrwx   1 root     root            9 Aug 15 11:50 /lib64 -> usr/lib64
       12      0 lrwxrwxrwx   1 root     root           13 Sep 15 04:36 /dev/fd -> /proc/self/fd
…

その中でもSymbolic linkが指す先がディレクトリとなっているSymbolic linkがいくつかあります。

/proc/self/root -> /
/proc/self/cwd -> (proccess dir)
/dev/fd -> /proc/self/fd
/var/spool/cron/crontabs -> /etc/crontabs
/var/spool/mail -> /var/mail

これを用いることで、下記のように/var/spool/cron/crontabs/../shadowというパスで/etc/shadowファイルを指定できます。

openatシステムコールの引数 Falcoのfd.name 実際にアクセスされるファイルパス
/var/spool/cron/crontabs/ /var/spool/cron/crontabs/ /etc/crontabs
/var/spool/cron/crontabs/../ /var/spool/cron/ /etc/
/var/spool/cron/crontabs/../shadow /var/spool/cron/shadow /etc/shadow

cat /var/spool/cron/crontabs/../shadowコマンド実行時にFalcoはopenatシステムコールの引数のファイルパスをパースしfd.nameを生成しますが、このときFalcoはパスに含まれているSymbolic linkを考慮せずに、/var/spool/cron/shadowと記録されます。この場合、ルールRead sensitive file trusted after startupではfd.nameが/etc/shadowと一致するという条件のため、検知を回避されてしまいます。

またこれ以外にも今回提案した/proc/self/environを検知するルールについても/dev/fd -> /proc/self/fdを使い/dev/fd/../environから取得でき、検知を回避できました。

今回、このSymbolic linkファイルによるFalcoの検知回避について一時的な対策と修正を提案しました。まずは一時的な対策として、著名なDocker image内にデフォルトで存在しているSymbolic linkファイルを検知する新たなルールについて、Pull Request(Add rule to detect bypass by symlink files #2202)を送りました。ただし、このルールだけでは未知のイメージや他のパッケージをインストールした際に新たに生成されるSymbolic linkファイルによる検知回避の検出ができないため、fd.nameの生成の中でSymbolic linkのパスを解決し根本的な修正を議論するためにIssue(Discuss about fundamental solution of detecting symlink file based bypass method #2203)を作成し、議論を継続しています。

Falcoによる攻撃検知の限界と今後期待すること

この章では、今回の検証の中で、実際のメルカリ本番環境へのルールのデプロイなども行った上で感じたFalcoの効果と限界について紹介します。
冒頭でも紹介したようにFalcoは実行されたシステムコールを収集し事前に定義したルールによって検知します。
このシステムコールによる攻撃検知は、必ず特定のシステムコールが実行されるような攻撃、例えば特定のファイルや外部への通信などでは効果を発揮しますが、下記の場合は検知が難しいという特徴があります。
・ アプリケーションレイヤ内で完結する攻撃
・ 1つのシステムコールで特定できず、複数のシステムコールによって特定できる攻撃

SQLインジェクションなど、アプリケーションレイヤ内で完結する攻撃については、システムコールベースの検知だけでは原理的に対応できず、別のソリューションが必要となります。
またFalcoでは、単一のシステムコールベースの検知しか出来ませんが、今後、複数のシステムコールによって特定できるような機能改善も期待しています。現在のFalcoによる検知は誤検知が多いという特徴があるので、攻撃を構成するような複数の行動が確認された時のみ検知するようにし誤検知を減らすことができれば、大幅に利便性が増すと思います。

またFalcoの運用に関して、検査がシステムコールごとに実施されるため、Kubernetes上で数十~数百単位で動かしているPodで検知されるような挙動があるとアラートが大量に発生することがあります。メルカリではアラートを監視基盤に転送した上で同じアラートをまとめる仕組みを開発し運用していますが、公式でこういった同一の大量検知を柔軟にまとめる仕組みが整備されていくことも期待しています。

インターンシップを通して得たこと

今回のインターンシップの中で印象的だったのが、Threat matrix for Kubernetesに欠けている攻撃手法を探し、既にあるFalcoルールが正しく検知するかを攻撃コードを作成し検証するという「本当に安全なのか」をきちんと検証するメルカリセキュリティチームの姿勢です。「安心安全なサービスを提供する」というセキュリティ対策の目的を見失わず、必要なことを考え行動していくことを実践して、1つの情報を鵜呑みにせず複数の情報ソースを調査する・実際に攻撃を再現し確実に検証する・Falcoの検知回避手法といった実験的なことを深堀するといったセキュリティ対策全体のプロセスを実践できました。

またタスクの開始にあたり、全体的な目線を持つためにいろいろとサポートをして頂きました。メルカリ内の課題だけではなくKubernetesセキュリティやFalcoでの検知が将来どうなっていくかを学ぶために外部の有識者やSysdig Secureのサポートの方と議論する機会を作って頂き、最終的に目指したいKubernetesセキュリティの世界を把握した上でタスクを進めることができました。このような足元の目標から一歩進んだ理想を見通していたことで、Falcoの検知バイパスといった踏み込んだトピックについて積極的に取り組むことができました。

メルカリではBe a Proという、1人1人がプロフェッショナルであることを目指すバリューがあります。そのため、私もインターンシップを通して、自分の持っている最大の価値を出せるよう挑戦しました。たとえば、特に今回新たに作成したFalcoの/proc/[pid]/environファイルからの環境変数読み出し検知ルールは、過去に自分が作問したCTF問題(Ironhand)から着想を得たもので、自分の持つ知識を使って、プロフェッショナルとして新たな価値を作ることに取り組みました。その結果、Falcoを始めとして9件のPull Requestを作成しメルカリの中にとどまらずKubernetesセキュリティの向上に寄与するという仕事ができ、エンジニアとして成長できたと感じています。

まとめ

安心安全なサービスを提供するという目的のために必要なことを見通しながらプロフェッショナルとしてセキュリティ対策を固めるという実りのある経験ができました。今回のインターンシップにあたってメンターをしていただいた末澤裕希(@rung)さん、Pull RequestやIssueの対応をしていただいたFalcoチーム、サポート対応および情報交換をしていただいたSysdig及びSCSKの方々、外部の有識者としてKubernetesセキュリティについて情報交換をしていただいた長谷川千広さん、森田浩平(@mrtc0)さんをはじめ、ご協力いただいたみなさまに感謝します。

参考文献

Threat matrix for Kubernetes – Microsoft Security
MITRE ATT&CK
Containers Matrix – MITRE ATT&CK
How to Bypass Falco – mrtc0

  • X
  • Facebook
  • linkedin
  • このエントリーをはてなブックマークに追加