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
const BANK_ROUTING = /([0-9]+)+\#/;
app.post("/profile", (req, res) => {
if (!BANK_ROUTING.test(req.body.bankRouting)) return res.sendStatus(400);
save(req.body);
});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
- Kod injection: eval'e verilen istek girdisiİstek verisi üzerinde eval, new Function ve string timer'ların neden uzaktan kod çalıştırma (CWE-95) anlamına geldiği, OWASP NodeGoat'tan gerçek bir örnek ve çözüm.
- Kod, secret ve bağımlılıklar için GitHub güvenlik taramasıGitHub reposunu injection açıkları, sızmış secret'lar ve zafiyetli bağımlılıklar için tara. İstekten tehlikeli çağrıya veri akışı izi ve çözüm önerileri.
Güncellendi 2026-10-11