TCP SACK パニック - カーネルの脆弱性 - CVE-2019-11477、CVE-2019-11478、および CVE-2019-11479

Public Date: June 17, 2019, 09:57
更新 June 20, 2019, 20:33 - Chinese, Simplified 英語 Korean
Resolved 状態
Important Impact

Insights vulnerability analysis

View exposed systems

概要

Linux カーネルによる TCP ネットワーキングの処理で、関連する 3 つの不具合が見つかりました。  最も深刻な脆弱性の場合、リモートの攻撃者は影響を受けるソフトウェアを実行しているシステムでカーネルパニックを引き起こすことができ、その結果、システムの可用性に影響します。

この問題には複数の CVE が割り当てられました。CVE-2019-11477 の重大度は 重要な影響 と判断され、CVE-2019-11478 および CVE-2019-11479中程度の影響 と判断されました。 

そのうちの 2 つは、MSS (最大セグメントサイズ、Maximum Segment Size) と SACK (選択的確認応答、Selective Acknowledgement) パケットが関連する不具合で、3 つ目の不具合は MSS のみに関連します。

これらの問題は、軽減策またはカーネルパッチを適用して修正されます。  軽減策の詳細と RHSA アドバイザリーへのリンクは、「解決策」タブを参照してください。

問題の詳細と背景情報

関連する 3 つの不具合は、サイズの小さい MSS を扱う TCP の SACK (選択的確認応答、Selective Acknowledgement) パケットに対する Linux カーネルの処理で発見されました。現時点では、影響の範囲はサービス拒否 (DoS) に限定されると見られています。現在、特権の昇格や情報漏えいの疑いはありません。

この記事に記載されている軽減策を使用することができますが、低い値の MSS を必要とする正当なソースからトラフィックを適切に送信できなくなる可能性があり、システムのパフォーマンスに影響する可能性があります。システムの環境に適する軽減策を判断してから、軽減策を適用してください。

SACK とは

TCP の SACK (選択的確認応答、selective acknowledgement) とは、正常に受け入れられたすべてのセグメントに関して、データの受信側が送信側に通知できる仕組みのことです。これにより、送信側は「既知の適切な」セットに欠けているストリームのセグメントを再送信することができます。TCP の SACK が無効である場合、完全なストリームを再送信するには、はるかに大きな再送信のセットが必要になります。

MSS とは 

MSS (最大セグメントサイズ、maximum segment size) とは、再構築された TCP セグメントに含まれるデータの合計量を指定するパケットの TCP ヘッダーのパラメーターセットです。
パケットが異なるルートで送信されると、断片化される可能性があるため、ホストが処理可能な最大 IP データグラムペイロードサイズと同じ値を MSS として指定する必要があります。MSS の値が大きすぎると、宛先に送信される途中でパケットのストリームが断片化される可能性があります。逆に、パケットが小さいと断片化の可能性は低くなりますが、未使用のオーバヘッドが発生します。


オペレーティングシステムおよびトランスポートとタイプは指定の MSS の値をデフォルトとすることができます。アクセス権限を持つ攻撃者は、パケットの改ざんされた MSS オプションを使用して raw パケットを作成し、この攻撃を実行することができます。

TCP の SACK

TCP はコネクション指向のプロトコルです。2 者が TCP 接続上で通信を行う場合、特定の情報を交換して接続を確立します。この情報には、接続開始の要求 (SYN)、初期シーケンス番号、確認応答番号、接続上で使用する MSS (最大セグメントサイズ、maximum segment size)、SACK (選択的確認応答) を送信および処理するパーミションなどが含まれます。この接続確立プロセスは、3 ウェイハンドシェイクと呼ばれます。

TCP は、セグメントと呼ばれる単位でユーザーデータを送受信します。TCP セグメントは TCP ヘッダー、オプション、およびユーザーデータで構成されます。
TCP セグメンテーション


各 TCP セグメントには SEQ (シーケンス番号、sequence number) と ACK (確認応答番号、acknowledgement number) があります。

