Kembali ke Blog

Apa yang Kerentanan Container Cloudflare Ajarkan tentang Keamanan Backend Game Multi-Tenant

Diterbitkan pada 25 September 2026
Apa yang Kerentanan Container Cloudflare Ajarkan tentang Keamanan Backend Game Multi-Tenant Dibuat dengan bantuan AI

Ringkasnya

Pelajari kerentanan container Cloudflare yang mengekspos data antar-tenant dan terapkan runbook deteksi-remediasi untuk backend game multi-tenant.

Backend game container Anda membuat VM baru untuk setiap pertandingan, setiap lobby, setiap batch analitik. Saat container itu dimatikan, datanya hilang — benar?

Belum tentu. Pada September 2026, peneliti keamanan Oren Yomtov dari Accomplish menemukan bahwa Cloudflare Containers memiliki kerentanan paparan data lintas-tenant. Blok disk residual dari container yang dihancurkan masih dapat dibaca oleh workload yang tidak terkait di host yang sama. Data yang dipulihkan mencakup struktur direktori, halaman database, dan database SQLite yang lengkap secara struktural.

Jika Anda menjalankan backend game di platform container multi-tenant mana pun, akar penyebab kerentanan ini — konfigurasi penyimpanan Linux bernama skip_block_zeroing di subsistem dm-thin — adalah sesuatu yang perlu Anda pahami. Postingan ini menguraikan apa yang salah, menyediakan runbook deteksi dan remediasi yang dapat Anda terapkan hari ini, serta membahas prinsip-prinsip arsitektur yang mencegah kelas kerentanan ini mencapai data pemain Anda.

Bagaimana Thin Provisioning Menciptakan Paparan Data Lintas-Tenant

Cloudflare Containers menjalankan workload di dalam micro-VM Firecracker pada hardware multi-tenant. Setiap container mendapatkan disk root yang dapat ditulis, didukung oleh Linux device-mapper thin provisioning (dm-thin). Firecracker mengekspos disk ini ke VM tamu sebagai /dev/vdc.

Thin provisioning bekerja dengan menunda alokasi penyimpanan fisik. Saat Anda membuat disk virtual 10 GiB, disk tersebut hampir tidak mengonsumsi ruang fisik. Blok dialokasikan on-demand dari pool bersama saat guest menulis ke region yang sebelumnya belum dipetakan. Pool yang terdampak di Cloudflare menggunakan ukuran blok thin 64 KiB.

Di sinilah kerentanan berada. Saat container dihancurkan, pemetaan thin-volume-nya dihapus, dan blok fisik kembali ke pool bersama untuk digunakan kembali. Pool yang terdampak dikonfigurasi dengan:

skip_block_zeroing

Dengan flag ini, dm-thin melewati zeroing blok yang baru dialokasikan sebelum membuatnya dapat diakses oleh tenant berikutnya. Penulisan 64 KiB penuh menimpa seluruh blok yang didaur ulang. Tetapi penulisan parsial — misalnya 4 KiB — hanya menggantikan region tersebut. Sisa 60 KiB dapat menyimpan data dari pemilik blok sebelumnya.

Ini bukan edge case teoretis. Peneliti memulihkan struktur direktori, halaman database, dan database SQLite lengkap dari blok residual di 18 dari 24 placement produksi dan 20 dari 22 node yang mendasarinya, tersebar di empat benua.

Mengapa Penulisan Parsial Menjadi Vektor Utama

Membaca region yang belum dipetakan dari disk thin baru mengembalikan nol — dm-thin menyajikan nol tanpa mengalokasikan blok fisik. Itu aman. Exploit bekerja karena penulisan kecil memicu alokasi blok 64 KiB yang didaur ulang tanpa melakukan zeroing terlebih dahulu.

Pola serangannya:

  1. Buat container di akun Workers Paid.
  2. Buka /dev/vdc (disk root yang dapat ditulis).
  3. Identifikasi region sejajar 64 KiB yang sesuai dengan ruang kosong ext4.
  4. Tulis satu blok 4 KiB yang sejajar ke setiap region target.
  5. Baca kembali blok 64 KiB penuh.
  6. Periksa hanya 60 KiB yang tidak ditimpa oleh penyerang.

Langkah 4 adalah momen kritisnya. Penulisan 4 KiB menyebabkan dm-thin mengalokasikan blok fisik dari pool bersama. Karena zeroing dinonaktifkan, sisa 60 KiB mungkin berisi data residual dari siapa pun yang sebelumnya memiliki blok tersebut.

