TCP SACK PANIC - 커널 보안 취약점 - CVE-2019-11477, CVE-2019-11478 & CVE-2019-11479
갱신됨
이 정보가 도움이 되었나요?
요약
Linux 커널의 TCP 네트워크 데이터 처리와 관련된 세 가지 보안 취약점이 발견되었습니다. 가장 심각한 보안 취약점의 경우 원격 공격자는 영향을 받는 소프트웨어를 실행하는 시스템에서 커널 패닉을 유발하여 결과적으로 시스템의 가용성에 영향을 줄 수 있습니다.
이 문제는 여러 CVE로 지정되어 있습니다. CVE-2019-11477은 중요한 영향을 미치는 것으로 평가되고 있으며 CVE-2019-11478 및 CVE-2019-11479은 중간 정도의 영향을 미치는 것으로 평가되고 있습니다.
처음 두 가지 문제는 MSS (Maximum Segment Size)와 결합된 SACK (Selective Acknowledgement) 패킷과 관련이 있으며 세 번째 문제는 MSS에만 관련되어 있습니다.
이러한 문제는 완화 조치 또는 커널 패치를 적용하여 수정됩니다. 완화 조치 정보 및 RHSA 권고에 대한 링크는 해결 방법 탭에서 확인하실 수 있습니다.
세부 사항 및 배경 정보
크기가 작은 MSS 값을 처리하는 TCP SACK (Selective Acknowledgement) 패킷에 대한 Linux 커널의 처리에서 세 가지 관련 보안 취약점이 발견되었습니다. 현재 이러한 보안 취약점의 영향은 서비스 거부 (DoS)를 유발하는 것으로 한정되며 권한 상승 또는 정보 유출이 의심되지는 않습니다.
이 문서에 설명되어 있는 완화 조치를 사용할 수는 있지만 전송을 위해 더 작은 MSS 값을 요구하는 정상적인 네트워크 작동 및 시스템의 성능에 영향을 미칠 수 있습니다. 시스템 환경에 적합한 지 평가한 후 완화 조치를 적용하십시오.
SACK (Selective Acknowledgement) 란 무엇입니까?
TCP SACK (Selective Acknowledgement)은 데이터 수신자가 성공적으로 수락된 모든 데이터 세그먼트에 대해 보낸 사람에게 알리는 승인 메커니즘입니다. 이를 통해 보낸 사람이 '정상/양호한 (known good)' 데이터에서 누락된 데이터 스트림 세그먼트를 재전송할 수 있습니다. TCP SACK이 비활성화된 경우 전체 스트림을 재전송하려면 훨씬 더 큰 재전송 세트가 필요합니다.
MSS란 무엇입니까?
MSS (Maximum Segment Size)는 재구성된 TCP 세그먼트에 포함된 총 데이터 양을 지정하는 패킷의 TCP 헤더에 설정된 매개 변수입니다.
패킷이 다른 경로를 통해 전송되면 여러 데이터 세그먼트로 분리될 가능성이 있기 때문에 호스트가 처리할 수있는 최대 IP 데이터 그램의 페이로드 크기와 동일한 값으로 MSS를 지정해야 합니다. MSS 값이 너무 크면 목적지로 전송되는 도중에 패킷 스트림이 여러 데이터 세그먼트로 분리될 수 있습니다. 반대로 작은 패킷의 경우 여러 데이터 세그먼트로 분리될 가능성은 낮지만 미사용의 오버 헤드가 발생할 수 있습니다.
운영 체제 및 전송 유형은 특정 MSS 값을 기본적으로 사용할 수 있습니다. 액세스 권한을 가진 공격자는 패킷에 변조된 MSS 옵션을 사용하여 시스템을 공격하는 원시 패킷을 만들 수 있습니다.
TCP SACK:
TCP는 연결 지향 프로토콜입니다. 두 당사자가 TCP 연결을 통해 통신하려는 경우 연결 시작 요청 (SYN), 초기 시퀀스 번호, 승인 번호, 이 연결을 통해 사용할 최대 세그먼트 크기 (MSS), SACK 전송 및 처리하는 등의 작업을 수행합니다. 이 연결 설정 프로세스를 3 방향 핸드 셰이크라고합니다.
TCP는 세그먼트 (Segment)라는 단위로 사용자 데이터를 송수신합니다. TCP 세그먼트는 TCP 헤더, 옵션, 사용자 데이터로 구성됩니다.
각 TCP 세그먼트에는 SEQ (Sequence Number, 시퀀스 번호)와 ACK (Acknowledgement Number, 승인 번호)가 있습니다.
이 SEQ 및 ACK 번호는 수신자가 성공적으로 수신한 세그먼트를 추적하는 데 사용됩니다. ACK 번호는 수신자가 수신을 예상한 다음 세그먼트를 나타냅니다.
예: 위에서 사용자 'A'는 각각 100 바이트의 13개 세그먼트를 통해 1 KB 데이터를 전송합니다. 각 세그먼트는 TCP 헤더가 20 바이트이므로 13 개의 세그먼트가 필요합니다. 수신 측에서 사용자 "B"는 1, 2, 4, 6, 8 -13 세그먼트를 수신하고 3, 5, 7 세그먼트가 손실되어 사용자 "B"에 수신되지 않습니다.
ACK 번호를 사용하여 사용자 "B"는 세그먼트 3을 수신할 것으로 예상하고 사용자 'A'는 세그먼트 2 이후에 사용자 "B"가 데이터를 수신하지 않은 것으로 해석합니다. 세그먼트 4, 6 및 8- 13이 사용자 'B'에 의해 성공적으로 수신되었더라도, 사용자 "A"는 3 번 이후의 모든 세그먼트를 다시 전송하게 됩니다. 사용자 "B"는 이러한 정보를 사용자 "A"에게 알릴 수 없습니다. 이로 인해 네트워크가 비효율적으로 사용되게 됩니다.
SACK (Selective Acknowledgement)
위의 문제를 극복하기 위해 SACK (Selective Acknowledgement) 메커니즘이 고안되어 RFC-2018에 정의되어 있습니다. 위의 예에서 사용자 'B'는 SACK를 통해 TCP 옵션 필드를 사용하여 사용자 'A'에게 모든 세그먼트 (1,2,4,6,8-13)가 성공적으로 수신되었음을 알립니다. 따라서 사용자 'A'는 세그먼트 3, 5, 7만 재전송하면 되므로 네트워크 대역폭을 절감하고 혼잡을 방지할 수 있습니다.
CVE-2019-11477 SACK 패킷:
소켓 버퍼(SKB):
SKB (Socket Buffer, 소켓 버퍼)는 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 블록을 효율적으로 처리하기 위해 하나로 통합됩니다.이 경우 목록에서 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 정보 보안)
참고 자료
RFC-2018 - TCP selective acknowledgments
How SKB’s work
영향을 받는 제품
Red Hat 제품 보안팀은 본 취약점이 이번 업데이트에서 중요한 영향을 미치는 것으로 평가하고 있습니다.
다음의 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를 출시할 예정입니다.
영향을 받는 Red Hat 제품 (CVE로 분류)
CVE-2019-11477 중요 | CVE-2019-11478 중간 | CVE-2019-11479 중간 | |
RHEL 8 (kernel, kernel-rt) | 영향을 받음 - 모든 활성 스트림을 수정 | 영향을 받음 - 모든 활성 스트림을 수정 | 영향을 받음 - 모든 활성 스트림을 수정 |
RHEL 7 (kernel, kernel-rt) | 영향을 받음 - 모든 활성 스트림을 수정 | 영향을 받음 - 모든 활성 스트림을 수정 | 영향을 받음 - 모든 활성 스트림을 수정 |
RHEL 6 | 영향을 받음 - 모든 활성 스트림을 수정 | 영향을 받음 - 모든 활성 스트림을 수정 | 영향을 받음 - 모든 활성 스트림을 수정 |
RHEL 5 | 영향을 받지 않음 | 영향을 받음 (지원 범위를 벗어나서 수정되지 않음) | 영향을 받음 (지원 범위를 벗어나서 수정되지 않음) |
세부 사항 및 배경 정보
다음과 같은 세 가지 보안 취약점이 보고되었습니다. 다음은 각 보안 취약점과 그 영향에 대한 간단한 설명입니다.
CVE-2019-11477
Linux 커널은 16 비트의 TCP_SKB_CB(skb)->tcp_gso_segs에서 정수 오버플로에 취약합니다. 원격 공격자가 이 취약점을 악용하면 시스템을 중단시키고 DoS (서비스 거부) 공격을 유발할 수 있습니다.
CVE-2019-11478
공격자는 Linux 커널의 보안 취약점을 악용하여 변조된 SACK 시퀀스를 전송하고 TCP 재전송 큐를 세그먼트로 분할할 수 있습니다. 공격자는 세그먼트화된 큐를 악용하여 동일한 TCP 연결에 대해 수신된 후속 SACK 패킷을 처리하는 동안 시스템이 많은 양의 리소스를 소비하게 합니다. 이로 인해 CPU가 데이터 열을 다시 작성하는데 시간을 과도하게 소비하게 되어 DoS (서비스 거부) 문제가 발생할 수 있습니다.
CVE-2019-11479
공격자는 Linux 커널의 보안 취약점을 악용하여 MSS 값이 낮은 변조된 패킷을 전송하여 시스템에서 리소스를 과도하게 소비하여 처리하도록 할 수 있습니다. 공격자는 Linux 커널이 응답을 8 바이트의 데이터만 포함하는 여러 개의 TCP 세그먼트로 분할하도록 할 수 있습니다. 이로 인해 동일한 양의 데이터를 처리하는데 필요한 대역폭이 크게 증가합니다. 또한 추가 리소스 (CPU와 NIC의 처리 기능)을 소비해야 합니다. 여기에는 공격자의 지속적인 공격이 필요하며 공격자가 트래픽 전송을 중단한 직후에 영향이 종료됩니다. 이 공격이 계속 진행되는 동안 시스템의 사용 가능한 리소스가 줄어들고 일부 사용자에 DoS (서비스 거부)가 발생할 수 있습니다.
취약점 진단
진단 스크립트를 사용하여 시스템에 현재 보안 결함이 있는지 확인합니다. 정규 스크립트임을 확인하려면 GPG 서명을 다운로드하십시오.
대응 방법
영향을 받는 Red Hat 제품 버전을 사용 중인 모든 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) | kernel | RHSA-2019:1479 |
Red Hat Enterprise Linux 8 | kernel-rt | RHSA-2019:1480 |
Red Hat Enterprise Linux 7 (z-stream) | kernel | RHSA-2019:1481 |
Red Hat Enterprise Linux 7 | kernel-rt | RHSA-2019:1486 |
Red Hat Enterprise Linux 7.5 Extended Update Support [1] | kernel | RHSA-2019:1482 |
Red Hat Enterprise Linux 7.4 Extended Update Support [1] | kernel | RHSA-2019:1483 |
Red Hat Enterprise Linux 7.3 Update Services for SAP Solutions, & Advanced Update Support [2], [3] | kernel | RHSA-2019:1484 |
Red Hat Enterprise Linux 7.2 Update Services for SAP Solutions, & Advanced Update Support [2], [3] | kernel | RHSA-2019:1485 |
Red Hat Enterprise Linux 6 (z-stream) | kernel | RHSA-2019:1488 |
Red Hat Enterprise Linux 6.6 Advanced Update Support [2] | kernel | RHSA-2019:1489 |
Red Hat Enterprise Linux 6.5 Advanced Update Support [2] | kernel | RHSA-2019:1490 |
Red Hat Enterprise Linux 5 Extended Lifecycle Support [5] | kernel | 아래 참조 |
RHEL Atomic Host [4] | kernel | 보류 중 |
Red Hat Enterprise MRG 2 | kernel-rt | RHSA-2019:1487 |
Red Hat Virtualization 4 | virtualization host | RHSA-2019:1594 |
[1] 이 패치에 액세스하려면 유효한 EUS 서브스크립션이 필요 합니다. 사용 계정에 유효한 EUS 서브스크립션이 없을 경우 보다 자세한 내용은 Red Hat 영업팀 또는 해당 지역 영업 담당자에게 문의하시기 바랍니다.
Red Hat Enterprise Linux Extended Update Support 서브스크립션이란?
[2] RHEL AUS에서 이러한 패치에 액세스하려면 유효한 AUS 서브스크립션이 필요합니다.
AUS (Advanced mission critical Update Support)란 무엇입니까?
[3] RHEL E4S / TUS에서 이러한 패치에 액세스하려면 유효한 SAP 솔루션 용 애드온 서비스 또는 TUS 서브스크립션이 필요합니다.
[4] Red Hat Enterprise Atomic Host 업데이트 방법에 대한 자세한 내용은 Deploying a specific version of Red Hat Enterprise Atomic Host에서 참조하십시오.
FAQ: Red Hat Enterprise Linux ELS (Extended Life Cycle Support) 애드온
[5] 현재 Red Hat Enterprise Linux 5는 지원 라이프 사이클 기간에 있지만 문제의 심각도에 따라 RHEL5는 지원 대상에서 제외됩니다. 사용 가능한 업그레이드 경로 및 옵션에 대한 내용은 Red Hat 지원에 문의하십시오.
완화 방법
CVE-2019-11477 및 CVE-2019-11478 문제를 완화하기 위해 취약한 구성 요소를 비활성화하거나 [옵션 #1] iptables를 사용하여 취약점을 악용할 수 있는 MSS(Minimum Segment Size)를 갖는 연결을 해제합니다 [Option #2].
옵션 #1
시스템 전체에서 새로 설정된 모든 TCP 연결에 대한 SACK(Selective Acknowledgement) 기능을 비활성화합니다.
# echo 0 > /proc/sys/net/ipv4/tcp_sack
또는
# sysctl -w net.ipv4.tcp_sack=0
이 옵션은 SACK(Selective Acknowledgement) 기능을 비활성화하지만 오류가 발생할 때 데이터 스트림을 다시 보내는데 필요한 대역폭을 늘릴 수 있습니다.
재부팅 후에도 이 설정을 유지하려면 /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’ 기본 조정 프로파일에 추가하여 이 설정을 모든 노드에 적용할 수 있습니다.
$ 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는 새 연결에서 작은 MSS 값 사용을 비활성화하여 CVE-2019-11477, CVE-2019-11478, CVE-2019-11479 문제를 완화할 수 있습니다.
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
이 옵션은 1에서 500까지의 모든 MSS 값에 대한 연결을 거부합니다. 이로 인해 유효한 연결이 거부될 수도 있습니다. 이 완화 방법은 net.ipv4.tcp_mtu_probing이 비활성화된 경우에 작동합니다.
시스템 재부팅 후에도 iptables 명령이 유지되도록 하려면 다음 문서를 참조하십시오.
Ansible Playbook
다음에는 Ansible Playbook (disable_tcpsack_mitigate.yml)이 제공됩니다. 이 Playbook은 SACK 기능을 비활성화하고 변경 내용을 영구 적용합니다. 이 Playbook를 사용하는 경우 HOSTS extra var를 사용하여 SACK 기능을 비활성화할 호스트를 지정해야 합니다.
ansible-playbook -e HOSTS=web,mail,ldap04 disable_tcpsack_mitigate.yml
Playbook의 진위 여부를 확인하려면 GPG 분리 서명을 다운로드하십시오.
Comments