Skip to content

QEMU VNC double-cleanup NULL deref (CVE-2023-3354)

Connection limit'i aştığı için ayrıca evict edilen başarısız bir VNC handshake iki kez cleanup edilir ve artık NULL olan bir I/O nesnesini dereference eder — QEMU process'ine karşı uzaktan, kimlik doğrulamasız bir denial of service.

Mechanism

Sınır neden kırılıyor

QEMU'nun yerleşik VNC server'ı (ui/vnc) host QEMU process içinde çalışır ve network'ten bağlantı kabul eder. Her client bağlantısı I/O channel state'ine ve bir TLS handshake state machine'ine sahiptir. İki bağımsız kod path'i bir bağlantıyı yıkmaya karar verebilir: (1) connection-limit check'i — yeni bir client sayıyı bir eşiğin üzerine ittiğinde, QEMU en eski bağlantıyı evict eder; ve (2) handshake-failure path'i — bir TLS handshake hata verdiğinde, QEMU aynı bağlantıyı finish/disconnect eder.

Açık şu ki bu iki path birbirini dışlamaz ve teardown'ın zaten gerçekleştiğini kaydetmez. Hâlâ handshake fazında olan bir bağlantı eviction için seçilebilir, bir kez cleanup edilebilir ve sonra başarısız handshake'i cleanup'ı tekrar tetikleyebilir. İkinci geçiş, birinci geçişin zaten release ettiği ya da NULL'a çevirdiği field'lar üzerinde çalışır ve bir NULL pointer dereference (CWE-476) üreterek QEMU'yu çökertir. İhlal edilen invariant idempotent teardown'dır: bir nesnenin cleanup'ı en fazla bir kez çalışmalı, ya da ikinci giriş bir no-op olacak şekilde guard edilmelidir. VNC port'u kimlik doğrulama öncesi erişilebilir olduğu için, herhangi bir remote peer race'i sürebilir — bu bir guest-privilege sorunu değil, uzaktan kimlik doğrulamasız bir DoS'tur. Genel class için ../primitive/null-pointer-dereference.md'a ve yakından ilişkili double-release pattern'i için ../primitive/double-free.md'a bakın.

Walkthrough

Public Red Hat advisory/Bugzilla'sından ve NVD açıklamasından kavramsal yeniden kurgu; yalnızca mantıksal adımlar.

  1. Bir saldırgan, en az bir peer'ı TLS handshake fazında bırakacak şekilde, yapılandırılmış connection limit'inde oturacak kadar VNC bağlantısı açar.
  2. Yeni bir bağlantı gelir ve sayıyı eşiğin üzerine iter, böylece QEMU en eski (hâlâ handshake eden) bağlantıyı eviction için seçer ve teardown'ını çalıştırır.
  3. Evict edilen bağlantının TLS handshake'i sonra başarısız olur ve handshake-failure path'i aynı bağlantı nesnesi üzerinde teardown'ı ikinci kez çalıştırır.
  4. İkinci teardown, birinci teardown'ın zaten kaldırdığı ya da NULL'a çevirdiği bir I/O watch / channel pointer'ına dokunur, NULL'u dereference eder ve host QEMU process'ini çökertir.
Root cause şekli (açıklayıcı, gerçek patch değil)

Açıklama "improper I/O watch removal in TLS handshake"'i tarif eder. Kavramsal olarak fix, watch removal'ı idempotent yapar / re-entry'yi guard eder:

/* before: unconditional removal can run twice on the same vs */
g_source_remove(vs->ioc_tag);

/* after: only remove if still present, then clear the handle */
if (vs->ioc_tag) {
    g_source_remove(vs->ioc_tag);
    vs->ioc_tag = 0;
}

"When a client connects to the VNC server, QEMU checks whether the current number of connections crosses a certain threshold and if so, cleans up the previous connection. If the previous connection happens to be in the handshake phase and fails, QEMU cleans up the connection again, resulting in a NULL pointer dereference." — Red Hat / NVD CVE-2023-3354

Detection

  • Crash imzası: Backtrace'i VNC teardown / I/O-watch removal path'ine (ui/vnc) düşen bir SIGSEGV ile sonlanan QEMU birincil sinyaldir; core dump'lar ve coredumpctl/systemd journal girdileri bunu yakalar.
  • Connection-churn telemetrisi: Connection limit'ine tekrar tekrar ulaşan, özellikle müzakere ortasında başarısız olan TLS handshake'lere sahip kısa ömürlü VNC bağlantısı patlamaları anormaldir ve VNC server log'larında ve network katmanında görünür.
  • Availability monitoring: VNC port'una gelen trafikle korele beklenmedik guest sonlanması (VM, QEMU process'iyle birlikte ölür).

Mitigation

  • Patch: 8.1.0'da gönderilen ve dağıtımlar tarafından backport edilen (örn. Red Hat RHSA-2023:5094), connection teardown / I/O-watch removal'ı idempotent yapan upstream QEMU fix'ini uygulayın.
  • Maruziyeti kısıtlayın: VNC server'ı public interface'lere bağlamayın. localhost'a bağlayın ve ona bir SSH tunnel ya da bir management VLAN üzerinden erişin ve önüne authentication koyun; untrusted network'lerden erişilebilir kimlik doğrulamasız bir VNC port'u asla çalıştırmayın.
  • Defense in depth: QEMU'yu seccomp (-sandbox on) ve svirt/SELinux confinement altında çalıştırın ve çökmüş guest'leri yeniden başlatan bir supervisor (libvirt) kullanın, böylece tek seferlik bir DoS VM'i kalıcı olarak devre dışı bırakmaz.

References