目次
■クラウド&インフラストラクチャ
2022.05.12 2024.03.06 約5分
皆さんはセキュリティについてどういう気持ちをもっていますか?僕は「面倒くさいけど面白い」です。はやくセキュリティなんて意識しなくてもいい時代になればいいのになー常々思っています。ですが、「面倒くさい」だけではありません。攻撃から守ったり、はたまたその防御を突破したりするイタチごっこを深堀りすると、そこにはワクワクする技術や考え方があります。この回ではコンテナや Kubernetes といったこれからのインフラ基盤技術における攻撃例と対策をお話します。また、開発サイクルや組織にどのようにセキュリティを取り入れていけばよいかについても議論できればと思います。近年、DevSecOps やゼロトラストなどの概念が登場していますが、自分たちの組織に適したセキュリティを再考したり、セキュリティへの向き合い方が変わるきっかけになれば幸いです。
「インフラとセキュリティとこれから」について発表します。GMOペパボ セキュリティ対策室所属の森田 康平と申します。「もりたこ」と呼ばれることが多いです。
サービスが数多くあるペパボのセキュリティを横断的に支援して、セキュリティの基盤を作ったり IPA さん主催の学生向けセキュリティイベントに講師として赴き、運営に近いところで活動しています。ブログはこちらで書いています。
今日はコンテナや kubernetes など、今後流行っていく技術のセキュリティについてと、今後組織としてどうセキュリティと向き合っていくのかを解説します。
コンテナのセキュリティについて話します。
コンテナのセキュリティは、2年前にセキュリティ・ミニキャンプで講義をした内容をピックアップして紹介します。
コンテナ・ Linuxコンテナのセキュリティを知るには、仕組み全体を知らないと難しいです。しかしすべて紹介すると時間がないので、本講義では省略します。
コンテナは Linux のセキュリティ機構を利用して、権限やリソースの分離、制御をおこなっています。機能は、PID Namespace や Mount Namespace、そして cgroup や Capability、または seccomp や LSM などがあります。
Infra Study Meetup インフラで私が一番面白いと考えている世界で、宇智朗さん がフルスクラッチでコンテナを作っているので、詳しくは、そちらをご参照ください。もしコンテナに設定の不備がある場合は、ホストの root を取得される可能性があるので、その点も説明します。
コンテナの攻撃シナリオには、いくつかパターンがあります。
たとえば、コンテナのイメージにマルウェアやバックドアが仕込まれているケースやコンテナイメージのなかにあるパッケージの脆弱性が Webアプリケーション経由で悪用されるパターンがあります。
コンテナランタイムの脆弱性や設定の不備、さらには Linux カーネル周りの脆弱性を利用するものもあります。今回は設定不備をメインに触れていきますが、 Webアプリケーションをコンテナで動かしていると、あまりこのレイヤーは意識しないと思います。
たとえば Webアプリケーションに、任意のコードが実行できる脆弱性があった場合、設定不備を利用して、さらなる権限昇格につながる可能性があります。アプリケーションを書いて Dockerコンテナを動かすとなると、この辺りの知識は必須になります。
コンテナの設定不備の対応方法については、コミュニティや機関が策定しているガイドラインを読んでみてください。ガイドラインは CIS Benchmarks や NIST から文書が出ています。
たとえば、CIS Benchmarks は、定められている設定に準拠しているかを検知してくれるツールもあり、セキュアにするためのアプローチの一つです。
「そこまでしないといけないのか」という厳しい項目もありますが、自社あるいは自分たちの組織にとって脅威は何かを考え、攻撃の可能性が高いところや影響が大きいものを優先的に対処していくことが大事です。
ここからはコンテナへの攻撃にフォーカスしていきます。
コンテナには読み書きできてはいけないファイルが多数存在します。これは Docker も LXC もコードを見ればわかりますが、たとえば/proc/kcoreや/proc/sysrq-trigger のようなファイルがあります。procfs や sysfs などのファイルです。
たとえば sysrq-trigger に c という文字列を書き込むと、ホストごとカーネルパニックを起こしてダウンしてしまいます。
読み書きできた場合は、可用性や機密性を脅かすことになるため、ReadOnly にしたり、マスクはそもそもマウントしないといった対応が必要になります。基本デフォルトでされていますが、されていないケースもいくつかあります。
また、/var/run/docker.sock をマウントするケースもあります。このソケットファイルを通して Docker API を叩けてしまうので、リスクになります。ソケットファイルをマウントするときは、気を付けましょう。
続いて、 Capability と seccomp のお話です。 Capability とは皆さんがネットワーク疎通のため、Pingコマンドを使うときに必要となるケースがありますが、そのような Capability も Linuxコンテナには使われています。コンテナでは CAP_SYS_ADMIN や、 CAP_SYS_PTRACE などの Capability が削られています。
これらを付与していない理由は、ホスト側にエスケープできてしまうからです。特にこれらを一気に付与してしまう特権コンテナは非常に危険なので、用法用量を守って使う必要があります。
たとえばマウントシステムコールは、呼び出しに CAP_SYS_ADMIN が必要ですが、もしそれが使えてしまうとホスト側のファイルシステムをマウントできてしまうケースもあります。1箇所でも Capability を間違えると非常に危険になるので、Linuxコンテナでは Capability だけでなく、 seccomp も使って制限しています。
seccomp はレベル1とレベル2がありますが、レベル2はシステムコールの呼び出しや呼び出し時の引数を制限できます。これを使用すれば、マウントシステムコールの禁止を促すことができます。
では、具体的に読み書きしてはいけないファイルのマウントがされていたり、不要な Capability がついてる場合にどのようなことが起こるのかを実演していきます。
共通のテクニックとして call_usermodehelper_exec() 関数というカーネルの関数がありますが、これを使うとコールバックのようにユーザープログラムを実行してくれます。
今回は call_usermodehelper_exec() 関数を使った方法を2つ紹介していきます。call_usermodehelper_exec() 関数は cgroup の release_agent や GDB でよく使うコアファイル生成をするための core_pattern と呼ばれるファイルでも使われています。
では、実際に紹介していきます。
まず、uevent_hlper を使った方法の紹介をします。詳しくは下記動画をご参照ください。
続いて、cgroup release_agent を使った方法の紹介をします。詳しくは下記動画をご参照ください。
最後に、seccomp bypass を使った方法の紹介をします。詳しくは下記動画をご参照ください。
いくつか攻撃例を紹介しましたが、 Linuxコンテナはある機構が突破されても別の機構で防ぎ、緩和する多層防御の形で設計されていることを覚えておいてください。
たとえば seccomp がバイパスされても Capability で防ぎ、AppArmor がバイパスされてもファイルを ReadOnly でマウントしたりマスクして防ぎます。
この多層防御の概念はセキュリティのあらゆる領域で重要です。1つの防御が、破られた場合でも他でカバーできることを意識して、セキュリティ対策をしましょう。
続いて、 Kubernetes のセキュリティを紹介します。
Kubernetes は、コンテナのオーケストレーションツールです。コンテナのセキュリティ内容に加え、 Kubernetes やクラウドプロバイダー特有のセキュリティ内容をどう設定していけばいいかを紹介します。
Kubernetes はコンポーネントが複雑ですが、これにも CIS Benchmark があります。たとえば kube-bench などの自動チェックツールを活用していくのは1つの手です。
また Kubernetes は環境によって認証周りの構成が異なることもあるため、脅威モデルなどを作っていくべきです。
たとえば CNCF では、STRIDE と呼ばれる脅威モデルを使って Kubernetes の信頼境界を認知して、潜在的なセキュリティの問題を特定するワーキンググループがあります。
さらに MITRE社が公開している、脆弱性を悪用した場合に、その攻撃をマトリックスにした、ATT&CK と呼ばれるフレームワークを使えば、 Kubernetes の詳しい攻撃方法を知ることができます。
上記の表の1行目はいわゆるサイバーキルチェーンと呼ばれるものです。実際に攻撃者が偵察したり、初期侵入してからどう動いていくのかを示したアクションアイテムがあり、その下に具体的な方法が書かれています。
上記は Kubernetes の ATT&CK をマイクロソフトが作成して公開した図です。たとえば Privilege Escalation のところからは Privileged Container の使用や hostPath の mount などが書かれています。
さらにいくつかの攻撃例を紹介します。たとえば、 Service Account Token の Pod にマウントされるトークンのサービスアカウントの権限が強いと、 kube-apiserver に対してリクエストを送信されクラスターを操作されてしまいます。
Pod Security Policy は先ほど説明した seccomp や Capability などの設定をします。また、改ざん対策として RootFilesystem は ReadOnly のみにする設定も必要になります。
Kubernetes は etcd といったコンポーネントもあるので、アクセス制御や暗号化などの準備も必要です。
メタデータサービスの話をします。
マネージドな Kubernetes を構築している場合は、169.254.169.254 というメタデータサービスに、Pod からアクセスできてしまいます。
このメタデータサービスに含まれる情報はクラウドプロバイダーによって異なりますが、 EKS であれば IAM のクレデンシャルがあったり、 GKE では Kubernetes の環境変数などが含まれてます。
また、アプリケーションレイヤーから、SSRF(Server Side Request Forgery) と呼ばれる任意の URL にリクエストを送信するような脆弱性がある場合、これを利用し、窃取されるケースがあります。
EKS の場合、curl コマンドで指している URL にアクセスすると、 IAM のアクセスキーや、シークレットアクセスキー、一時的なセッショントークンなどを取得できます。
これに紐付くポリシーは、インスタンス情報の取得や VPC 、SecurityGroupの情報の取得、そして ECR リポジトリのイメージの取得などがあります。イメージを取得し、もしイメージ内にソースコードやクレデンシャルがあれば、さらなる権限昇格につながります。
AWS のドキュメントにもメタデータサービスへのアクセスに関する記載があり、ネットワークポリシーなどを利用してアクセス制御をおこなうように。と書いてあります。
GKE のメタデータには、kubelet で使用される環境変数が存在します。そのなかに kubelet が認証するために必要な証明書を生成する bootstrap で使う証明書が入っています。
kubeadm を使ったことがある方はノードを追加するときにトークンを使ったと思いますが、 GKE では代わりに証明書を使います。
kubelet が認証で使う証明書を作り、 Certificate Signing Request というリソースを作って送信します。そして、kube-controller-manager は common name が system node から始まるものを自動で Approve する機能を利用して、クライアント証明書を取得し、kubelet になりすますことができます。
GKE のドキュメントに「metadata concealment を有効にしない限り、Pod からこれらのシークレットにアクセス可能です」と書かれてます。
このパターンの PoC は広く出回っているので、コマンドの解説はしません。この PoC では Pod の一覧を取得して、その Pod が使っている Secret を取得して、さらなる権限昇格につなげることができます。
実際の事例もいくつか紹介します。
たとえば一番上の Shopify の事例は、アプリケーションレイヤーの SSRF の脆弱性を利用して GKE のメタデータサービスにアクセスされ、Kubernetes API のアクセスに必要な証明書と書かれて権限昇格されたケースです。
他にも Azure Security Center のレポートでは、node への SSH ができる機能を持った管理ツールや、任意のコンテナを実行できるツールやダッシュボードを持つツールに対して、実際に攻撃し、マイニングするようなポットが作られたケースが紹介されています。
Forkwellは「成長し続けるエンジニアを支援する」をコンセプトに勉強会を開催しています。Infra Study Meetupは、インフラ技術の「これまで」と「これから」を網羅的に学ぶイベントです。インフラ技術の各分野に精通した講師を招いた講演や著名エンジニアによる発表を実施しています。
当記事に掲載されている全ての情報は、イベント実施日時点の情報であり、完全性、正確性、時間の経過、あるいは情報の使用に起因する結果について一切の責任を負わないものとします。