Kubernetesはしっかり理解しないとセキュリティを担保するのは難しい
EKS(Amazon)やGKE(Google)が出てきたことでコンテナベースのインフラも一般的になって来ました。
サイバー攻撃を最小化する仕組みも多数備えていることも知られています。しかし、それは十全に機能を活用できた場合で、実際は理解が曖昧なままなんとなく使ってしまっている企業も少なくないのが現状です。
Kubernetesベースのコンテナ環境のリスクを正しく把握しコントロールするためにもまずは簡単にコンテナの基礎から確認していきましょう。
Kubernetesとはコンテナ化されたアプリを管理するためのツールでありコンテナオーケストレーションツールと呼ばれます。
Kubernetesを用いることでコンテナの死活管理やオートスケールなどを含むリソースマネージメントができることが期待されます。
Kubernetesにおいてコンテナを管理する場所がコントロールプレーン、コンテナが動く場所がデータプレーンと呼びます。
軸足を決めた方がよいかと思いますのでAWS環境をベースにセキュリティをどのように考えて行けば良いかに付いて書いていきたいと思います。
EKSはElastic Kubernetes Serviceの略でKubernetesのマネージメントサービスです。
役割として分類するとレジストリ、オーケストレーション、コンピューティングとなりすが
AWSではそれぞれレジストリをECR、オーケストレーションをECS/EKS、コンピューティングをFargate/EC2で実現します。
AWS App Runnerはコードシリーズの統合のようにレジストリ、オーケストレーション、コンピューティングの一連を統合的にマネージドサービスとなります。
コンテナセキュリティのセキュリティ標準であるNIST SP800-190ではどんなセキュリティが要求されるのか
さてコンテナセキュリティのセキュリティ標準であるNIST SP800-190ですが以下のような構成になっています。
1.イメージのリスク
2.レジストリのリスク
3.オーケストレータのリスク
4.コンテナのリスク
5.ホストOSのリスク
そして、ここに書かれているのは「イメージに接続文字列、SSH 秘密鍵、X.509 秘密鍵といった平文の秘密情報を記載するな」といったものや「レジストリへのアクセスには認証を設けましょう」など、CVEなどの脆弱性以前の「基礎的な」リスクが記載されています。(OWASP IoT Top10でも同じ空気を感じたような)
まずはNIST SP800-190に記載されている「基礎的な」項目を網羅した上で日々に発生する脆弱性情報への対処へとレベルアップしていきましょう。
残念ながら大半のコンテナ環境のサイバー攻撃はKubernetesの脆弱性以前にそもそも脆弱な設定や設計が原因となっています。
コンテナには「一度構築した本番環境には更新やパッチの提供などの変更を加えず稼働させる」というImmutable Infrastructureという思想がありますが、
パッチ対応しないという意味ではなく「本番の再現環境で更新・パッチの提供・テストを実施し、問題がないと判断すれば、本番環境と入れ替える」運用をするということです
EKS,ECS階層も網羅されていて階層ごとに対応をまとめると以下のようになります。
Layer | EKS | ECS | Description | NIST SP800-190 |
---|---|---|---|---|
Code | ○ | ○ | ソースや設定のバグ | ○ |
Container | ○ | ○ | コンテナランタイム設計のバグ、イメージ自体のバグ | ○ |
Pod | - | ○ | ネットワークやボリュームの設計 | ○ |
Node | - | ○ | コンテナの稼働するマシンの分離 | ○ |
Namespace | - | ○ | 名前空間の管理の不備 | ○ |
Cluster | - | ○ | クラスタコンポーネントのバグ | ○ |
Cloud | - | ○ | ハードの障害、物理設計のバグ | ○ |
実際、脆弱性の発生するセクションとしてはイメージ、レジストリ、オーケストレータ、コンテナで分類しさらにオーケストレータであるKubernetesをコンポーネント単位に分解して理解するとCVE報告単位の脆弱性と合致させることができます。
オーケストレータは分量的に別建てにする必要性があるため、イメージとレジストリの脆弱性を先に解説していきます。
イメージはCVEで報告される脆弱性意外に①平文のシークレット (Embedded clear text secrets)、②信頼性のないイメージの利用 (Use of untrusted images)、③イメージ設定の欠陥 (Image configuration defects)を確認します。
①平文のシークレット (Embedded clear text secrets)
データベースの接続や他のシステムにアクセスするためのSSHの鍵やX.509の証明書といったシークレット情報をイメージに含めてしまっていると悪用される可能性があるという脆弱性です。
シークレット情報はKubernetesのSecretリソースを用いて、コンテナの起動時に環境変数で渡すかファイルとしてマウントする方法をとりましょう。
②信頼性のないイメージの利用 (Use of untrusted images)
信頼性の低いコンテナイメージでは中にマルウエアを含んでいたり、設定がずさんで情報漏洩してしまうなどの脆弱性が想定されます。
信頼のおける組織が出しているイメージであるか、に加えそのイメージをビルドするのに使っているDockerfileが公開されているかも併せて確認するようにしましょう。
③イメージ設定の欠陥 (Image configuration defects)
コンテナ内に特権プロセスを実行されているようなイメージの設定に起因して悪用される可能性があるという脆弱性です。
1コンテナ1プロセス(1サービス)の原則に従っているか見直してみましょう。
Kubernetesのコンポーネントの整理
kubectl(KubernetesのCLIクライアント)
Masterコンポーネント
etcd:リソースの永続化に使われる高信頼分散KVSです
kube-apiserver:リソース情報のCRUD処理を行いリソース情報の管理を担います。
kube-scheduler:新しく作られたPodのノードへの割り当てを行うスケジューラーです。
kube-controller-manager:Replication Controllerなどの各種コントローラーの起動の管理を担います。
Nodeコンポーネント
kubelet:Nodeのメイン処理であるPodの起動・管理を行います。
kube-proxy:各ノードで動作する、Serviceが持つ仮想的なCluster IPを転送するためのネットワークProxyです。
container runtime:コンテナの起動を行います。
Kubernetesのコンポーネントと脆弱性(CVE)情報
Kubernetesのコンポーネントで発見された脆弱性とその脅威を事例(CVE情報)をもとに考えていきましょう。
kube-apiserver(Kubernetesのリソースを管理するAPIサーバー)
リソース情報のCRUD処理を行いリソース情報の管理を担います。
Kubernetesの全てのコンポーネントからの API の受付口となるコンポーネントとなっています。
CVE 2018-1002105
Kubernetes の API エンドポイントにアクセスすることができるユーザであれば、kube-apiserver がリバースプロキシとして動作する際にWebSocketに遷移する際のHTTP Upgrade時に101 Switching Protocolsというステータスのエラーハンドリングがバイパス可能であることを悪用した脆弱性です。etcdの秘密鍵などを入手される可能性があり大変危険です。
脆弱性への理解は修正済みのパッチが公開されている場合、「どう修正しているのか」を確認するのが早道です。しかし、危険性を理解するためにはkube-apiserverの知識を補足しておく必要があります。
①リバースプロキシとしてのkube-apiserver は全ての kubelet API を呼び出し可能
②aggregated API server は kube-apiserver の送ってきた認証の結果を無条件で信用する
if rawResponseCode != http.StatusSwitchingProtocols {
// If the backend did not upgrade the request, finish echoing the response from the backend to the client and return, closing the connection.
klog.V(6).Infof("Proxy upgrade error, status code %d", rawResponseCode)
_, err := io.Copy(requestHijackedConn, backendConn)
if err != nil && !strings.Contains(err.Error(), "use of closed network connection") {
klog.Errorf("Error proxying data from backend to client: %v", err)
}
// Indicate we handled the request
return true
}
kube-proxy(KubernetesのServiceが持つcluster IPへのアクセスをルーティング)
Kubernetesクラスタの各ノードで動作するネットワークプロキシで、ポッド−サービス間の接続を管理する役割を持ちます。
CVE-2020-8558 クラスタに乗っ取りの危険性
sysctlファイルを使って設定されるnet.ipv4.conf.all.route_localnet=1により、ノードと同じLAN上の他のホスト、または実行中のコンテナによって到達可能になる可能性があるという脆弱性です。
やはりCVEの分析は仕組みを理解する近道ですね。
以上です。参考になれば幸いです。