Apa yang Sebenarnya Divalidasi oleh Peneliti

Para peneliti menggunakan checksum blok direktori ext4 (fitur metadata_csum) untuk membedakan blok filesystem uji mereka sendiri dari blok asing. Di enam placement produksi:

  • 5.614 blok direktori yang dapat diuji diperiksa
  • 0 blok yang diatribusikan ke filesystem milik peneliti sendiri
  • 2.700 inode direktori asing yang berbeda diidentifikasi melalui analisis checksum

Jenis file yang dipulihkan bukanlah sampah. File-file itu mencakup database SQLite yang bermakna secara struktural — jenis data yang, dalam konteks backend game, dapat berisi save state pemain, token sesi, atau catatan inventaris.

Playbook Deteksi: Menemukan Pemanenan Data Residual di Infrastruktur Anda

Jika Anda mengoperasikan backend game container di infrastruktur multi-tenant, Anda memerlukan dua lapis deteksi: audit konfigurasi dan analisis anomali I/O runtime.

Langkah 1: Audit Konfigurasi dm-thin Anda

Jalankan skrip ini di setiap host yang menjalankan container Anda:

#!/bin/bash
set -euo pipefail

echo "=== dm-thin Pool Configuration Audit ==="
echo ""

# Find all thin pool devices on this host
for pool in $(dmsetup status --target thin-pool 2>/dev/null | awk '{print $1}'); do
    echo "Pool: $pool"
    TABLE=$(dmsetup table "$pool")
    echo "  Full table: $TABLE"
    
    if echo "$TABLE" | grep -q "skip_block_zeroing"; then
        echo "  ⚠️  WARNING: skip_block_zeroing is ENABLED"
        echo "  Recycled blocks may retain previous tenant data."
        echo "  Action: Remove skip_block_zeroing from pool table."
    else
        echo "  ✅ Block zeroing is active (default dm-thin behavior)"
    fi
    echo ""
done

echo "=== Thin-block size check ==="
for pool in $(dmsetup status --target thin-pool 2>/dev/null | awk '{print $1}'); do
    BLOCK_SECTORS=$(dmsetup table "$pool" | grep -oP '\d+ \d+ thin-pool' | awk '{print $1}')
    BLOCK_KB=$((BLOCK_SECTORS * 512 / 1024))
    echo "  Pool $pool: block size = ${BLOCK_KB} KiB"
    if [ "$BLOCK_KB" -le 64 ]; then
        echo "    ⚠️  Small block size amplifies residual data exposure."
        echo "    Larger block sizes reduce the ratio of leftover bytes per partial write."
    fi
done

Jika skip_block_zeroing muncul di mana pun dalam konfigurasi pool Anda, Anda memiliki kelas kerentanan yang sama dengan yang ditambal oleh Cloudflare. Perbaiki segera — jangan menunggu jendela pemeliharaan terjadwal.

Langkah 2: Pantau Tanda Tangan I/O yang Karakteristik

Exploit menghasilkan tanda tangan yang dapat dideteksi: penulisan kecil yang diikuti pembacaan besar yang tidak proporsional. Penulisan 4 KiB mengalokasikan blok 64 KiB; pembacaan berikutnya memulihkan 64 KiB penuh. Telemetri container di mana volume pembacaan melebihi volume penulisan >10x mencurigakan.

#!/usr/bin/env python3
"""
Detect anomalous write-then-read patterns characteristic of
cross-tenant residual data harvesting in thin-provisioned containers.

Usage: python detect_residual_harvesting.py io_events.jsonl

Input: JSONL file with one event per line:
  {"container_id": "abc123", "operation": "write", "size_bytes": 4096}
"""

import json
import sys
from collections import defaultdict

ANOMALY_THRESHOLD = 10.0  # read_bytes : write_bytes ratio

