PHP çekirdeğinde iki uzak kod çalıştırma açığı 20 Ekim 2026 akşamı kamuya açıldı. Açıklamalar embargo kalkmadan önce sızdı ve PHP ekibi güvenlik duyurusunu ileri çekerek düzeltmeleri bugün 14:00 UTC'de, Türkiye saatiyle 17.00'de yayımlamayı duyurdu. Duyurularda yama saatinin 17.15 olarak verildiği de görülüyor. Bu saate kadar internet erişimi olan her PHP kurulumu için mesafe birkaç saatten ibaret. CERT-EU advisory 2026-018 aynı iki CVE'yi işaret ediyor ve saldırı kanıtı konusunda çelişkili açıklamalar dolaşıyor. Cloudflare'ın CTO'su erken saldırıların başladığını bildirdi, Alman BSI ise henüz doğrulanmış saldırı olmadığını söyledi. Durum belirsiz olsa da açığın kapsamı geniş, beklemek doğru hareket değil.
İki açık, tek senaryo, onarım sadece yama değil
Konu CVE-2026-109618 ve CVE-2026-109619. PHP güvenlik ekibi ikisini de CVSS v4.0 ile 9.2 puan, yani kritik seviyede tanımladı. CERT-EU'ya göre ikisi de kimlik doğrulaması gerektirmeyen uzak kod çalıştırmaya yol açabilir ve PHP 5 sürümünden itibaren tüm sürümleri kapsayabilir. Yayımlanan istismar aracının kendi iddiası, 5.4.0'dan bu yana çıkan her sürümde çalıştığı yönünde. Resmi teknik ayrıntılar sızıntı öncesinde paylaşılmadığı için bugün sürüm notlarında görülecek olan kök neden, sınıflandırma koduna kadar PHP çekirdeğinde.
İstismar zincirinin ortak noktası, PHP'nin dosya yükleme ilerlemesini oturuma yazan özelliği. session.upload_progress.enabled varsayılan olarak açık geliyor ve PHP her multipart isteğinde PHP_SESSION_UPLOAD_PROGRESS alanını arıyor. Alan bulunduğunda PHP, istekteki çerezden gelen oturum kimliğini kullanarak bir oturum dosyası açıyor ve ilerleme verisini içine yazıyor. Bu işlem uygulamanın kodundan bağımsız, istek gövdesi ayrıştırılırken ve uygulama session_start() çağırmasa bile çalışıyor. Araştırma tarafında doğrulanan birden fazla yol var: oturum dosyasına enjeksiyon ve yerel dosya dahil etme, var_destroy içindeki kullanımdan sonra bırakılan bellek hatası, ve işleyici uyuşmazlığı yoluyla nesne enjeksiyonu. İlki tek başına yeterli değildi, diğer ikisi uygulamada LFI açığı bulunmasını gerektirmiyor. Bu yüzden açığı "sadece bir LFI yükselteci" diye değerlendiren ilk yazılar eksik kaldı.
Hangi sürümler etkileniyor
PHP yalnızca hâlâ desteklenen dalları yamalar. Düzeltmelerin çıkması beklenen sürümler 8.2.35, 8.3.36, 8.4.27 ve 8.5.12. 8.2'nin güvenlik desteği 31 Aralık 2026'da, 8.3'ün 2027, 8.4'ün 2028, 8.5'in 2029'da bitiyor. 8.1 ve üzeri altındaki tüm dallar yaşam döngüsünü tamamladı, PHP ekibinden resmî yama gelmeyecek. Linux dağıtımlarının kendi paketleri geriye dönük taşıma yapabilir, o yüzden Ubuntu, Debian ve Red Hat advisory sayfaları ayrıca takip edilmeli.
Sürüm kontrolünü php -v yerine paket sürümüyle yapmak gerekiyor. Ubuntu ve Red Hat sık sık yamayı eski sürüm numarasına geri taşır, yani 8.3.6 hâlâ 8.3.6 görünür ama paket sürümü değişmiştir. Debian ise yeni upstream sürümünü kendisi dağıtır, bookworm'da 8.2.x, trixie'de 8.4.x yükselmesi beklenir. Debian ve Ubuntu'da dpkg -l 'php*' ile, RHEL tarafında rpm -qa 'php*' ile durum görülmeli. RHEL 8'de düz dnf install php komutu 7.2 kurar, o akış 2021'den beri emekli. RHEL 9'un 8.1 modül akışı da aynı durumda.
Üçüncü taraf paket depolarının durumu
Ubuntu 22.04 ve 24.04 için kullanılan Ondřej Surý deposu, DESTEKLENEN tüm Debian ve Ubuntu sürümlerinde yamayı alacak. amd64 paketleri önce, arm paketleri derlendikçe geliyor. Deponun bazı aynaları geciktiği için apt-cache policy php8.4-fpm çıktısında yeni sürüm görünmüyorsa kaynak adresi doğrudan PPA içeriğine alınmalı. PHP Vakfı, Remi deposunun 21 Ekim'de yama vermeyeceğini açıkladı. Bu depo RHEL, AlmaLinux ve Rocky için yaygın kullanılıyor ve oradaki sistemler bugün yamayı alamayacak. Dağıtımın kendi paketlerine geçmek ya da kaynaktan derlemek gerekiyor. CloudLinux alt-php paketlerini hazırlıyor, Imunify360 ModSecurity kural seti 8.83 ile dolaşımdaki istismar şeklini engelliyor.
Yamadan önce: geçici önlem katmanları
Aşağıdaki adımların hepsi geçicidir. Hiçbiri açığı kapatmaz, sadece saldırı yüzeyini daraltır ve yamaya kadar geçen süreyi kısaltır. En önemli nokta, hiçbirinin tek başına yeterli olmadığı. Kurulumda bu adımları bir geçici önlem olarak işaretleyin, kalıcı çözüm olarak kaydetmeyin. Tek gerçek onarım, güvenli sürüme yükseltmektir.
En etkili iki önlem var. Birincisi, oturum yükleme ilerlemesi kod yolunu kapatmak. Debian ve Ubuntu'da her SAPI'nin tarama dizinine düşürme dosyası ekleniyor, örneğin /etc/php/8.4/fpm/conf.d/99-disable-upload-progress.ini:
session.upload_progress.enabled = 0
session.use_strict_mode = 1
Ardından FPM yeniden yükleniyor. Bu ayar PHP_INI_PERDIR seviyesinde olduğu için çalışma zamanında ini_set() ile değiştirilemiyor, dosyadan veya havuz tanımından verilmesi gerekiyor. Havuz bazında kapatmak isteyenler /etc/php/8.4/fpm/pool.d/www.conf içine şunu ekleyebilir:
php_admin_flag[session.upload_progress.enabled] = off
FrankenPHP kullanıyorsanız PHP ikiliye gömülü olduğu için hiçbir php.ini okunmuyor. Değer Caddyfile içindeki global seçenekler bloğuna yazılıyor:
{
frankenphp {
php_ini session.upload_progress.enabled 0
}
}
İkinci önlem, multipart istekleri web sunucusunda engellemek. nginx için http bağlamında bir map tanımı ve her PHP'ye aktaran sunucu bloğunda karar:
map $http_content_type $block_multipart {
default 0;
"~*multipart" 1;
}
if ($block_multipart) {
return 403;
}
403 hatası geri döndüğünde isteği PHP'ye yönlendiren bir error_page tanımı varsa return 444; kullanılmalı. Sitenin tamamında dosya yüklemesi kullanılmıyorsa bu en etkili yöntem. Yükleme gerekiyorsa yalnızca belirli uç noktalara izin verilebilir, $uri eşleşmesi sorgu dizesini içermediği için /upload gibi yolları listede tutmak yeterli.
Apache 2.4 için vhost ya da .htaccess içinde şu blok kullanılıyor. req('Content-Type') kullanılması önemli, yüzde değişkeniyle yapılan denetim bazı sürümlerde çalışmıyor:
<If "req('Content-Type') =~ /multipart/i">
Require all denied
</If>
Caddy tarafında eşleşme header_regexp ile büyük küçük harf duyarsız yapılıyor:
example.com {
@multipart header_regexp Content-Type (?i)multipart
respond @multipart 403
}
lighttpd için mod_access modülü ve şu koşul gerekiyor:
server.modules += ( "mod_access" )
$REQUEST_HEADER["Content-Type"] =~ "(?i)multipart" {
url.access-deny = ( "" )
}
Sitenin tamamını kapatmak zorunda kalırsanız dikkat: yalnızca PHP işleyicisini devre dışı bırakmak kötü bir fikir. Apache a2dismod php8.4 sonrası .php dosyalarını kaynak kod olarak düz metin olarak servis edebiliyor, içindeki parolalar açığa çıkıyor. nginx'de location ~ \.php$ bloğunu kaldırmak da aynı sonucu doğurur. Web sunucusunu durdurmak veya her isteğe 503 döndürmek güvenli olan yol. Yalnızca FPM'i durdurup nginx yapılandırmasını olduğu gibi bırakmak 502 verdiği için sorun çıkarmıyor.
Bir kademe daha geride: siteyi salt okunur yapmak
Siteyi tamamen kapatmak istemiyorsanız, exploit POST veya PUT gövdesiyle geldiği için yalnızca GET ve HEAD'e izin vermek daraltılmış bir yüzey bırakıyor. nginx için:
if ($request_method !~ ^(GET|HEAD)$) {
return 503;
}
Bu yaklaşım girişleri, formları ve ödeme akışlarını durdurur. Ziyaretçi siteyi okuyabilir, veri giremez.
Yararlı görünen ama işe yaramayan adımlar
Birkaç öneri internette dolaşıyor, hiçbiri exploit'i durdurmuyor. file_uploads = Off PHP'nin multipart gövdesini ayrıştırmayı engellemiyor, yalnızca dosya parçalarını atlamasını sağlıyor. post_max_size ve upload_max_filesize için güvenli sayı yok, post_max_size = 0 sınır olmadığı anlamına geliyor. enable_post_data_reading = Off normal formları kırıyor ve PHP 8.4 ile gelen request_parse_body() yolunu kapsamıyor. Uygulama katmanındaki CSRF kontrolü, oturum açma kontrolü, Laravel bakım modu ve WordPress güvenlik eklentileri istemciyi engelliyor ama istek gövdesi zaten ayrıştırıldığı için çok geç kalıyor. WAF kuralları ise çoğunlukla bilinen istismar kalıbına eşleşiyor, farklı bir varyant sessizce geçebiliyor.
Cloudflare yöneticileri için önemli bir ayrıntı var: Cloudflare'ın kural setleri yalnızca trafik Cloudflare üzerinden geliyorsa işe yarıyor. Origin IP doğrudan erişilebilir durumdaysa saldırgan isteği origin'e gönderip WAF'ı tamamen atlıyor. Aynı durum Bunny Shield ve ModSecurity için de geçerli. Origin IP'yi yalnızca Cloudflare IP'lerinden gelen trafikle sınırlamak, WAF'ı her zaman kullanışlı kılar.
Yamadan sonra ne yeniden başlatılacak
PHP dosyaları diskte değişir ama çalışan süreçler eski kodu bellekte tutmaya devam eder. FPM arkasında nginx, Caddy veya proxy_fcgi kullanan Apache varsa systemctl restart php8.3-fpm yeterli, reload da yeni kodu yükler, web sunucusunda işlem gerekmez. mod_php ile çalışan Apache'de reload ve apachectl graceful yetmez, tam stop ve start gerekir. LiteSpeed ve OpenLiteSpeed kurulumlarında lsphp süreçleri ayrı çalıştığı için paketleri yükselttikten sonra sudo pkill lsphp çalıştırılmalı. FrankenPHP'de PHP ikilinin içinde olduğu için apt ve dnf işe yaramaz, yeni FrankenPHP sürümü ya da imajı gerekir. Docker kullanılan kurulumlarda docker build --pull ile imaj yeniden kurulup konteynerler yeniden oluşturulmalı. Kuyruk işçileri, Laravel Octane ve Supervisor işleri de yeniden başlatılmalı, Laravel kuyrukları için php artisan queue:restart çalışıyor. Octane için octane:reload yalnızca uygulama kodunu yeniler, PHP'yi değil.
Eski PHP çalıştıran süreç kalmadığını doğrulamak için şu komut kullanılıyor. Diskteki dosya silinmiş ama bellekte açık kaldığında süreç haritasında silinmiş dosya işaretleniyor:
sudo grep -lE ' /(usr|lib|opt).*\(deleted\)$' /proc/[0-9]*/maps
Çıktı boşsa her şey yeni sürümü çalıştırıyor. Desen yalnızca /usr, /lib ve /opt altındaki dosyaları arıyor, çünkü OPcache her FPM sürecinde silinmiş bir /dev/zero eşlemesi tutuyor ve geniş bir desen her PHP sürecini yanlışlıkla işaretlerdi. Ubuntu ve Debian'da needrestart -b -r l aynı kontrolü yapıyor.
Yamadan sonra hangi önlemler geri alınacak
Önce yama, sonra eski PHP çalıştıran süreç kontrolü, en son önlemlerin geri alınması sırası önemli. Web sunucusundaki multipart engeli kaldırılmalı, aksi halde dosya yükleme bozulur. Cloudflare özel kuralı da kaldırılmalı, yönetilen kurallar kalabilir. session.upload_progress.enabled = 0 uygulamanızda bu özellikle yükleme ilerlemesi çubuğu yoksa kalabilir. session.use_strict_mode = 1 her durumda önerilir, PHP zaten her site için bunu öneriyor. Siteyi çevrimdışı alan kurulumlar geri açılır, salt okunur yapılanlar normal hale döner. PHP'den program çalıştırmayı engelleyen AppArmor ya da SELinux kuralları uygulama hâlâ çalışıyorsa bırakılabilir.
İzleme ve ihlal belirtileri
Yamadan sonra geriye bırakılan hiçbir şey otomatik olarak temizlenmiyor. PHP çalışan sürecin bir kabuk, betik yorumlayıcı veya indirme aracı başlattığında alarm üretmek, ihlali erken yakalamanın en pratik yolu. PHP işçisi, PHP CGI, httpd ya da apache2 süreçleri üzerinden bir shell açılması kuralına yazılmalı. Bazı uygulamalar görsel boyutlandırma veya PDF üretimi için bilerek başka programlar çalıştırır, kurallar yazılmadan önce normal davranış belirlenmeli. Web shell dosyaları, yeni cron işleri, yeni kullanıcı hesapları ve değişmiş dosya izinleri elde tutulan loglara bakılarak incelenmeli.
Exploit başarılı olduğunda genellikle oturum kayıtlarından PHP çalışma dizininde yeni dosyalar, beklenmeyen system veya exec çağrıları, oturum kayıtlarının normalden hızlı büyümesi görülür. Veritabanı bağlantı bilgileri PHP kaynak kodunun içinde olduğu için sızma sonrası veritabanı erişimi de yeniden değerlendirilmeli.
EOL sunucular için uzun vadeli yol
8.1 ve altı dallara resmî yama gelmeyecek. Dağıtımınız geriye dönük taşıma yapmıyorsa iki seçenek kalıyor: sunucuyu geçici olarak çevrimdışı tutmak ya da internete açık olmayan bir ağa taşımak. Desteklenen bir sürüme geçiş taşınabilir, ama 8.2'nin güvenlik desteği 31 Aralık 2026'da bitiyor, doğrudan 8.4 veya 8.5 hedeflenmeli. Ubuntu'da sürüm yükseltme LTS paketleri üzerinden yapılıyor, 24.04 PHP 8.3, 26.04 PHP 8.5 ile geliyor. RHEL tarafında modül akışı değişikliği önce sıfırlama gerektiriyor.
Yamaların 14:00 UTC'de çıkması bekleniyor ve dağıtım depolarının takvimi bunun birkaç saat sonrasına dağılıyor. Bugün sürüm notlarını okuyup hangi dalın hangi sürümle kapandığını netleştirmek, sonra paket yükseltme ve yeniden başlatma adımlarını izlemek, gece yarısına kadar halledilebilir bir iş. Sabit sürümü atlamak, tekrar geriye dönük yama uygulamak işi uzatar.
Desteklenen PHP sürümlerinin listesi ve güvenlik desteğinin bitiş tarihleri php.net desteklenen sürümler sayfasında duruyor. Duyuru ve sürüm notlarını aynı sayfadan takip etmek gerekiyor.
CVE kapsamı, etkilenen sürümler ve CERT-EU'nun önerileri için CERT-EU 2026-018 advisory sayfası kullanılabilir.