これらの SEQ および ACK 番号は、受信側によって正常に受信されたセグメントを追跡するために使用されます。ACK 番号は、受信側が想定する次のセグメントを示します。

例: 上記でユーザー「A」はそれぞれが 100 バイトの 13 個のセグメントで 1 キロバイトのデータを送信します。これは各セグメントの TCP ヘッダーが 20 バイトであるため 13 個になります。受信側では、ユーザー「B」が 1、2、4、6 番のセグメントと 8 から 13 番のセグメントを受信します。3、5、7 番のセグメントは失われ、ユーザー「B」によって受信されません。

ユーザー「B」は ACK 番号を使用して、3 番のセグメントを次に想定していることを示します。これにより、ユーザー「A」は 2 番よりも後のセグメントはすべてユーザー「B」によって受信されていないと解釈します。4、6 番のセグメントと 8 から 13 番のセグメントはユーザー「B」が正常に受信したにも関わらず、ユーザー「A」は 3 番以降のセグメントをすべて再送信します。ユーザー「B」は 3 番以降に受信したセグメントがあることをユーザー「A」に示すことはできません。これにより、ネットワークが非効率に使用されることになります。

SACK (選択的確認応答)

SACK では、ユーザー「B」は TCP オプションフィールドを使用して、正常に受信したすべてのセグメント (1、2、4、6 および 8-13) をユーザー「A」に通知します。そのため、ユーザー「A」は 3、5、および 7 番のセグメントのみを再送信する必要があるため、ネットワークの帯域幅を大幅に節約し、輻輳を回避することができます。

CVE-2019-11477 SACK パニック
SKB (ソケットバッファー):
SKB (ソケットバッファー) は、Linux の TCP/IP 実装で使用される最も中心的なデータ構造です。SKB はネットワークパケットを保持する、バッファーの連結リストです。このようなリストは送信キュー、受信キュー、SACK キュー、再送信キューなどとして機能することが可能です。SKB は、パケットデータをフラグメントとして保持することができます。Linux SKB は最大 17 個のフラグメントを保持することができます。

linux/include/linux/skbuff.h
define MAX_SKB_FRAGS (65536/PAGE_SIZE + 1)  => 17

各フラグメントは、x86 で最大 32KB のデータ (PowerPC では 64KB) を保持します。パケットを送信する場合、そのパケットは送信キューに置かれ、詳細は以下のような制御バッファー構造に保持されます。

    linux/include/linux/skbuff.h
struct tcp_skb_cb {
    __u32       seq;                    /* Starting sequence number */
    __u32       end_seq;    /* SEQ + FIN + SYN + datalen */
    __u32       tcp_tw_isn;
        struct {
                u16 tcp_gso_segs;
                u16 tcp_gso_size; 
        };
    __u8        tcp_flags;  /2* TCP header flags. (tcp[13])  */
    …
}

このうち tcp_gso_segs および tcp_gso_size フィールドを使用してセグメンテーションオフロードの情報をデバイスドライバーに通知します。

セグメンテーションオフロードが有効で、SACK メカニズムも有効である場合、パケットの損失と一部パケットの選択的な再送信により、SKB が tcp_gso_segs によってカウントされる複数のパケットを保持してしまう可能性があります。リストのこのような複数の SKB は、異なる SACK ブロックを効率的に処理するために 1 つにまとめられます。これには、リストの SKB 間でデータを移動します。さらに、データの移動中に SKB のフラグメントが最大数の 17 個に達する可能性があり、tcp_gso_segs パラメーターがオーバーフローして以下の BUG_ON() 呼び出しを引き起こし、該当のカーネルパニックの問題が発生する可能性があります。

static bool tcp_shifted_skb (struct sock *sk, …, unsigned int pcount, ...)
{
...
tcp_skb_pcount_add(prev, pcount);
BUG_ON(tcp_skb_pcount(skb) < pcount);   <= SACK panic
tcp_skb_pcount_add(skb, -pcount);

}