def analyze_io_events(events_file):
    with open(events_file) as f:
        events = [json.loads(line) for line in f]

    containers = defaultdict(
        lambda: {"writes": 0, "reads": 0, "write_bytes": 0, "read_bytes": 0}
    )

    for event in events:
        cid = event.get("container_id", "unknown")
        op = event.get("operation")
        size = event.get("size_bytes", 0)

        if op == "write":
            containers[cid]["writes"] += 1
            containers[cid]["write_bytes"] += size
        elif op == "read":
            containers[cid]["reads"] += 1
            containers[cid]["read_bytes"] += size

    print("=" * 60)
    print("CONTAINERS WITH ANOMALOUS READ/WRITE RATIOS")
    print("=" * 60)

    flagged = 0
    for cid, stats in sorted(containers.items()):
        if stats["write_bytes"] == 0:
            continue
        ratio = stats["read_bytes"] / stats["write_bytes"]
        if ratio > ANOMALY_THRESHOLD:
            flagged += 1
            print(f"\n🚩 Container: {cid}")
            print(f"   Writes: {stats['writes']:,} ops | "
                  f"{stats['write_bytes']:,} bytes")
            print(f"   Reads:  {stats['reads']:,} ops | "
                  f"{stats['read_bytes']:,} bytes")
            print(f"   Ratio:  {ratio:.1f}x — investigate")

    if flagged == 0:
        print("\n✅ No anomalous containers detected.")
    print(f"\nScanned {len(containers)} containers. Flagged: {flagged}")
    return flagged

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Usage: python detect_residual_harvesting.py <io_events.jsonl>")
        sys.exit(1)
    sys.exit(1 if analyze_io_events(sys.argv[1]) > 0 else 0)

Dalam insiden Cloudflare, proof-of-concept para peneliti menghasilkan tepat tanda tangan ini. Tim keamanan Cloudflare membangun deteksi dari PoC, menerapkannya ke telemetri I/O disk historis, dan mengonfirmasi bahwa satu-satunya aktivitas yang cocok berasal dari para peneliti dan engineer Cloudflare sendiri selama validasi resmi. Tidak ada eksploitasi pihak ketiga yang ditemukan.

Pelajarannya: jika Anda mengumpulkan telemetri I/O container, Anda dapat mengaudit secara retrospektif. Jika tidak, Anda terbang buta.

Runbook Remediasi

Jika audit Anda mengungkapkan skip_block_zeroing atau paparan serupa, berikut urutan remediasi yang dieksekusi Cloudflare — dan urutannya penting.

Langkah 1: Aktifkan Kembali Block Zeroing di Semua Pool

Hapus skip_block_zeroing dari konfigurasi pool dm-thin Anda. Ini adalah perubahan runtime pada perangkat thin-pool, tetapi hanya melindungi alokasi baru. Blok yang sudah dipetakan ke container yang berjalan dan snapshot image yang di-cache tetap rentan.

# This is a simplified representation — actual dm-thin 
# pool recreation commands vary by your orchestration layer.
# The core principle: restart the pool WITHOUT skip_block_zeroing.

dmsetup reload <pool-name> --table "0 <size> thin-pool <meta_dev> <data_dev> <data_block_size> 0"
dmsetup suspend <pool-name>
dmsetup resume <pool-name>

Cloudflare berhasil melakukan merge pada perbaikan ini dalam waktu sekitar 6 jam setelah laporan awal. Para peneliti secara independen mengonfirmasi bahwa PoC berhenti bekerja setelah perubahan ini.

Langkah 2: Pensiunkan Semua Disk Container yang Berjalan

Blok yang sudah dipetakan ke perangkat thin aktif mempertahankan kontennya (tanpa zeroing). Satu-satunya cara untuk menghilangkan data residual adalah dengan menghancurkan dan membuat ulang setiap disk container.

Cloudflare melakukan drain pada host di luar jam sibuk dan memulai ulang VM di setiap host. Ini adalah operasi bergulir (rolling) — untuk backend game, jadwalkan di jendela lalu lintas terendah Anda. Harapkan gangguan singkat per host. Jika lapisan matchmaking Anda mendukung pengalihan yang mulus, pemain di host yang sedang di-drain akan dimigrasikan, bukan diputus.

Langkah 3: Bersihkan Snapshot Image yang Di-cache

Langkah ini mudah terlewat. Lapisan orkestrasi container biasanya meng-cache layer image OCI sebagai snapshot dm-thin untuk mempercepat startup container. Snapshot cache ini dibuat sebelum perbaikan dan dapat berisi data residual di region yang tidak digunakan (termasuk ruang kosong ext4). Container baru yang mewarisi layer yang di-cache dapat membaca byte residual dari /dev/vdc tanpa pernah mengalokasikan blok baru.

Cloudflare menghapus semua snapshot cache pra-mitigasi di seluruh fleet yang terdampak, menyelesaikan pembersihan 15 hari setelah laporan awal. Layer cache dibuat ulang menggunakan alokasi yang di-zeroing.

Urutan pembuatan ulang itu penting. Jika Anda membersihkan cache sebelum mengaktifkan zeroing, Anda baru saja memasukkan blok yang tidak di-zeroing kembali ke snapshot baru.

