ReDoS: tek bir düzenli ifade sunucuyu nasıl kilitler

Bazı düzenli ifadeler neredeyse eşleşen girdide üstel süre harcar. Tek bir event loop'un her isteğe hizmet ettiği Node.js'te böyle tek bir eşleşme tüm sunucuyu durdurur.

Örnek

Zafiyetli
const BANK_ROUTING = /([0-9]+)+\#/;

app.post("/profile", (req, res) => {
  if (!BANK_ROUTING.test(req.body.bankRouting)) return res.sendStatus(400);
  save(req.body);
});
Güvenli
const BANK_ROUTING = /^[0-9]{1,17}#$/;

app.post("/profile", (req, res) => {
  const value = String(req.body.bankRouting).slice(0, 32);
  if (!BANK_ROUTING.test(value)) return res.sendStatus(400);
  save(req.body);
});

Nasıl oluşur

İçeriği kendisi tekrar edebilen tekrarlı bir grup — (a+)+, ([0-9]+)+, (\w+\s?)+ — motora aynı girdiyi bölmenin birçok yolunu verir. Genel eşleşme başarısız olduğunda hepsini dener. Eşleşmeyi bozan bir karakterle biten otuz rakam saniyeler sürebilir; kırk rakam dakikalar. Kullanıcı girdisinden desen derlemek (new RegExp(req.query.q)) desenin kendisini saldırgana verir.

Nasıl düzeltilir

Her tekrarı belirsizlikten kurtar.

  • İç içe niceleyiciyi kaldır: ([0-9]+)+ yerine [0-9]+
  • Deseni sabitle ve tekrar sayılarını sınırla ({1,17})
  • Eşleştirmeden önce girdi uzunluğunu sınırla
  • Desen kurmadan önce kullanıcı girdisini escape et veya string karşılaştırması kullan

RepoVerse bunu nasıl bulur

  • Yüksekİstek girdisi geri izlemeye açık bir düzenli ifadeyle eşleştiriliyor

    İç içe niceleyiciler üstel geri izleme yapar. Birkaç düzine özel karakter CPU'yu kilitler; Node'un tek event loop'unda bu, sunucudaki her isteği durdurur.

    veri akışı · CWE-1333

  • Ortaİstek girdisi düzenli ifadeye derleniyor

    Deseni çağıranın kendisi verir — sonsuza kadar geri izleyen bir desen de dahil.

    veri akışı · CWE-1333

  • DüşükKilitlenmeye zorlanabilen düzenli ifade

    `(a+)+` gibi iç içe niceleyiciler üstel olarak geri izler; birkaç düzine karakterlik hazırlanmış bir girdi bir CPU çekirdeğini kilitler.

    örüntü · CWE-1333

Sorular

Her iç içe niceleyici tehlikeli mi?
Hayır. Her tekrar grubun geri kalanının eşleşemeyeceği sabit bir karakterle başlamak zorundaysa — bir sürüm numarasındaki (\.\d+)* gibi — girdiyi bölmenin tek bir yolu vardır ve eşleşme doğrusal kalır. RepoVerse her iç içe grubu işaretlemek yerine bunları ayırt eder.
ReDoS Node.js'te neden daha kötü?
Düzenli ifadeler ana thread'de çalışır; yavaş bir eşleşme bitene kadar sunucudaki diğer tüm istekleri bloklar.

İlgili

Güncellendi 2026-10-11