リモートユーザーは、TCP 接続の MSS (最大セグメントサイズ、Maximum Segment Size) を下限の 48 バイトに設定し、改ざんされた SACK パケットのシーケンスを送信することで、この問題を引き起こすことが可能です。MSS の値を最も小さくすると、セグメントごとに 8 バイトのデータのみとなるため、必要な TCP セグメントの数を増やしてすべてのデータを送信します。

謝辞

Jonathan Looney 氏 (Netflix Information Security)

その他の参考資料


RFC-2018 - TCP selective acknowledgments 
How SKB’s work

Netflix (レポーター) のオリジナルレポート


影響を受ける製品


Red Hat Product Security チームは、本件によるセキュリティー上の影響を重要な影響と評価しています。

以下の Red Hat 製品のバージョンが影響を受けます。
直接的な影響を受ける製品

  • Red Hat Enterprise Linux 8
  • Red Hat Enterprise Linux 7
  • Red Hat Enterprise Linux 6
  • Red Hat Enterprise Linux 5
  • Red Hat Atomic Host
  • Red Hat Enterprise MRG 2
  • Red Hat OpenShift Container Platform 4 (RHEL CoreOS)
  • Red Hat OpenShift Online
  • Red Hat OpenShift Dedicated (および依存するサービス)
  • OpenShift on Azure (ARO)
  • Red Hat OpenStack Platform (イメージ同梱カーネル)
  • Red Hat Virtualization (RHV-H)

二次的な影響を受ける製品 (基盤のプラットフォームを更新する必要があります)

  • Red Hat Virtualization (RHV)
  • Red Hat OpenStack Platform
  • Red Hat OpenShift Container Platform 3

Red Hat の Linux コンテナーはカーネルの脆弱性の影響を直接受けませんが、そのセキュリティーはホストカーネル環境の整合性に依存しています。Red Hat では最新バージョンのコンテナーイメージを使用することを推奨します。Red Hat Container Catalog の一部である Container Health Index を使用すると、常に Red Hat コンテナーのセキュリティー状態を確認できます。使用中のコンテナーのプライバシーを保護するには、これらの攻撃に対して (Red Hat Enterprise Linux、CoreOS、Atomic Host といった) コンテナーホストを更新する必要があります。Red Hat はこのユースケース向けに更新された Atomic Host をリリースする予定です。


該当の CVE の影響を受ける Red Hat 製品


CVE-2019-11477
重要な影響
CVE-2019-11478
中程度の影響
CVE-2019-11479
中程度の影響
RHEL 8 (kernel、kernel-rt)影響あり - すべてのアクティブなストリームを修正します影響あり - すべてのアクティブなストリームを修正します影響あり - すべてのアクティブなストリームを修正します
RHEL 7 (kernel、kernel-rt)影響あり - すべてのアクティブなストリームを修正します影響あり - すべてのアクティブなストリームを修正します影響あり - すべてのアクティブなストリームを修正します
RHEL 6影響あり - すべてのアクティブなストリームを修正します影響あり - すべてのアクティブなストリームを修正します影響あり - すべてのアクティブなストリームを修正します
RHEL 5 影響なし影響あり (wontfix、サポート範囲外)影響あり (wontfix、サポート範囲外)

問題の詳細と背景情報

以下の 3 つの不具合が報告されています。不具合別の簡単な説明とその影響を以下に示します。

CVE-2019-11477

Linux カーネルは、16 ビット幅の TCP_SKB_CB(skb)->tcp_gso_segs での整数オーバーフローに対して脆弱です。リモートの攻撃者がこの問題を悪用すると、システムをクラッシュし、DoS (サービス拒否) 攻撃を実行することができます。


CVE-2019-11478

Linux カーネルは、攻撃者が TCP 再送信キューを断片化するよう改ざんされた SACK のシーケンスを送信できる不具合に対して脆弱です。攻撃者は断片化されたキューをさらに悪用し、同じ TCP 接続に対して受信された後続の SACK に対して連結リストを悪用できるようになります。 これにより、CPU が時間を過剰に費やして、リストの再構築を試みるため、サービス拒否 (DoS) が発生します。 


