GÜNDEM
PHP2Shell: Açık uygulamanızda değil, PHP'nin kendisinde
CVE-2026-109618 ve CVE-2026-109619, PHP çalışma zamanında kimlik doğrulamasız RCE'ye kapı açıyor. CMS'i güncellemek yetmiyor; sunucudaki PHP binary'sini yamalamanız gerekiyor.
Tek cümlelik özet
Hedef WordPress'iniz değil, onu çalıştıran PHP: dosya yükleme kabul eden tek bir uç nokta, uygulama kodunuz daha çalışmadan istismar edilebiliyor.
21 Ekim 2026'da PHP iki kritik açık için acil bir sürüm çıkardı: CVE-2026-109618 ve CVE-2026-109619. İkisine birlikte PHP2Shell deniyor, ikisi de CVSS 4.0'da 9.2 alıyor ve hiçbiri authentication istemiyor.
Bu haberde beni en çok rahatsız eden kısım açığın yeri oldu. Çoğumuz böyle bir başlık görünce önce WordPress plugin'lerine, Drupal modüllerine ya da kendi kodumuza bakarız. Burada hata PHP runtime'ının kendisinde. O yüzden CMS'i güncellemek, plugin silmek ya da WAF'a kural eklemek tek başına işi bitirmiyor; web request'lerine cevap veren PHP binary'sini patch'lemeniz gerekiyor.
Ne oldu?
Recorded Future'ın çıkardığı zaman çizelgesi (UTC) şöyle:
- 19 Ağustos'ta Wiz Research ilk açığı buluyor ve iki gün içinde Drupal ile WordPress üzerinde unauthenticated RCE'yi doğruluyor.
- 24 Ağustos'ta açıklar PHP ekibine özel olarak bildiriliyor.
- 20 Ekim'de PHP, 21 Ekim için olağan dışı bir güvenlik sürümü duyuruyor.
- 21 Ekim saat 02:29'da sızdırılmış bir arşiv VirusTotal'e yükleniyor ve CVE numaraları planlanandan önce ortaya çıkıyor.
- Aynı gün 07:34'te Patchstack, hosting iş ortaklarından birden fazla aktif exploitation vakası geldiğini duyuruyor.
- 13:52'de patch'ler yayında: 8.5.12, 8.4.27, 8.3.36, 8.2.35.
Yani exploit denemeleri patch'ten önce başlamış. Kaç sistemin gerçekten ele geçirildiğini ise hâlâ kimse net söyleyemiyor.
İki açık nasıl çalışıyor?
CVE-2026-109619, session upload progress özelliğindeki bir use-after-free. Dosya yükleme ilerlemesini takip eden kod, session tablosundaki iki değere raw pointer tutuyor. Sonraki bir session güncellemesi tabloyu free edip yenisini kuruyor ama bu pointer'ları güncellemiyor. Saldırgan da boşalan alana sahte bir yapı yerleştiriyor ve engine o sahte yapıyı takip ediyor.
CVE-2026-109618 ise out-of-memory anındaki bir memory corruption. PHP memory_limit'e çarptığında longjmp() ile doğrudan request shutdown'a atlıyor ve normal temizliği atlıyor. Yarım kalmış yapılar shutdown sırasında geçerliymiş gibi okunuyor. Bellek önceden sahte veriyle doldurulmuşsa bu, saldırganın seçtiği bir function pointer'a dallanmak anlamına geliyor.
İşi asıl tehlikeli yapan şu: session katmanı upload progress'i sizin uygulama kodunuz çalışmadan önce işliyor. Dosya upload kabul eden herhangi bir endpoint, gelen dosyayı hiç kullanmasa bile hedef olabiliyor ve session.upload_progress.enabled varsayılan olarak açık geliyor.
Kim etkileniyor?
Web request'lerine cevap veren bütün PHP kurulumları etkileniyor: PHP-FPM, Apache mod_php, php-cgi, FrankenPHP ve LiteSpeed. Raporlar PHP 5.4'ten 8.5'e kadar olan sürümleri kapsamda sayıyor.
Ölçek de ürkütücü. Qualys verisinde sürümü bilinen 156 milyon PHP kurulumunun yaklaşık %71'i desteği bitmiş dallarda (5.4 ile 8.1 arası) çalışıyor ve açıklamadan sonraki ilk 12 saatte patch'lenen kurulum sayısı sadece 199 bin. PHP 7.4, 8.0 ya da 8.1 kullanıyorsanız upstream'den yalnızca sınırlı source backport var; bu durumda dağıtımınızın paketine bakmanız ya da sürüm yükseltmeniz gerekiyor.
Ne biliyoruz, ne bilmiyoruz?
Doğrulanmış olanlar iki CVE, 9.2'lik CVSS skoru, patch'li sürümler, mod_php üzerinde gösterilmiş RCE, patch öncesi sızıntı ve gerçek saldırı trafiği.
Doğrulanmamış olan ise başarılı compromise sayısı. GitHub'da dolaşan PoC'ler var ama Recorded Future, bunlardan birinin yazarının sonradan kendi teorisini geçersiz saydığını not ediyor. Elinizdeki PoC çalışmadı diye açığın exploit edilemeyeceğini düşünmeyin.
Sunucunuzu 5 dakikada kontrol edin
İlk tuzak şu: php -v size CLI sürümünü gösterir ama web'e cevap veren binary bambaşka olabilir. Web tarafını ayrıca kontrol etmeniz gerekiyor.
# CLI ve FPM sürümleri (farklı olabilir)
php -v
php-fpm8.3 -v 2>/dev/null || php-fpm -v
# Apache mod_php yüklü mü? (en yüksek risk)
apache2ctl -M 2>/dev/null | grep -i php
# Upload progress açık mı?
php -i | grep -E "session.upload_progress.enabled|memory_limit|post_max_size"
# Debian/Ubuntu paket sürümü (dağıtım backport'u eski numarayı koruyabilir)
dpkg -l | grep -E "^ii\s+php[0-9.]*-(common|fpm|cli)"Dağıtım paketleri fix'i eski bir sürüm numarasıyla getirebiliyor. Bu yüzden numaraya güvenmek yerine dağıtımınızın security advisory'sine bakın.
Log'larda iz arayın
Bilinen exploit akışı request tarafında birkaç iz bırakıyor: bir PHPSESSID, PHP_SESSION_UPLOAD_PROGRESS alanı taşıyan multipart bir POST, bir saniyeden uzun bir bekleme ve art arda tekrarlanan çok sayıda form alanı. Sunucu tarafında ise crash olan worker'lar görürsünüz.
# Çöken PHP worker'ları (20 Ekim'den itibaren)
grep -E "SIGSEGV|exit signal Segmentation fault" /var/log/php*-fpm.log /var/log/apache2/error.log
# Upload progress alanı içeren istekler (body log'luyorsanız ya da WAF log'unda)
grep -l "PHP_SESSION_UPLOAD_PROGRESS" /var/log/waf/*.logTek bir eşleşme compromise olduğunuzu göstermez. Ama 20 Ekim'den bu yana açıklayamadığınız worker crash'leri varsa incident response başlatır, o sunucudaki credential'ları (veritabanı şifreleri, API key'ler) değiştirirdim. Açıklardan biri worker belleğini sızdırabildiği için bu adımı atlamamak gerekiyor.
Patch'i hemen geçemiyorsanız
Aşağıdakiler riski azaltır ama patch'in yerini tutmaz:
; php.ini ya da FPM pool — ini_set() ve .user.ini YETMEZ
session.upload_progress.enabled = Off
; yalnızca PHP 8.5
fatal_error_backtraces = Off
; yükleme yoksa 8M, varsa 32M; upload_max_filesize bundan küçük olsun
post_max_size = 8MAyarı değiştirdikten sonra bütün worker'ları restart etmeyi unutmayın, yoksa eski ayarla çalışmaya devam ederler. Bunun yanında multipart request'e ihtiyaç duymayan endpoint'lerde bunu reverse proxy'de engelleyebilir, request boyutuna, alan sayısına ve header'lara sınır koyabilirsiniz. Worker başına memory limit'i de cgroup üzerinden vermek mantıklı. Bunların hiçbiri mümkün değilse servisi internete kapatıp her sistem için bir sorumlu ve bir son tarih belirlemenizi öneririm.
Hemen yapılacaklar
- Web'e cevap veren her PHP'nin listesini çıkarın. Container image'ları, yönetim panelleri ve üçüncü parti uygulamaların içine gömülü PHP'ler de bu listeye girmeli.
- Apache + mod_php çalışan sunucuları listenin en başına alın.
- 8.5.12, 8.4.27, 8.3.36 ya da 8.2.35'e veya dağıtımınızın patch'li paketine geçin ve worker'ları restart edin; restart olmadan fix devreye girmiyor.
php:8.xtabanlı container image'larını yeniden build edin, çünkü eski image çalıştığı sürece açık da yaşamaya devam ediyor.- CVE-2026-115560 düzelene kadar upload progress'i kapalı tutun.
- Log'lara 20 Ekim'den itibaren bakın; crash görürseniz credential'ları rotate edin.
Kaynaklar: Qualys TRU · Akamai · Recorded Future Insikt · Fortinet
