Skip to content
Bloga Dönün
Eğitimler

HTML Varlıkları Açıklandı: Adlı, Sayısal ve Ne Zaman Escape

HTML varlıkları için pratik kılavuz: adlı, ondalık ve onaltılık başvurular, escape edilmesi gereken beş karakter ve XSS'e karşı bağlam kuralları.

8 dakika okuma

HTML varlığı, bir karakteri tarayıcının onu işaretleme olarak değil de metin olarak göstereceği biçimde yazmanın yoludur. İçeriğinize ham bir < yazarsanız tarayıcı bunu bir etiketin başlangıcı sanır; bunun yerine &lt; yazarsanız sayfada düz bir < görünür. İşte HTML varlık kodlamasının arkasındaki tüm fikir bu yer değiştirmedir.

HTML’de beş karakter özel anlam taşır ve en sık escape ettikleriniz bunlardır: <, >, &, " ve '. Bunları iki nedenle escape edersiniz. Birincisi görüntülemedir: kodu veya işaretlemeyi metin olarak göstermek istersiniz. İkincisi ve daha önemlisi güvenliktir: güvenilmeyen girdiyi escape etmek, siteler arası betik çalıştırmayı (XSS) durdurmanın temelidir.

Herhangi bir varlığı yazmanın birbirinin yerine geçebilen üç yolu vardır (adlı &lt;, ondalık &#60; ve onaltılık &#x3C;) ve bunların hepsi aynı karaktere çözümlenir. Asıl iş ne zaman ve neyle escape edileceğini bilmektir, çünkü doğru yanıt değerin nereye düştüğüne bağlıdır: HTML metni, bir öznitelik, bir betik ya da bir URL. Bu kılavuz; gösterimleri, ayrılmış karakter kümesini, bir bağlam karar matrisini ve insanları en çok ısıran tuzakları adım adım anlatır.

HTML varlığı nedir? (anatomi)

Karakter başvurusu olarak da adlandırılan HTML varlığı, tek bir karakterin yerini tutan kısa bir koddur. Her varlık bir ampersand & ile başlar ve bir noktalı virgül ; ile biter. Aralarında ne bulunduğu, hangi karakteri elde edeceğinizi belirler.

Üç biçimi vardır:

  • &name;&lt; veya &copy; gibi bir adlı başvuru.
  • &#decimal;&#60; gibi bir ondalık sayısal başvuru.
  • &#xhex;&#x3C; gibi bir onaltılık sayısal başvuru.

Tarayıcı başvuruyu okur, işaret ettiği karakteri arar ve o tek karakteri işler. Görünen sonuçla ilgili hiçbir şey değişmez; &lt; ile ham bir < aynı şekilde görüntülenir. Tek fark, varlığın hiçbir zaman bir etiketin başlangıcı olarak değil, metin olarak ele alınmasıdır.

Üç gösterim: adlı, ondalık, onaltılık

Üç gösterim de aynı Unicode kod noktasına başvurur; yalnızca yazılışları farklıdır. Adlı varlık okunabilir biçimdir ama yalnızca tanımlı bir adı olan karakterler için vardır. Ondalık varlık kod noktasını 10 tabanında yazar. Onaltılık varlık aynı kod noktasını 16 tabanında yazar; bu da Unicode standardında gördüğünüz U+XXXX gösterimine birebir karşılık gelir.

KarakterAdlıOndalıkOnaltılık
<&lt;&#60;&#x3C;
&&amp;&#38;&#x26;
©&copy;&#169;&#xA9;
é&eacute;&#233;&#xE9;

Onaltılık biçim U+XXXX ile doğrudan örtüştüğü için (é karakteri U+00E9, dolayısıyla &#xE9;) birçok geliştirici belirli bir kod noktasını belgelerken veya üzerine düşünürken bu biçime başvurur. Günlük işaretleme için adlı varlıklar en iyi okunan biçimdir.

Escape etmeniz gereken beş ayrılmış karakter

Bunlar, tarayıcının bir belgeyi nasıl ayrıştırdığını değiştiren HTML özel karakterleridir. Bunlardan biri, çalıştırılması değil de gösterilmesi gereken içerikte yer alıyorsa onu escape edin.

KarakterAdlıOndalıkOnaltılıkEscape etmezseniz ne bozulur
<&lt;&#60;&#x3C;Bir etiket başlatır; tarayıcı sonraki metni işaretleme olarak okur
>&gt;&#62;&#x3E;Bir etiketi vaktinden önce kapatır
&&amp;&#38;&#x26;Bir varlık başlatır; kalanı bir başvuru sanılabilir
"&quot;&#34;&#x22;Çift tırnaklı bir öznitelik değerini erken bitirir
'&#x27;&#39;&#x27;Tek tırnaklı bir öznitelik değerini erken bitirir

HTML ampersand varlığı tüm sistemin köküdür. & karakteri her varlığı başlatır, bu yüzden önce onun escape edilmesi gerekir. Köşeli açıları ampersand’dan önce escape ederseniz, az önce ürettiğiniz varlıklardaki & karakterini yeniden escape edersiniz. Bu tuzak hakkında daha fazlası aşağıda.

Gerçekte ne zaman escape etmeniz gerekir? (bağlama duyarlı)

Çoğu hatanın ve çoğu güvenlik açığının yaşadığı yer burasıdır. Temel ilke kısadır: değerin düştüğü bağlama uygun biçimde, çıktı anında escape edin. Bir yerde güvenli olan bir değer başka bir yerde tehlikelidir, dolayısıyla uyguladığınız kodlamanın hedefe uyması gerekir.

HTML öğe içeriği

Bir değeri etiketlerin arasına bıraktığınızda, yani bir <p>, bir <div> ya da bir <td> içine, <, > ve & karakterlerini escape edin. Tırnakları burada escape etmek zararsızdır ama gereksizdir. <strong> metnini bir sonraki kelimeyi kalınlaştırmak yerine düz karakterler olarak göstermek istiyorsanız, onu &lt;strong&gt; biçimine kodlayın; tarayıcı etiketi uygulamak yerine onu yazdırır.

HTML öznitelik değerleri

Bir özniteliğin içinde tırnak karakterleri kritik hale gelir. Bir değer title="…" içinde bulunuyor ve escape edilmemiş bir " içeriyorsa, özniteliği erken bitirir ve bir saldırganın yeni öznitelikler eklemesine olanak tanır; klasik bir XSS vektörüdür. Öznitelik bağlamında " (ve ideal olarak ') karakterini escape edin. He said "hi" gibi bir değerin, kendi içinde tutulması için He said &quot;hi&quot; biçimine dönüşmesi gerekir.

<script> veya satır içi JavaScript içinde

HTML varlıkları burada işe yaramaz. Bir <script> bloğuna veya satır içi bir olay işleyicisine inşa edilen bir dizgenin, karakter başvurularına değil, JavaScript veya JSON dizge escape’ine ihtiyacı vardır. Bir JS dizge değişmezi içinde &quot; yazmak, bir tırnak değil, altı karakterlik düz metin üretir. Bu bağlam için JSON Kaçış aracına başvurun ve betik içinde gerçekten geçerli olan \uXXXX kuralları için JSON dizge escape’i için eksiksiz kılavuzu okuyun.

Bir URL içinde

Bir URL’nin kendi escape şeması vardır: yüzde kodlaması. HTML varlıkları bir değeri URL açısından güvenli yapmaz. a&b c dizgesi bir sorgu içinde a&amp;b c değil, a%26b%20c olarak yer alır; boşluk hâlâ URL’yi bozar ve & hâlâ parametreleri ayırır. Bunun için URL Kodlayıcı ve Çözücü aracını ve ayrılmış ile ayrılmamış karakterlere dair tüm kurallar için URL kodlama ve çözme kılavuzunu kullanın.

Karar matrisi

BağlamNeyle escape edilirÖrnekBaşarısız olan yanlış seçim
HTML öğe içeriğiHTML varlıkları (< > &)<strong>&lt;strong&gt;< karakterini ham bırakmak bir etiket enjekte eder
HTML öznitelik değeriHTML varlıkları (" ' kritik)"hi"&quot;hi&quot;Escape edilmemiş bir " dışarı kaçar
<script> / satır içi JSJS / JSON dizge escape’i"\"HTML varlıkları JS içinde işlevsizdir
URL / sorgu dizesiYüzde kodlamasıboşluk → %20&amp; ve varlıklar URL’yi yine de bozar

Adlı mı sayısal mı: hangisini kullanmalısınız?

Adlı varlıklar okunabilirdir ve yaygın ayrılmış karakterler ile iyi bilinen simgeler için doğru varsayılandır: &lt;, &amp;, &copy;, &mdash;. Ancak yalnızca tanımlı bir adı olan karakterler için vardır. Ondalık veya onaltılık sayısal varlıklar, adı olmayanlar dahil herhangi bir kod noktasını kodlayabilir; bu da onları evrensel yedek seçenek yapar. Tüketen sistemin belirli bir adlı varlığı desteklediğini garanti edemediğinizde, güvenli seçim sayısaldır.

Kesme işareti neden &#x27; olup &apos; değil

&apos; adlı varlığı yalnızca HTML5 ve XML ile getirildi. HTML4’te tanımsızdır, bu yüzden bir avuç eski ayrıştırıcı ve e-posta istemcisi onu bir kesme işareti yerine düz metin &apos; olarak işler. &#x27; sayısal başvurusu ve onun ondalık ikizi &#39; tam olarak aynı karaktere, U+0027, işaret eder ve yazılmış her standart uyumlu ayrıştırıcı tarafından anlaşılır. he gibi iyi test edilmiş escape kütüphaneleri, tek tırnak için tam da bu nedenle &#x27; üretir ve iyi bir kodlayıcı, çıktının herhangi bir HTML, XML veya öznitelik bağlamına güvenle bırakılabilmesi için bu kurala uyar.

Karakter kümesi mi varlıklar mı: ASCII dışı ne zaman kodlanır

UTF-8 gibi bir karakter kümesi, karakterlerin baytlar olarak nasıl saklanacağına karar verir. Bir varlık ise bir karakteri yalnızca düz ASCII (&, #, ;, harfler, rakamlar) kullanarak yazmanın yoludur. Bunlar farklı katmanlardır ve onları birbirine karıştırmak gereksiz kodlamaya yol açar.

Bir UTF-8 sayfasında, yani <meta charset="utf-8"> bildiren hemen hemen her modern sayfada, vurgulu harfler, çizgiler ve emoji geçerli ham karakterlerdir. é, ve 😀 karakterlerini tam olduğu gibi bırakın. Her şeyi varlıklara kodlamak yalnızca metnin eski tek baytlı bir karakter kümesinden ya da ham UTF-8’i bozan bir sistemden sağ çıkması gerektiğinde önem taşır; “tüm ASCII dışını kodla” modu bu durumlar için vardır. Baytların, kod noktalarının ve karakterlerin nasıl ilişkilendiğinden emin değilseniz, UTF-8, UTF-16 ve Unicode kodlama kılavuzu modeli ortaya koyar.

Yaygın HTML varlık tuzakları

& karakterini en son escape etmek çift escape’e yol açar

Sıra önemlidir. < ve > karakterlerini & öncesinde değiştirirseniz, az önce oluşturduğunuz varlıkların (&lt;, &gt;) başındaki & de escape edilir, böylece < sonunda &amp;lt; olur ve düz metin &lt; olarak görünür. Her zaman önce & karakterini, sonra geri kalanını escape edin. Bu tek kural, var olan en yaygın kodlama hatasını önler.

Zaten escape edilmiş metni çift kodlamak

Zaten escape edilmiş bir metni bir kodlayıcıdan tekrar geçirmek, onu yeniden kodlar. &amp; karakteri &amp;amp; olur ve ziyaretçi sayfada & yerine &amp; görür. Tam olarak bir kez, çıktı anında escape edin. Bir değer birkaç katmandan geçiyorsa, yalnızca birinin escape ettiğinden emin olun.

Çözerken mojibake

Diğer yöne gitmenin de kendi tuzağı vardır. Yanlış karakter kümesiyle çözün ya da iki kez çözün, bozuk çıktı elde edersiniz; klasik mojibake. Bir sayfa, < beklediğiniz yerde düz metin &amp;lt; gösteriyorsa, varlıkların tam olarak neye çözümlendiğini görmek için onu HTML Varlık Çözücü aracına yapıştırın; adlı, ondalık, onaltılık ve hatta sonunda noktalı virgül olmayan &copy gibi eski sonlandırılmamış başvuruları bile işler.

Escape’e eksiksiz bir XSS çaresi olarak güvenmek

Escape ilk savunma hattıdır, tek hattı değil. HTML’de farklı kurallara sahip birkaç bağlam olduğu için, yanlışı için escape etmek bir açık bırakır: özniteliklerdeki tırnaklar, betikteki JS escape’i, URL’lerdeki yüzde kodlaması. Doğru, bağlama duyarlı escape’i bir İçerik Güvenliği Politikası (CSP) ve çerçevenizin otomatik escape’iyle birlikte kullanın. Varlık kodlamasını temel olarak düşünün; CSP ve çerçeve varsayılanları onun üzerine katmanlanır.

Pratikte varlıklar nasıl kodlanır ve çözülür

HTML’i elle inşa ettiğinizde, escape’i kendiniz yaparsınız. İşte &-önce sıralamasını işleyen doğru bir escapeHtml() ile gerçek uygulama kodu için daha iyi uygulama.

// The five reserved characters and their safe entities:
//   <  →  &lt;     >  →  &gt;     &  →  &amp;     "  →  &quot;     '  →  &#x27;

function escapeHtml(str) {
  return str
    .replace(/&/g, '&amp;')   // & FIRST, so later entities are not double-escaped
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#x27;'); // numeric form — safe in HTML4, HTML5 and XML
}

const userInput = `<a href="x">Tom & Jerry's</a>`;
const safe = escapeHtml(userInput);
// → &lt;a href=&quot;x&quot;&gt;Tom &amp; Jerry&#x27;s&lt;/a&gt;

// Better in app code: let the platform escape for you.
//   el.textContent = userInput;   // the browser escapes; no manual replace
//   React / Vue / Angular escape interpolated text by default
//   Server templates (Jinja, ERB, Blade) auto-escape unless you opt out

Elle yazılmış işlev, ne olup bittiğini anlamak ve tek seferlik dönüşümler için yararlıdır, ancak üretimde yerleşik yolu tercih edin. element.textContent ayarlamak, tarayıcının sizin yerinize escape etmesini sağlar ve modern çerçeveler aradeğerlenmiş değerleri otomatik olarak escape eder. Elle escape’i, platformun kapsamadığı durumlara saklayın.

Hızlı işler için HTML Varlık Kodlayıcı ayrılmış kümeyi escape eder (adlı, ondalık veya onaltılık) ve HTML Varlık Çözücü bunu tersine çevirir. İkisi ayrılmış karakterler için tam terslerdir, böylece metni kayıpsız olarak ikisinden de geçirip geri döndürebilirsiniz.

Sıkça sorulan sorular

HTML varlığı nedir?

HTML varlığı, & ile başlayan ve ; ile biten, tek bir karakteri temsil eden kısa bir koddur. Tarayıcı, varlığın işaret ettiği karakteri işaretleme olarak ele almak yerine onu işler. Örneğin &lt; düz bir < gösterir, &amp; ise düz bir & gösterir.

HTML’de hangi karakterleri escape etmem gerekir?

Beş ayrılmış HTML özel karakteri: <, >, &, " ve '. Öğe içeriğinde temel olarak <, > ve & gerekir; öznitelik değerlerinde " ve ' tırnakları da kritik hale gelir. Diğer varlıkların çift escape edilmemesi için önce & ampersand’ını escape edin.

Adlı mı yoksa sayısal (ondalık/onaltılık) varlıkları mı kullanmalıyım?

Tanınması kolay olduklarından, yaygın karakterlerle okunabilirlik için adlı varlıkları (&lt;, &copy;) kullanın. Tanımlı bir adı olmayan bir karakteri kodlamanız gerektiğinde ya da tüketicinin belirli bir adlı varlığı desteklediğini garanti edemediğinizde sayısal varlıkları (ondalık &#60; veya onaltılık &#x3C;) kullanın. Her iki biçim de aynı kod noktasına başvurur.

HTML varlıkları XSS’e karşı koruma sağlar mı?

Doğru uygulandığında temeli oluştururlar. Güvenilmeyen girdiyi HTML öğe veya öznitelik içeriğine yerleştirmeden önce beş ayrılmış karakteri escape etmek, etiket ve betik enjeksiyonunu durdurur. Ancak escape bağlama bağlıdır: betik blokları JavaScript escape’i, URL’ler ise yüzde kodlaması gerektirir. Doğru, bağlama duyarlı escape’i CSP ve çerçeve otomatik escape’iyle birleştirin.

Sayfam neden < yerine &amp;lt; gösteriyor?

Bu çift escape’tir. Metin iki kez kodlandı ya da & köşeli açılardan sonra escape edildi, böylece &lt; içindeki & karakteri &amp; haline geldi. Ziyaretçi de bunun üzerine &lt; ifadesini düz metin olarak görür. Tam olarak bir kez escape edin ve her zaman önce & karakterini escape edin. Çözücü aracı, varlıkların neye çözümlendiğini doğrulayabilir.

é, — veya emoji gibi karakterleri escape etmem gerekir mi?

Genellikle hayır. <meta charset="utf-8"> bildiren bir sayfada vurgulu harfler, çizgiler ve emoji geçerli ham karakterlerdir ve hiçbir kodlama gerektirmez; onları olduğu gibi bırakın. ASCII dışını yalnızca metnin eski tek baytlı bir karakter kümesinden ya da ham UTF-8’i bozan bir sistemden geçmesi gerektiğinde kodlayın.

Etiketler: HTML Encoding Security Web