CVE-2019-11479    

Linux カーネルは、攻撃者が MSS の値が低い改ざんされたパケットを送信してリソースを過剰に消費させることができる不具合に対して脆弱です。攻撃者は、Linux カーネルを強制し、応答を複数の TCP セグメントに分割し、各セグメントに 8 バイトのデータのみが含まれるようにすることが可能です。これにより、同じデータ量を送信する必要のある帯域幅が大幅に広がります。さらに、追加のリソース (CPU および NIC の処理能力) を消費します。これには、攻撃者の継続的な攻撃が必要で、攻撃者がトラフィックの送信を停止した直後に影響は停止します。 この攻撃が継続される間、システムのパフォーマンスは低下するため、一部のユーザーでサービス拒否 (DoS) が発生します。


脆弱性の診断

以下の診断スクリプトを使用して、現在ご使用のシステムにこの不具合による脆弱性が存在するかどうかを判断します。正規のスクリプトであることを確認する場合は GPG 分離署名 もダウンロードします。

システムの脆弱性の判断

現在のバージョン: 1.0

対処方法

影響のあるバージョンの Red Hat 製品をご使用のお客様は、エラータが入手可能になり次第、該当製品を更新することが強く推奨されます。利用可能な更新を早急に適用し、適切であると思われる軽減策を有効にしてください。  

Red Hat Enterprise Linux 7 以上のサポートされるバージョンを実行しているお客様は、kptach を利用できます。kpatch を取得するには、サポートケースを作成してください。

kpatch に関する詳細は、Is live kernel patching (kpatch) supported in RHEL 7 and beyond? を参照してください。

影響を受ける製品の更新

製品名パッケージアドバイザリー/更新
Red Hat Enterprise Linux 8 (z-stream)kernelRHSA-2019:1479
Red Hat Enterprise Linux 8kernel-rtRHSA-2019:1480
Red Hat Enterprise Linux 7 (z-stream)kernelRHSA-2019:1481
Red Hat Enterprise Linux 7kernel-rtRHSA-2019:1486
Red Hat Enterprise Linux 7.5 Extended Update Support [1]kernelRHSA-2019:1482
Red Hat Enterprise Linux 7.4 Extended Update Support [1]kernelRHSA-2019:1483
Red Hat Enterprise Linux 7.3 Update Services for SAP Solutions, & Advanced Update Support [2]、[3]kernelRHSA-2019:1484
Red Hat Enterprise Linux 7.2 Update Services for SAP Solutions, & Advanced Update Support [2]、[3]kernelRHSA-2019:1485
Red Hat Enterprise Linux 6 (z-stream)kernelRHSA-2019:1488
Red Hat Enterprise Linux 6.6 Advanced Update Support [2]kernelRHSA-2019:1489
Red Hat Enterprise Linux 6.5 Advanced Update Support [2]kernelRHSA-2019:1490
Red Hat Enterprise Linux 5 Extended Lifecycle Support [5]kernel以下参照
RHEL Atomic Host [4]kernelリスピン保留中
Red Hat Enterprise MRG 2kernel-rtRHSA-2019:1487
Red Hat Virtualization 4virtualization host保留中


[1] このパッチを取得するには 有効な EUS サブスクリプションが必要です。  お持ちのアカウントに有効な EUS サブスクリプションがない場合は、Red Hat の営業部門または営業担当者に お問い合わせ ください。

Red Hat Enterprise Linux Extended Update Support サブスクリプションとは何ですか?

[2] RHEL AUS のパッチを入手するには、アクティブな AUS サブスクリプションが必要です

What is Advanced mission critical Update Support (AUS)?

[3] RHEL E4S/TUS のパッチを取得するには、有効な Update Services for SAP Solutions Add-on または TUS サブスクリプションが必要です

[4] Red Hat Enterprise Atomic Host の更新方法に関する詳細は、「Deploying a specific version fo Red Hat Enterprise Atomic Host」を参照してください。