Langkah 4: Validasi Bahwa Perbaikan Bertahan

Setelah remediasi, jalankan skrip deteksi terhadap telemetri I/O baru selama setidaknya 48 jam. Bandingkan rasio tulis/baca Anda dengan baseline pra-tambal. Pola rasio tinggi yang khas akan hilang sepenuhnya.

Anda juga harus memverifikasi tabel dm-thin di setiap host setelah reboot:

# Confirm no host still has skip_block_zeroing
dmsetup table 2>/dev/null | grep -q "skip_block_zeroing" && \
    echo "CRITICAL: Host $(hostname) still has skip_block_zeroing" || \
    echo "OK: $(hostname) — block zeroing active"

Prinsip Arsitektur untuk Mencegah Kelas Kerentanan Ini

Insiden Cloudflare adalah salah satu contoh dari kelas kegagalan isolasi penyimpanan multi-tenant yang lebih luas. Berikut adalah prinsip-prinsip yang melindungi backend game Anda — apakah Anda mengelola container sendiri atau mengandalkan platform.

Prinsip 1: Jangan Pernah Nonaktifkan Block Zeroing di Pool Multi-Tenant

Flag skip_block_zeroing ada untuk kinerja — zeroing blok 64 KiB pada setiap alokasi menambah overhead I/O. Di hardware single-tenant di mana hanya kode Anda yang berjalan, tradeoff ini mungkin dapat diterima. Di infrastruktur bersama di mana container didaur ulang antar-tenant, ini adalah cacat keamanan.

Aturan: Setiap pool dm-thin yang mengalokasikan blok ke lebih dari satu identitas tenant harus mengaktifkan block zeroing. Terapkan ini di lapisan infrastructure-as-code sehingga tidak ada host yang dapat diprovisikan tanpa itu.

Prinsip 2: Perlakukan Disk Container sebagai Ephemeral dan Berbahaya

Backend game Anda tidak boleh berasumsi bahwa disk container bersih saat startup. Bahkan dengan block zeroing yang diaktifkan, ada edge case dengan layer cache, pewarisan snapshot, dan bug kernel.

Tulis entrypoint container Anda untuk memformat atau menghapus volume yang dapat ditulis saat boot:

#!/bin/bash
# Ensure a clean writable disk on container start
if [ -b /dev/vdc ]; then
    # Overwrite with zeros (slow but thorough)
    # For a game backend, the writable disk is typically small (1-4 GiB)
    dd if=/dev/zero of=/dev/vdc bs=1M count=4096 status=progress
    
    # Create a fresh filesystem
    mkfs.ext4 -F /dev/vdc
    
    mount /dev/vdc /workspace
fi

Ini menambah beberapa detik pada startup container. Untuk pertandingan game yang berjalan 5–45 menit, itu dapat diterima. Untuk kebutuhan cold-start sub-detik, gunakan pendekatan yang lebih cepat: blkdiscard (yang memicu TRIM dan mungkin melakukan zeroing blok tergantung pada backend penyimpanan) dikombinasikan dengan mkfs.ext4 -F.

Prinsip 3: Pantau Rasio I/O sebagai Sinyal Keamanan

Sebagian besar pemantauan container berfokus pada CPU, memori, dan jaringan. Tambahkan I/O disk ke telemetri keamanan Anda. Rasio byte yang dibaca terhadap byte yang ditulis adalah sinyal kuat untuk serangan pemanenan data residual — workload game yang sah menulis dan membaca dalam pola yang seimbang. Container yang menulis potongan 4 KiB lalu membaca kembali 60+ KiB per region adalah anomali.

Jika backend Anda sudah mencatat peristiwa siklus hidup container, Anda dapat mengkorelasikan anomali I/O dengan identitas tenant dan stempel waktu pembuatan untuk mempersempit radius dampak dari insiden potensial. Untuk pengembang game yang menginginkan laporan crash dan log pengguna bawaan tanpa mengelola infrastruktur telemetri ini sendiri, platform seperti horizOn menyediakan kemampuan ini langsung jadi — artinya Anda menghabiskan lebih sedikit waktu untuk membangun plumbing dan lebih banyak waktu untuk logika game.

Prinsip 4: Terapkan Defense in Depth untuk Data Pemain

Bahkan jika disk container Anda bocor, kerusakannya terbatas jika data di dalamnya dienkripsi atau tidak berarti tanpa kunci. Simpan save state pemain, token sesi, dan data inventaris dalam keadaan terenkripsi at rest. Kunci enkripsi harus berada di secrets manager, bukan di disk container.

