htmlspecialchars($text) &, <, >, " ve ' karakterlerini &, <, >, " ve ' değerlerine çevirir. Bir sayfaya yazdırdığınız her kullanıcı girdisi parçasında onu çağırın; girdi HTML olarak okunmak yerine metin olarak gösterilir.
Blok aynı yorumu iki kez yazdırır, bir kez ham ve bir kez kaçışlanmış. Çalıştırın ve Page sekmesindeki iki satırı karşılaştırın, sonra forma kendi HTML'inizi yazın, örneğin <h1>big</h1> veya <img src=x>, ve Show düğmesine basın.
Ham satırda tarayıcı etiketlere uyar: kalın kelime kalın olur ve <script> yazan bir ziyaretçinin betiği diğer her okuyucunun tarayıcısında çalışır. Bu saldırıya siteler arası betik çalıştırma (XSS) denir. Kaçışlanmış satırda aynı karakterler <b> olarak gelir ve tarayıcı onları metin olarak çizer. PHP'nin gerçekte yazdırdığı varlıkları görmek için Output sekmesine geçin.
htmlspecialchars neleri dönüştürür
Beş karakter, başka hiçbir şey. Harfler, aksanlar ve emoji değişmeden geçer.
& listededir çünkü her varlık onunla başlar: dokunulmadan bırakılsaydı < ifadesinden bahseden bir yorum < olarak gösterilirdi.
Yalnızca metni değil, öznitelikleri de kaçışlayın
Bir özniteliğin içindeki kullanıcı girdisi de aynı ölçüde kaçışlama gerektirir. O olmadan değerdeki bir tırnak özniteliği kapatır ve girdinin geri kalanı yeni öznitelikler olur. Burada "isim" gizlice bir style özniteliği ekler; çalıştırın ve iki kutuya bakın.
Güvensiz kutuda tarayıcı value="Ada" ve ardından yeni bir style özniteliği görür, bu yüzden kutu kırmızıya döner ve yalnızca Ada gösterir. Bir saldırgan orada style yerine onfocus="..." yazardı ve kodu çalışırdı. Güvenli kutuda her " " oldu, bu yüzden dizgenin tamamı value içinde kalır ve yazıldığı gibi gösterilir.
PHP 8.1'den beri varsayılan bayraklar ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401 olduğu için tek tırnaklar da kaçışlanır ve '...' ile yazılan öznitelikler güvenlidir. Eski kodlar çoğu zaman ENT_QUOTES değerini elle verir ve PHP 7 ve öncesinde bu gerekliydi:
Şablonlar için kısa bir yardımcı
Bir şablonda düzinelerce kez htmlspecialchars($x, ENT_QUOTES, 'UTF-8') yazmak kalabalık yaratır, bu yüzden çoğu proje onu tek harfli bir fonksiyonla sarar. Twig ve Blade gibi şablon motorları her {{ $var }} için aynısını otomatik olarak yapar.
?string türü ve ?? '' önemlidir: htmlspecialchars() fonksiyonuna null vermek PHP 8.1'den beri kullanımdan kaldırılmıştır ve sizin PHP'niz biyografisi olmayan her kullanıcı için bir kullanımdan kaldırma bildirimi yazdırırdı.
Çift kodlama ve htmlspecialchars_decode
Bir değer iki kez kaçışlanırsa okuyucu varlıkları görür: & ilk seferde &, ikincisinde &amp; olur ve tarayıcı bunu & olarak gösterir. Bu genellikle değerin kaydedilirken ve yazdırılırken yeniden kaçışlandığı anlamına gelir. Var olan varlıklara dokunmamak için double_encode: false verin ve geri dönmek için htmlspecialchars_decode() kullanın.
Gerçek çözüm ham metni saklamak ve yalnızca çıktıda kaçışlamaktır. double_encode: false içe aktarılmış bir besleme gibi sizin oluşturmadığınız varlıklar içeren metinler içindir.
htmlspecialchars, htmlentities ve strip_tags karşılaştırması
Bu üçü sık karıştırılır. Blok hepsini aynı girdi üzerinde çalıştırır ve her biri için PHP'nin ne yazdırdığını ve tarayıcının bundan ne çıkardığını gösterir:
htmlspecialchars()beş HTML karakterini kaçışlar. HTML'e yazdırdığınız her metin için kullanın.htmlentities()ayrıcaékarakteriniéyapar. Sayfalar UTF-8 değilken kullanışlıydı; bugün yalnızca kaynağı okumayı zorlaştırır.strip_tags()etiketleri siler ve metinlerini korur. HTML'i düz metne çevirmek (bir e-posta önizlemesi, bir meta açıklama) içindir, güvenlik için değil: son satır izin verilen bir<b>etiketininonclicközniteliğini koruduğunu ve bir özniteliğin içine konan metne hiç dokunulmadığını gösterir.
htmlspecialchars'ın yetmediği yerler
htmlspecialchars() HTML metni ve tırnaklı öznitelikler için doğru kaçışlamadır. Bir sayfanın diğer yerlerinin başka kuralları vardır:
- Bir URL'de
http_build_query()veyaurlencode()değeri kodlar;htmlspecialchars()ardından parametreler arasındaki&işaretini geçerli HTML yapar. - JavaScript'te
json_encode()geçerli bir JS değeri üretir veJSON_HEX_TAG<ve>karakterlerini\u003Cve\u003Eyapar, böylece verideki bir</script>betik etiketini kapatamaz. - Kullanıcı girdisini şemasını kontrol etmeden asla bir
hrefiçine yazdırmayın:htmlspecialchars('javascript:alert(1)')değişmez ve tıklandığında yine çalışır. filter_var sayfasında gösterildiği gibi yalnızcahttpvehttpsURL'lerini kabul edin.
Bunların hepsini bir araya getiren form işleme için PHP formlar sayfasına bakın.
Sıkça Sorulan Sorular
PHP'de htmlspecialchars ne işe yarar?
&, <, >, " ve ' karakterlerini &, <, >, " ve ' ile değiştirir. Tarayıcı o zaman bu karakterleri HTML olarak okumak yerine gösterir, böylece bir forma yazılan <script> metin olarak gösterilir ve asla çalışmaz.
htmlspecialchars ile htmlentities arasındaki fark nedir?
htmlspecialchars() yalnızca HTML'de özel olan beş karakteri dönüştürür. htmlentities() adlandırılmış bir varlığı olan her karakteri de dönüştürür, bu yüzden café café olur. UTF-8 sayfalarda ikisi de eşit derecede güvenlidir ve htmlspecialchars() çıktıyı okunur tuttuğu için olağan seçimdir.
PHP 8'de hâlâ ENT_QUOTES gerekiyor mu?
Güvenlik için değil: PHP 8.1'den beri varsayılan bayraklar ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401 olduğu için tek tırnaklar da kaçışlanır. Birçok kod tabanı, çağrının eski sürümlerde de aynı davranması ve okuyucular için açık olması için ENT_QUOTES, 'UTF-8' değerini hâlâ açıkça verir.
htmlspecialchars girdide mi yoksa çıktıda mı kullanılmalı?
Çıktıda. Ham değeri saklayın ve doğrulayın, onu HTML'e yazdırdığınız anda kaçışlayın. Girdide kaçışlamak veritabanınızda < saklar, uzunlukları ve aramaları bozar ve &lt; gibi çift kaçışlamaya yol açar.
strip_tags XSS'i önlemek için yeterli mi?
Hayır. strip_tags() etiketleri siler ama izin verilen etiketler parametresi onların özniteliklerini korur, bu yüzden <b onclick="..."> hayatta kalır ve bir özniteliğin içine konan metin için hiçbir şey yapmaz. Kullanıcı girdisini yazdırırken htmlspecialchars() kullanın.