Red Hat Enterprise Linux 5 Extended Life Cycle Support (ELS) アドオンに関する FAQ

[5] 本問題の重大度と Red Hat Enterprise Linux 5 はサポートライフサイクルであることを踏まえ、RHEL5 は対象外となります。 利用可能なアップグレードパスやオプションについては、Red Hat サポートにお問い合わせください。

軽減策

CVE-2019-11477 および CVE-2019-11478 の問題を軽減するには、脆弱なコンポーネントを無効にするか (オプション 1)、iptables を使用して脆弱性の悪用が可能な MSS を持つ接続を切断します (オプション 2)。


オプション 1
新たに確立されたすべての TCP 接続に対し、SACK をシステム全体で無効にします。 


# echo 0 > /proc/sys/net/ipv4/tcp_sack

または

# sysctl -w net.ipv4.tcp_sack=0

このオプションは、SACK を無効にしますが、エラーの発生時にストリームを適切に完了するためにより広い帯域幅が必要になります。
このオプションを再起動後も維持するには、/etc/sysctl.d/ に以下の内容が含まれるファイル (例: /etc/sysctl.d/99-tcpsack.conf) を作成します。

# CVE-2019-11477 & CVE-2019-11478
net.ipv4.tcp_sack=0

Red Hat OpenShift Container Platform (OCP) 4.x では、ノードチューニングオペレーターを使用するとすべてのノードで sysctl 設定を永続化することができます。OCP 4.1 のデフォルトインストールでは、sysctl を openshift のデフォルト tuned プロファイルに追加すると、この設定をすべてのノードに適用することができます。

$ oc edit tuned/default -n openshift-cluster-node-tuning-operator
...
spec:
  profile:
  - data: |
      [main]
      summary=Optimize systems running OpenShift (parent profile)
      ...
      [sysctl]
      net.ipv4.tcp_sack=0
      ...
      name: openshift


 詳細は、製品のドキュメントを参照してください。

オプション 2 は CVE-2019-11477CVE-2019-11478、および CVE-2019-11479 の問題を軽減します。そのために、MSS の値が低い新規接続を回避します。

Red Hat Enterprise Linux 7 および 8 のデフォルトのファイアウォールは firewalld です。 firewalld を使用する MSS の値が低い新しい接続を回避するには、以下のコマンドを使用します。

# firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -p tcp --tcp-flags SYN SYN -m tcpmss --mss 1:500 -j DROP
# firewall-cmd --permanent --direct --add-rule ipv6 filter INPUT 0 -p tcp --tcp-flags SYN SYN -m tcpmss --mss 1:500 -j DROP
# firewall-cmd --reload
# firewall-cmd --permanent --direct --get-all-rules

この firewall-cmd コマンドは、システム再起動後も維持されます。
Red Hat Enterprise Linux のいずれかバージョンで従来の iptables によるファイアウォールを使用している場合、iptables の同等のコマンドは次のようになります。

# iptables -I INPUT -p tcp --tcp-flags SYN SYN -m tcpmss --mss 1:500 -j DROP
# ip6tables -I INPUT -p tcp --tcp-flags SYN SYN -m tcpmss --mss 1:500 -j DROP

# iptables -nL -v
# ip6tables -nL -v

このオプションは、MSS の値が 1 から 500 までの接続を拒否します。有効であるとみられる接続も拒否される可能性があるため、注意してください。この軽減策は、net.ipv4.tcp_mtu_probing が無効である場合に動作します。

iptables コマンドがシステム再起動後も維持されるようにするには、ソリューションの手順を参照してください。

Ansible Playbook

Ansible Playbook の disable_tcpsack_mitigate.yml を以下に提供します。この Playbook は、SACK を無効にし、変更を永続化します。この Playbook を使用するには、SACK を無効にするホストを HOSTS extra var で指定します。

ansible-playbook -e HOSTS=web,mail,ldap04 disable_tcpsack_mitigate.yml

正規の Playbook であることを確認するために、GPG 分離署名をダウンロード することができます。

軽減策の自動化

現在のバージョン: 1.0

Comments