Ini adalah prinsip yang sama yang kami bahas dalam analisis kami tentang kebocoran data Star Citizen dan cara merancang backend game agar bertahan dari kompromi — defense in depth berarti berasumsi bahwa setiap lapisan tunggal pada akhirnya akan gagal.

Checklist Praktik Terbaik

  1. Audit setiap konfigurasi pool dm-thin sebelum deployment. Tambahkan pemeriksaan pre-flight ke pipeline orkestrasi container Anda yang gagal jika skip_block_zeroing ada. Ini adalah pemeriksaan CI lima baris yang mencegah seluruh kelas kerentanan.

  2. Kumpulkan telemetri I/O disk container dengan atribusi tenant. Anda tidak dapat mendeteksi eksploitasi yang tidak Anda amati. Catat volume tulis/baca per container, dikorelasikan dengan ID tenant dan ID host. Simpan setidaknya 30 hari untuk investigasi retrospektif.

  3. Zeroing atau hapus volume container yang dapat ditulis saat boot. Jangan hanya mengandalkan lapisan penyimpanan. mkfs.ext4 baru saat startup menambah overhead tulis 2–5 GiB tetapi menjamin tidak ada data residual yang bertahan dari daur ulang container.

  4. Lakukan drain dan daur ulang container selama tambalan keamanan, bukan hanya setelahnya. Mengaktifkan block zeroing hanya melindungi alokasi baru. Pemetaan yang ada di container yang berjalan dan snapshot image yang di-cache harus dibersihkan secara eksplisit. Selalu ikuti perbaikan dengan daur ulang di seluruh fleet.

  5. Enkripsi data pemain yang sensitif at rest dengan manajemen kunci eksternal. Jika blok residual bocor, ciphertext tanpa kunci tidak ada gunanya. Save state pemain yang dikelola melalui Cloud Save terikat akun milik horizOn menggunakan penulisan yang sadar revisi (revision-aware) dan resolusi konflik sisi klien — tetapi isolasi disk yang mendasarinya tetap menjadi tanggung jawab Anda jika Anda self-host container.

Timeline: Bagaimana Cloudflare Merespons

Sebagai referensi, beginilah cepatnya tim yang memiliki sumber daya memadai bergerak untuk menangani kerentanan infrastruktur yang kritis:

Waktu (UTC) Aksi
Sep 4, 15:26 Peneliti melaporkan melalui HackerOne
Sep 4, 18:45 Insiden keamanan dibuka, setup produksi dikonfirmasi
Sep 4, 21:27 Perbaikan runtime di-merge dengan uji penggunaan-ulang
Sep 4, 23:15 Peluncuran dimulai
Sep 7, 06:13 Peluncuran selesai, pembersihan dimulai
Sep 14, 10:50 Peneliti mengonfirmasi PoC tidak lagi berfungsi
Sep 19, 15:03 Semua snapshot cache pra-mitigasi dibersihkan

Itu di bawah 3 jam dari laporan ke akar penyebab yang dikonfirmasi, dan di bawah 8 jam ke perbaikan yang di-merge. Pembersihan fleet penuh memakan waktu 15 hari — normal untuk operasi bergulir di infrastruktur global.

Kecepatan itu penting. Setiap jam antara laporan kerentanan dan perbaikan adalah jam di mana eksploitasi mungkin terjadi. Jika Anda mengoperasikan infra container sendiri, bangun runbook sebelum Anda membutuhkannya.

Intinya

Kerentanan container Cloudflare bukan zero-day dalam arti kriptografis. Itu adalah tradeoff konfigurasi penyimpanan yang diketahui — kinerja di atas keamanan — yang tidak tepat untuk workload multi-tenant. Perbaikannya adalah satu perubahan konfigurasi ditambah daur ulang fleet.

Jika Anda menjalankan backend game di infrastruktur container bersama, audit pool dm-thin Anda hari ini. Jalankan skrip deteksi terhadap telemetri I/O Anda. Dan jika Anda lebih memilih untuk tidak mengelola isolasi disk container, daur ulang fleet, dan pipeline telemetri I/O sendiri, horizOn menangani autentikasi, laporan crash, cloud save, leaderboard, dan layanan backend lain yang dibutuhkan game Anda — sehingga Anda dapat fokus merilis game Anda, bukan debugging keamanan lapisan penyimpanan di produksi jam 3 pagi.


Sumber: Bagaimana Cloudflare menangani kerentanan paparan data lintas-tenant di Containers