HTL Tutorial #4: Context-Aware XSS Protection
HTL Tutorial #4: Context-Aware XSS Protection
Cos'è XSS?
Cross-Site Scripting (XSS) è una vulnerabilità che permette agli attaccanti di iniettare codice JavaScript malevolo nelle pagine web.
Esempio di attacco XSS:
// Un utente inserisce questo in un campo "nome":
<script>alert('Hacked!');</script>
// Senza protezione, viene eseguito:
<p>Ciao <script>alert('Hacked!');</script></p> ❌ PERICOLOSO!La Soluzione di HTL
HTL protegge automaticamente da XSS analizzando il contesto dove l'output viene inserito e applicando l'escaping appropriato.
Escaping Automatico
<!-- Input utente malevolo -->
${properties.userInput} <!-- contiene: <script>alert('XSS')</script> -->
<!-- HTL output sicuro: -->
<script>alert('XSS')</script>Il codice viene visualizzato come testo, non eseguito!
I 17 Context di HTL
HTL riconosce automaticamente 17 diversi contesti e applica l'escaping corretto per ognuno.
1. context='html' (DEFAULT)
Contesto: Contenuto HTML normale Comportamento: Rimuove markup potenzialmente pericoloso
<!-- Automatico nel contenuto HTML -->
<div>${properties.content}</div>
<!-- Esplicito -->
<div>${properties.content }</div>Esempio:
<!-- Input -->
${properties.text} <!-- "Hello <b>World</b> <script>alert('xss')</script>" -->
<!-- Output -->
Hello <b>World</b> <!-- <script> rimosso! -->2. context='text'
Contesto: Testo puro (codifica TUTTO l'HTML) Uso: Quando vuoi mostrare HTML come testo
<pre>${properties.codeSnippet }</pre>Esempio:
<!-- Input -->
${'<div>HTML Code</div>' }
<!-- Output (visibile come testo) -->
<div>HTML Code</div>3. context='attribute'
Contesto: Valori di attributi HTML generici
<div title="${properties.tooltip @ context='attribute'}">
Hover me
</div>4. context='uri'
Contesto: URL/URI (href, src, action) Comportamento: Blocca javascript:, data:, vbscript: pericolosi
<!-- Sicuro -->
<a href="${properties.link @ context='uri'}">Link</a>
<!-- Se properties.link = "javascript:alert('XSS')" -->
<!-- HTL blocca e output: "#" -->Esempio pratico:
<!-- Link esterni -->
<a href="${properties.externalLink @ context='uri'}" target="_blank">
Visita il sito
</a>
<!-- Download -->
<a href="${properties.downloadUrl @ context='uri'}" download>
Scarica PDF
</a>
<!-- Immagini -->
<img src="${properties.imageUrl @ context='uri'}" alt="${properties.alt}">5. context='elementName'
Contesto: Nome tag HTML dinamico Comportamento: Whitelist di tag permessi
<${properties.tagName }>
Contenuto
</${properties.tagName }>Esempio:
<!-- properties.tagName = "article" -->
<article>Contenuto</article> ✓
<!-- properties.tagName = "script" -->
<!-- Bloccato! Output: <div> come fallback -->6. context='attributeName'
Contesto: Nome attributo dinamico
<div ${properties.attrName @ context='attributeName'}="value">
Content
</div>7-10. JavaScript Contexts
context='scriptToken'
JavaScript token (variabili, funzioni):
<script>
var ${properties.varName @ context='scriptToken'} = 'value';
</script>context='scriptString'
Stringhe JavaScript:
<script>
var message = '${properties.message @ context='scriptString'}';
</script>context='scriptComment'
Commenti JavaScript:
<script>
/* ${properties.comment @ context='scriptComment'} */
</script>context='scriptRegExp'
Regular expressions:
<script>
var pattern = /${properties.pattern @ context='scriptRegExp'}/g;
</script>11-13. CSS Contexts
context='styleToken'
Token CSS (proprietà, valori):
<div style="color: ${properties.color @ context='styleToken'}">
Text
</div>context='styleString'
Stringhe CSS:
<style>
.class::before {
content: '${properties.content @ context='styleString'}';
}
</style>context='styleComment'
Commenti CSS:
<style>
/* ${properties.comment @ context='styleComment'} */
</style>14. context='comment'
Contesto: Commenti HTML
<!-- ${properties.comment @ context='comment'} -->15. context='number'
Contesto: Solo valori numerici
<input type="number" value="${properties.age @ context='number'}">Esempio:
<!-- Input: "25abc" -->
${properties.value }
<!-- Output: "25" (solo numero) -->
<!-- Input: "not a number" -->
${properties.value }
<!-- Output: "0" (fallback) -->16. context='unsafe' ⚠️
ATTENZIONE: Disabilita TUTTA la protezione XSS!
Usa SOLO se:
- Il contenuto proviene da fonte assolutamente fidata
- Il contenuto è già stato sanitizzato
- Sai esattamente cosa stai facendo
<!-- ⚠️ PERICOLOSO se source non è sicura! -->
<div>${properties.richText }</div>Alternativa sicura:
Usa context='html' che rimuove script malevoli ma mantiene markup sicuro.
Rilevamento Automatico del Context
HTL rileva automaticamente il context basandosi sulla posizione:
<!-- Context HTML (auto) -->
<p>${properties.text}</p>
<!-- Context ATTRIBUTE (auto) -->
<div class="${properties.cssClass}"></div>
<!-- Context URI (auto) -->
<a href="${properties.url}">Link</a>
<img src="${properties.image}">
<!-- Context TEXT nei text node -->
${properties.plainText}Quando Specificare il Context Manualmente
1. JavaScript Inline
<script>
// DEVI specificare il context!
var data = '${properties.data @ context='scriptString'}';
</script>2. CSS Inline
<style>
.custom {
color: ${properties.color @ context='styleToken'};
}
</style>3. Attributi Dinamici
<div ${properties.attrName @ context='attributeName'}="${properties.attrValue @ context='attribute'}">
</div>Esempio Completo: User Profile Card
<div class="profile-card" data-sly-use.user="com.example.UserModel">
<!-- Text content - auto HTML context -->
<h2>${user.name}</h2>
<!-- Bio (può contenere <b>, <i> etc) - HTML context permette markup sicuro -->
<p>${user.bio }</p>
<!-- Avatar image - auto URI context -->
<img src="${user.avatarUrl}" alt="${user.name}">
<!-- Social link - URI context esplicito per sicurezza -->
<a href="${user.website @ context='uri'}" target="_blank">
Website
</a>
<!-- Attributo data dinamico -->
<div data-user-id="${user.id @ context='attribute'}">
<!-- JavaScript context -->
<script>
var userName = '${user.name @ context='scriptString'}';
var userId = ${user.id @ context='scriptToken'};
console.log('User: ' + userName);
</script>
</div>
<!-- Badge con HTML sicuro ma limitato -->
<span class="badge">${user.badgeHtml }</span>
</div>Best Practice
- Lascia che HTL scelga automaticamente quando possibile
- Specifica sempre il context in
<script>e<style> - Mai usare
context='unsafe'su input utente - Usa
context='html'invece diunsafeper rich text - URI context blocca automaticamente link pericolosi
- Number context per input numerici - previene injection
- Test i tuoi context con input malevoli durante lo sviluppo
Tabella Riepilogativa
| Context | Uso | Esempi |
|---|---|---|
html |
Contenuto HTML (default) | <div>${text}</div> |
text |
Testo puro encoded | <pre>${code}</pre> |
attribute |
Attributi generici | <div title="${tip}"> |
uri |
URL/Link | <a href="${link}"> |
elementName |
Tag dinamici | <${tag}>content</${tag}> |
attributeName |
Attributi dinamici | <div ${attr}="val"> |
scriptToken |
JS tokens | var ${name} = value; |
scriptString |
Stringhe JS | var s = '${text}'; |
styleToken |
CSS token | color: ${color} |
number |
Solo numeri | value="${age}" |
unsafe |
NO escaping ⚠️ | Evita se possibile! |
Test di Sicurezza
Prova questi input malevoli nei tuoi componenti:
<script>alert('XSS')</script>
javascript:alert('XSS')
<img src=x onerror="alert('XSS')">
" onload="alert('XSS')
');alert('XSS');//HTL dovrebbe bloccarli automaticamente!
Prossima Lezione
Nella prossima lezione inizieremo con i block statements, partendo da data-sly-text per l'output di contenuto.
Lezione #4 della serie HTL Tutorial. ← Lezione precedente | Lezione successiva →