サービス拒否攻撃(DoS)とは?
サービス拒否攻撃(DoS)とは、対象となるマシンやネットワークを停止させ、本来のユーザーが利用できなくすることを目的とした攻撃です。DoS攻撃は、標的に大量のトラフィックを送りつけるか、クラッシュを引き起こす情報を送信することでこれを達成します。この種の活動から金銭的利益を得ることは通常ありません。攻撃者が雇われたり報酬を受け取ったりする場合もありますが、その動機は単に、そのウェブアプリケーションやサービスを利用する必要がある正当なユーザーに混乱を引き起こすことにある可能性があります。
サービス拒否攻撃について知っておくべきすべて、具体的にはKubernetesへの影響、侵害の兆候の特定方法、クラウドネイティブツールを用いた防止策などについて、引き続きご覧ください。
学ぶ内容
- サービス拒否攻撃(DoS攻撃)とその仕組みについて
- Kubernetesにおける攻撃の兆候を特定し、その対策を行う方法
- FalcoによるDoS攻撃を防ぐためのベストプラクティス
KubernetesにおけるDoS攻撃とは?
KubernetesにおけるDoS(サービス拒否)攻撃は、多くの場合クラスター外部、つまり外部IPアドレスからの脅威として認識されています。しかし、一部の脆弱性によっては、内部的なDoS攻撃が発生する可能性もあります。実際のところ、すべてのDoS攻撃が意図的に仕掛けられるとは限りません。場合によっては、設定ミスのあるデプロイメントがAPIに大量の不正リクエストを送信し、結果としてノードに過剰な負荷をかけてしまうことがあります。
Kubernetesでは、DoS攻撃への対応方法がやや特殊です。たとえば、AWSのようなクラウドプラットフォーム上で自動スケーリングサービスを利用している場合、この仕組みは技術的にはDoS攻撃に対して比較的堅牢です。これは、新たなトラフィックに対応するために自動的にリソースを追加割り当てできるためです(予期せぬ大規模トラフィック発生時に自動スケーリングが行われる点こそ、Kubernetesがコンテナオーケストレーターとして高く評価される理由の一つです)。しかし、この設計には特有の問題も存在します。
余剰容量がある場合は、トラフィックの急増に応じてワークロードをスケールアップできますが、追加のリソースを確保できない場合(たとえば、クラウドネイティブなワークロードをオンプレミスのデータセンターで実行している場合など)は、システムが最大負荷に達してクラッシュする危険性があります。
また、オートスケーラーによるクラスター運用では、リソースが逼迫し始めると新規ノードを自動的にプロビジョニングできますが、ここにも別の課題があります。アプリケーションを稼働・可用状態に保つためだけに、不要なリソースに対してコストを支払う必要があるのです。新しいノードのスピンアップはAWS全体の支出を増加させるため、AWSの請求額が制御不能に膨れ上がるのを防ぐには、ハードリミットや強制ポリシーを適切に設定することが重要です。
KubernetesにおけるDoS攻撃の兆候をどう特定するか?
まず始めに、KubernetesのContainer Network Interface(CNI)プラグインから検討されることをお勧めいたします。Project Calico、Cilium、Weavenetなど、いくつかの異なるCNIプラグインが存在します。CNIプラグインは、コンテナ化されたワークロードからのすべてのWebリクエスト(ノース/サウスまたはイースト/ウェスト)を処理する役割を担っています。CNIプラグインがなければ、Kubernetes内でのネットワーク接続は成立しません。
通常、IPTablesでアクティビティを確認したり、eBPFを使用してトラフィックリクエストを追跡したりできます。ただし、トラフィック量をより深く理解するためには、PrometheusやGrafanaなどのイベント集約ツールにデータを送信し、相関レポートを作成すべきです。あるいは、Sysdig Secureを使用して、Kubernetes APIサーバーが大量のインバウンドトラフィックを受信しているかどうかを把握することも可能です。このツールは、コンテナ名や特定閾値の超過といったメタデータとの相関分析も行います。
KubernetesにおけるDoS攻撃への備え
1. ワークロードのレート制限設定
Kubernetes環境では、従来、レート制限はイングリッシュレイヤーで適用され、外部ユーザーがクラスターに対して送信できるリクエスト数を制限します。加えて、クラスター内で稼働するマイクロサービスアプリケーション間においても、レート制限の適用をご検討ください。さらに、サービスメッシュやイングリッシュコントローラーに対して適用可能な場合、レート制限を設定することで、ワークロード間の接続に異常な急増が生じ、DoSインシデントを引き起こす可能性を防止できます。これにより、クラスター内の単一ノードが過大な帯域幅を消費する事態を防ぎます。レート制限に関しては、Traefik Proxyが汎用的な方法で制限を定義可能です:
apiVersion: traefik.containo.us/v1alpha1Code language: JavaScript (javascript)
kind: Middleware
metadata:
name: prod-rate-limit
spec:
rateLimit:
average: 30
burst: 50
2. 負荷テストを実施し、アプリケーションのスケーラビリティを把握しましょう。
アプリケーションをステージング環境のクラスターに設定し、トラフィックを投入してテストすることをお勧めします。分散型サービス拒否攻撃(DDoS)に対しては、複数のIPアドレスから同時にトラフィックが流入する可能性があるため、テストがやや困難ですが、この分野を支援するサービスもいくつか存在します。
Speedscaleを使用してリクエストを捕捉し、接続に関わる要素を把握してください。Speedscaleをまだお持ちでない場合は、こちらから無料トライアルにお申し込みいただき、speedctlをダウンロードいただけます。
sh -c "$(curl -Lfs https://downloads.speedscale.com/speedctl/install)"Code language: JavaScript (javascript)
3. CalicoまたはCiliumのNetworkPolicyフレームワークにおいて、eXpress Data Path(XDP)を活用してください
XDPは、DoS/DDoS対策において、パケット処理パイプライン内で理論上可能な限り早い段階で、潜在的に悪意のあるパケットを破棄することを可能にします。カーネルのNIC(ネットワークインターフェースカード)ハードウェアおよびドライバは、XDPオフロードオプションをサポートしています。XDPはソフトウェアスタックの最下層でベアメタルのパケット処理を提供するため、プログラム可能性を損なうことなく高速性を実現するのに理想的です。
apiVersion: projectcalico.org/v3Code language: JavaScript (javascript)
kind: GlobalNetworkPolicy
metadata:
name: dos-mitigation
spec:
selector: apply-dos-mitigation == 'true'
doNotTrack: true
applyOnForward: true
types:
- Ingress
ingress:
- action: Deny
source:
selector: dos-deny-list == 'true'
さらに、ネットワークポリシーを活用することで、どのポッド同士が通信できるかを制限することが可能です。攻撃者が特定のポッドへのアクセス権を取得したとしても、クラスター内の他のポッドから隔離されていれば、ラテラルムーブメントを行うことはできません。
外部からの脅威
公開されているアプリケーションをお持ちの場合、外部からアプリケーションロジックを悪用される可能性が現実的に存在します。たとえアプリケーションがエアギャップ環境でインターネットに公開されていなくても、クラウド内のネットワークポリシー設定ミスだけで、内部に新たな攻撃経路が突然開かれる可能性があります。
残念ながら、Kubernetesには誤設定されたコードを修正する機能はありません。アプリケーションのセキュリティ脆弱性による被害を軽減するため、クラウドネイティブ技術を学ぶことが可能です。侵害された単一コンポーネントが全面的なDDoS攻撃に発展しないようにする方法はいくつかあります:
ネットワークポリシー
ネットワークポリシーを使用して、どのポッドが相互に通信できるかを制限します。攻撃者が特定のポッドへのアクセス権を取得した場合でも、クラスターの他の部分から隔離されていれば、それ以上攻撃を拡大することはできません。
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: deny-app-policy
spec:
namespaceSelector: has(projectcalico.org/name) && projectcalico.org/name not in {"kube-system", "calico-system", "calico-apiserver"}Code language: JavaScript (javascript)
types:
- Ingress
- Egress
egress:
# allow all namespaces to communicate to DNS pods
- action: Allow
protocol: UDP
destination:
selector: 'k8s-app == "kube-dns"'
ports:
- 53
上記の例では、すべての非システムポッドに対してデフォルト拒否の動作を適用しております。また、このポリシーではkube-dnsへのアクセスを許可しているため、各ポッドごとのポリシーでDNSルールを重複して記述する必要がなくなり、設定が簡素化されます。
各ワークロードのセキュリティ設定を監査してください。
Falcoなどのツールは、ユーザーがコンテナにroot権限でシェルアクセスしていないこと、制限されたホストネットワークへのアクセス権限を持たないこと、その他潜在的に不安全な設定がないことを確認します。
- macro: container
condition: container.id != host
- macro: spawned_process
condition: evt.type = execve and evt.dir=<
- rule: run_shell_in_container
desc: a shell was spawned by a non-shell program in a container. Container entrypoints are excluded.
condition: container and proc.name = bash and spawned_process and proc.pname exists and not proc.pname in (bash, docker)Code language: JavaScript (javascript)
output: "Shell spawned in a container other than entrypoint (user=%user.name container_id=%container.id container_name=%container.name shell=%proc.name parent=%proc.pname cmdline=%proc.cmdline)"
priority: WARNING
スクラッチベースイメージを使用してイメージを構築してください。
攻撃者の主な目的は、脆弱なイメージを介して通信を行うことです。攻撃者が脆弱なイメージを介してシステムコールを実行できない場合、攻撃は頓挫します。
脆弱なイメージがパイプライン内で実行されていない限り、攻撃者はそれらのイメージを利用できません。安全なイメージのみを本番環境に導入する方法の一つとして、Open Policy Agent(OPA)のようなアドミッションコントローラーが挙げられます。以下の例では、「ペット」の所有者のみが「ペット」情報を更新できます。さらに、JSON Web Token(JWT)を保持する従業員のみが、既に引き取られたペットを確認できます:
package kubernetes.admission
import future.keywords
deny contains msg if {
input.request.kind.kind == "Pod"
some container in input.request.object.spec.containersCode language: JavaScript (javascript)
image := container.image
not startswith(image, "hooli.com/")
msg := sprintf("image '%s' comes from untrusted registry", [image])
}
内部脅威
前述の通り、すべての脅威が組織外から発生するわけではありません。
コードの単純な設定ミスについて触れましたが、SSHアクセス権を持つ怒り心頭の従業員がデータを不正に流出させたり、強制的にシステム停止を引き起こしたりする可能性もあります。適切な制御が施されていない場合、退職した従業員がSSHキーを介して制御プレーンノードにアクセスできる可能性があります。大企業であれ小規模な技術組織であれ、内部脅威を防ぐための対策を講じることが重要です。最初から適切なセキュリティ慣行を確立することが重要であり、Kubernetes内のロールベースアクセス制御(RBAC)ほど適した手段はありません。
ロールベースのアクセス制御
内部者による脅威を防ぐ最も重要な方法は、認証情報の共有を避けることです。各ユーザーには固有のServiceAccount(Kubernetesにおけるユーザープロファイル)を割り当てるべきです。その後、RBACを用いてKubernetes内のServiceAccountの権限範囲を制限できます。最悪のシナリオは、全てのユーザーがクラスター操作のために同一のServiceAccount認証情報にアクセスできる状態です。従業員が退職した場合、内部脅威が発生した際にクラスターに変更を加えた人物を特定できません。同様に、ユーザーの権限を無効化することもできません。これは組織全体の業務に支障をきたすためです。また、チーム向けに新しいServiceAccountを設定する必要が生じます。クラスター内のあらゆる操作が匿名ではなく、誰が何を行ったかを監査する計画であれば、各ユーザーに境界を設定する必要があります。
クラスターとやり取りする個人ごとに個別の認証情報をプロビジョニングしたら、最小権限の原則を遵守することが重要です。Kubernetesには、誰が何を実行できるかを管理するための組み込みのRBAC(ロールベースのアクセス制御)が備わっています。業務遂行に必要なリソースと操作のみに個別のアクセス権を付与してください。これは悪意のある従業員の場合だけでなく、真のミスを防ぐのにも役立ちます。
GoogleのGKEやAWSのEKSといったマネージドKubernetesサービスでは、通常、事前定義されたIAMプロファイルとKubernetes認証情報が提供されます。また、rbac-managerのようなオープンソースプロジェクトも、RBAC設定を簡潔かつ管理しやすくするのに役立ちます。以下は「default」ネームスペース内で、ポッドへの読み取りアクセス権を付与するために使用できるロールの例です:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: defaultCode language: JavaScript (javascript)
name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["get", "watch", "list"]
Falcoのベストプラクティス
これらのオープンソースツールはすべて、KubernetesにおけるDoS攻撃の防止に相互に置き換えて使用できますが、常にデジタルインシデント対応とフォレンジック(DFIR)のためのルールを設定しておくことが重要です。Falcoは侵害の兆候を特定し、ユーザーが潜在的なDoS攻撃に対して対策を講じることができるようにします。
- 侵害されたワークロードからの予期しないアウトバウンド接続を監視する: Falcoは、Elasticsearchが使用する標準ポート以外のポートからのアウトバウンドネットワークトラフィックを監視できます(例として)。
- macro: outbound
condition: syscall.type=connect and evt.dir=< and (fd.typechar=4 or fd.typechar=6)
- macro: elasticsearch_cluster_port
condition: fd.sport=9300
- rule: elasticsearch_unexpected_network_outbound
desc: outbound network traffic from elasticsearch on a port other than the standard portsCode language: JavaScript (javascript)
condition: user.name = elasticsearch and outbound and not elasticsearch_cluster_port
output: "Outbound network traffic from Elasticsearch on unexpected port (connection=%fd.name)"
priority: WARNING
- 制限されたネームスペースからの外部接続試行を監視する: 企業環境における大半のケースで発生する、内部ネットワーク(RFC1918)への外部接続を監視することが可能です。これには独自のマクロとルールを定義することで対応いたします:
- macro: outbound_corp
condition: >
(((evt.type = connect and evt.dir=<) or
(evt.type in (sendto,sendmsg) and evt.dir=< and
fd.l4proto != tcp and fd.connected=false and fd.name_changed=true)) and
(fd.typechar = 4 or fd.typechar = 6) and
(fd.ip != "0.0.0.0" and fd.net != "127.0.0.0/8") and
(evt.rawres >= 0 or evt.res = EINPROGRESS))
- list: k8s_not_monitored
items: ['"green"', '"blue"']
- rule: kubernetes outbound connection
desc: A pod in namespace attempted to connect to the outer world
condition: outbound_corp and k8s.ns.name != "" and not k8s.ns.label.network in (k8s_not_monitored)Code language: JavaScript (javascript)
output: "Outbound network traffic connection from a Pod: (pod=%k8s.pod.name namespace=%k8s.ns.name srcip=%fd.cip dstip=%fd.sip dstport=%fd.sport proto=%fd.l4proto procname=%proc.name)"
priority: WARNING
- 送信接続における信頼済みドメインと非信頼済みドメインの指定: 下記の例では、信頼済みドメイン名の一覧(sysdig.com、github.com、google.com)を定義しています。これらのドメイン名で解決されないIPアドレスへのネットワーク接続は、すべてポリシーの対象となります。これにより、Falcoに対して許可される接続を明確に指定し、それ以外の接続についてはすべて通知を受けることが可能となります。
- list: trusted_domains
- rule: Unexpected outbound network connection
desc: Detect outbound connections with destinations not on allowed list
condition: >
outbound
and not (fd.sip.name in (trusted_domains))Code language: JavaScript (javascript)
output: Unexpected Outbound Connection
(container=%container.name
command=%proc.cmdline
procpname=%proc.pname
connection=%fd.name
servername=%fd.sip.name
serverip=%fd.sip
type=%fd.type
typechar=%fd.typechar
fdlocal=%fd.lip
fdremote=%fd.rip)
priority: NOTICE
まとめ
クラウドネイティブとKubernetesは、透明性とオープンソースを基盤として構築されています。上記の事例が、DoSインシデントにつながる可能性のある攻撃ベクトル、およびDoS攻撃を軽減するために利用できる無料のオープンソースツールについて、ご理解の一助となれば幸いです。
DoS対策は万能ではありません。したがって、コンテナのライフサイクル全体にわたるリスクを継続的に監視するとともに、以下の点を確実に実施する必要があります:
- ネットワークポリシーがゼロトラストアーキテクチャを適用していること。
- 脆弱性データベースが最新の状態に保たれ、既知の脆弱性を検出できること。
- CI/CDパイプラインの可能な限り早い段階で設定をスキャンし、環境が進化する中でもコンテナセキュリティのベストプラクティスを継続的に遵守できること。
レート制限については、これは必須の対策です。イングリッシュコントローラーのレート制限に加え、コンテナ内のリソース制限も設定可能です。クラウドプロバイダーでの過剰な支出を避けるため、例えばAWSアカウントでは課金上限クォータの設定が可能です。
対策に加え、侵害につながるパターンや行動を特定できることも重要です。Falcoは、C2サーバーからの既知の悪意あるIPへの接続、許可されていないIP/FQDNへの接続、およびアプリケーションアーキテクチャのベースライン設計から外れたポートやプロトコルでの接続について、ユーザーに警告を発することができます。これらの技術をそれぞれ活用することで、クラウドネイティブ技術を用いてDoS攻撃をどのように軽減できるか、十分な理解を得られるはずです。
