Κουίζ: μπορείτε να αμυνθείτε ενάντια στην ευπάθεια XSS;

πριν από 2 χρόνια Από David Grudl  

Δοκιμάστε τις γνώσεις σας στο κουίζ ασφαλείας! Μπορείτε να εμποδίσετε έναν εισβολέα να πάρει τον έλεγχο μιας σελίδας HTML;

Σε όλες τις εργασίες θα λύσετε την ίδια ερώτηση: πώς να εμφανίσετε σωστά τη μεταβλητή $str σε μια σελίδα HTML ώστε να μην προκύψει ευπάθεια XSS. Η βάση της άμυνας είναι το escaping, το οποίο σημαίνει την αντικατάσταση χαρακτήρων με ειδική σημασία με τις αντίστοιχες ακολουθίες. Για παράδειγμα, κατά την εμφάνιση μιας συμβολοσειράς σε κείμενο HTML, όπου ο χαρακτήρας < έχει ειδική σημασία (σηματοδοτεί την αρχή ενός tag), τον αντικαθιστούμε με την οντότητα HTML &lt; και ο περιηγητής εμφανίζει σωστά το σύμβολο <.

Να είστε προσεκτικοί, γιατί η ευπάθεια XSS είναι πολύ σοβαρή. Μπορεί να προκαλέσει την ανάληψη ελέγχου της σελίδας ή ακόμα και του λογαριασμού χρήστη από έναν εισβολέα. Καλή επιτυχία και να καταφέρετε να διατηρήσετε την σελίδα HTML ασφαλή!

Οι τρεις πρώτες ερωτήσεις

Αναφέρετε ποιοι χαρακτήρες και με ποιον τρόπο πρέπει να αντιμετωπιστούν στο πρώτο, δεύτερο και τρίτο παράδειγμα:

1) <p><?= $str ?></p>
2) <input value="<?= $str ?>">
3) <input value='<?= $str ?>'>

Αν η έξοδος δεν αντιμετωπιζόταν καθόλου, θα γινόταν μέρος της εμφανιζόμενης σελίδας. Αν ένας εισβολέας εισήγαγε στη μεταβλητή τη συμβολοσειρά 'foo" onclick="evilCode()' και η έξοδος δεν αντιμετωπιζόταν, θα προκαλούσε την εκτέλεση του κώδικά του κατά το κλικ στο στοιχείο:

$str = 'foo" onclick="evilCode()'
❌ χωρίς επεξεργασία: <input value="foo" onclick="evilCode()">
✅ με επεξεργασία:  <input value="foo&quot; onclick=&quot;evilCode()">

Λύσεις των μεμονωμένων παραδειγμάτων:

  1. οι χαρακτήρες < και & αντιπροσωπεύουν την αρχή ενός HTML tag και οντότητας, τους αντικαθιστούμε με &lt; και &amp;
  2. οι χαρακτήρες " και & αντιπροσωπεύουν το τέλος της τιμής του attribute και την αρχή μιας HTML οντότητας, τους αντικαθιστούμε με &quot; και &amp;
  3. οι χαρακτήρες ' και & αντιπροσωπεύουν το τέλος της τιμής του attribute και την αρχή μιας HTML οντότητας, τους αντικαθιστούμε με &apos; και &amp;

Για κάθε σωστή απάντηση κερδίζετε έναν πόντο. Φυσικά, και στις τρεις περιπτώσεις μπορούν να αντικατασταθούν και άλλοι χαρακτήρες με οντότητες, αυτό δεν βλάπτει, αλλά δεν είναι απαραίτητο.

Ερώτηση αρ. 4

Συνεχίζουμε. Ποιοι χαρακτήρες πρέπει να αντικατασταθούν κατά την εμφάνιση της μεταβλητής σε αυτό το πλαίσιο;

<input value=<?= $str ?>>

Λύση: Όπως βλέπετε, εδώ λείπουν τα εισαγωγικά. Ο ευκολότερος τρόπος είναι απλά να προσθέσετε τα εισαγωγικά και στη συνέχεια να κάνετε escape όπως στην προηγούμενη ερώτηση. Υπάρχει και μια δεύτερη λύση, και αυτή είναι να αντικαταστήσετε στη συμβολοσειρά με οντότητες HTML το κενό και όλους τους χαρακτήρες που έχουν ειδική σημασία μέσα στο tag, δηλαδή >, /, = και κάποια άλλα.

Ερώτηση αρ. 5

Τώρα αρχίζει να γίνεται πιο ενδιαφέρον. Ποιοι χαρακτήρες πρέπει να αντιμετωπιστούν σε αυτό το πλαίσιο:

<script>
	let foo = '<?= $str ?>';
</script>

Λύση: Μέσα στο tag <script> οι κανόνες για το escaping καθορίζονται από τη JavaScript. Οι οντότητες HTML δεν χρησιμοποιούνται εδώ, ωστόσο ισχύει ένας ειδικός κανόνας. Ποιους χαρακτήρες λοιπόν κάνουμε escape; Μέσα σε μια συμβολοσειρά JavaScript κάνουμε escape φυσικά τον χαρακτήρα ', ο οποίος την οριοθετεί, και αυτό με τη χρήση πλάγιας καθέτου, δηλαδή τον αντικαθιστούμε με \'. Δεδομένου ότι η JavaScript δεν υποστηρίζει συμβολοσειρές πολλαπλών γραμμών (μόνο ως template literal), πρέπει να κάνουμε escape και τους χαρακτήρες τέλους γραμμής. Ωστόσο, προσοχή, εκτός από τους συνηθισμένους χαρακτήρες \n και \r, η JavaScript θεωρεί ως τέλος γραμμής και τους unicode χαρακτήρες \u2028 και \u2029, τους οποίους πρέπει να κάνουμε escape επίσης. Και τέλος, ο αναφερόμενος ειδικός κανόνας: στη συμβολοσειρά δεν πρέπει να εμφανιστεί το </script. Αυτό μπορεί να αποφευχθεί π.χ. αντικαθιστώντας το με <\/script.

Αν το γνωρίζατε αυτό, συγχαρητήρια.

Ερώτηση αρ. 6

Το ακόλουθο πλαίσιο φαίνεται απλώς σαν μια παραλλαγή του προηγούμενου. Τι νομίζετε, θα διαφέρει η αντιμετώπιση;

<p onclick="foo('<?= $str ?>')"></p>

Λύση: Και πάλι εδώ ισχύουν οι κανόνες για το escaping σε συμβολοσειρές JavaScript, αλλά σε αντίθεση με το προηγούμενο πλαίσιο, όπου δεν γινόταν escape με οντότητες HTML, εδώ αντίθετα γίνεται escape. Δηλαδή, πρώτα κάνουμε escape τη συμβολοσειρά JavaScript με πλάγιες καθέτους και στη συνέχεια αντικαθιστούμε τους χαρακτήρες με ειδική σημασία (" και &) με οντότητες HTML. Προσοχή, η σωστή σειρά είναι σημαντική.

Όπως βλέπετε, το ίδιο JavaScript literal μπορεί να κωδικοποιηθεί διαφορετικά στο στοιχείο <script> και διαφορετικά σε ένα attribute!

Ερώτηση αρ. 7

Ας επιστρέψουμε από τη JavaScript πίσω στην HTML. Ποιους χαρακτήρες πρέπει να αντικαταστήσουμε μέσα στο σχόλιο και με ποιον τρόπο;

<!-- <?= $str ?> -->

Λύση: μέσα σε ένα σχόλιο HTML (και XML) όλοι οι παραδοσιακοί ειδικοί χαρακτήρες, όπως <, &, " και ', μπορούν να εμφανιστούν. Απαγορεύεται, και αυτό ίσως σας εκπλήξει, το ζεύγος χαρακτήρων --. Το escaping αυτής της ακολουθίας δεν καθορίζεται, οπότε εξαρτάται από εσάς με ποιον τρόπο θα την αντικαταστήσετε. Μπορείτε να τα παρεμβάλετε με κενά. Ή ίσως να τα αντικαταστήσετε με ==.

Ερώτηση αρ. 8

Πλησιάζουμε στο τέλος, οπότε ας δοκιμάσουμε να αλλάξουμε την ερώτηση. Προσπαθήστε να σκεφτείτε τι πρέπει να προσέξετε κατά την εμφάνιση της μεταβλητής σε αυτό το πλαίσιο:

<a href="<?= $str ?>">...</a>

Λύση: εκτός από το escaping, είναι σημαντικό να επαληθεύσετε ότι το URL δεν περιέχει επικίνδυνο σχήμα όπως javascript:, επειδή ένα τέτοιο URL, αν κλικαριστεί, θα καλούσε τον κώδικα του εισβολέα.

Ερώτηση αρ. 9

Στο τέλος, ένα κερασάκι για τους πραγματικούς γνώστες. Πρόκειται για ένα παράδειγμα εφαρμογής που χρησιμοποιεί ένα σύγχρονο JavaScript framework, συγκεκριμένα το Vue. Για να δούμε αν θα σκεφτείτε τι πρέπει να προσέξετε κατά την εμφάνιση της μεταβλητής μέσα στο στοιχείο #app:

<div id="app">
    <?= $str ?>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
    el: '#app',
    ...
})
</script>

Αυτός ο κώδικας δημιουργεί μια εφαρμογή Vue που θα αποδοθεί στο στοιχείο #app. Η Vue αντιλαμβάνεται το περιεχόμενο αυτού του στοιχείου ως το template της. Και μέσα στο template ερμηνεύει τα διπλά άγκιστρα, τα οποία σημαίνουν εμφάνιση μεταβλητής ή κλήση κώδικα javascript (π.χ. {{ foo }}).

Επομένως, μέσα στο στοιχείο #app, εκτός από τους χαρακτήρες < και &, ειδική σημασία έχει και το ζεύγος {{, το οποίο πρέπει να αντικαταστήσουμε με άλλη αντίστοιχη ακολουθία, ώστε η Vue να μην το ερμηνεύσει ως δικό της tag. Η αντικατάσταση με οντότητες HTML, ωστόσο, δεν βοηθά σε αυτή την περίπτωση. Πώς να το αντιμετωπίσουμε; Λειτουργεί ένα κόλπο: ανάμεσα στα άγκιστρα εισάγουμε ένα κενό σχόλιο HTML {<!-- -->{ και η Vue αγνοεί μια τέτοια ακολουθία.

Αποτελέσματα κουίζ

Πώς τα πήγατε στο κουίζ; Πόσες σωστές απαντήσεις έχετε; Αν απαντήσατε σωστά σε τουλάχιστον 4 ερωτήσεις, ανήκετε στο 8% των καλύτερων λυτών – συγχαρητήρια!

Ωστόσο, για να διασφαλίσετε την ασφάλεια του ιστότοπού σας, είναι απαραίτητο να επεξεργάζεστε σωστά την έξοδο σε όλες τις καταστάσεις.

Αν σας εξέπληξε πόσα διαφορετικά πλαίσια μπορούν να εμφανιστούν σε μια συνηθισμένη σελίδα HTML, να ξέρετε ότι δεν αναφέραμε ούτε κατά διάνοια όλα. Αυτό θα έκανε το κουίζ πολύ μεγαλύτερο. Παρόλα αυτά, δεν χρειάζεται να είστε ειδικός στο escaping σε κάθε πλαίσιο, αν το σύστημα template σας μπορεί να το χειριστεί.

Ας τα δοκιμάσουμε λοιπόν.

Πώς τα πάνε τα συστήματα template;

Όλα τα σύγχρονα συστήματα template καυχώνται για τη λειτουργία autoescaping, η οποία κάνει αυτόματα escape όλες τις εμφανιζόμενες μεταβλητές. Αν το κάνουν σωστά, ο ιστότοπός σας είναι ασφαλής. Αν το κάνουν λάθος, ο ιστότοπος είναι εκτεθειμένος στον κίνδυνο της ευπάθειας XSS με όλες τις σοβαρές συνέπειες.

Θα δοκιμάσουμε δημοφιλή συστήματα template από τις ερωτήσεις αυτού του κουίζ για να διαπιστώσουμε πόσο αποτελεσματικό είναι το autoescaping τους. Ξεκινά το dTest των συστημάτων template για PHP.

Twig ❌

Πρώτο στη σειρά είναι το σύστημα template Twig (έκδοση 3.5), το οποίο χρησιμοποιείται συχνότερα σε συνδυασμό με το framework Symfony. Θα του αναθέσουμε να απαντήσει σε όλες τις ερωτήσεις του κουίζ. Η μεταβλητή $str θα είναι πάντα γεμάτη με μια πονηρή συμβολοσειρά και θα δούμε πώς θα τα καταφέρει με την εμφάνισή της. Τα αποτελέσματα τα βλέπετε δεξιά. Μπορείτε επίσης να εξερευνήσετε τις απαντήσεις και τη συμπεριφορά του στο playground.

   {% set str = "<'\"&" %}
1) <p>{{ str }}</p>
2) <input value="{{ str }}">
3) <input value='{{ str }}'>

   {% set str = "foo onclick=evilCode()" %}
4) <input value={{ str }}>

   {% set str = "'\"\n\u{2028}" %}
5) <script>	let foo = '{{ str }}'; </script>
6) <p onclick="foo('{{ str }}')"></p>

   {% set str = "-- ---" %}
7) <!-- {{ str }} -->

   {% set str = "javascript:evilCode()" %}
8) <a href="{{ str }}">...</a>

   {% set str = "{{ foo }}" %}
9) <div id="app"> {{ str }} </div>

✅ <p>&lt;&#039;&quot;&amp;</p>
✅ <input value="&lt;&#039;&quot;&amp;">
✅ <input value='&lt;&#039;&quot;&amp;'>


❌ <input value=foo onclick=evilCode()>


❌ <script> let foo = &#039;&quot;u{2028}; </script>
❌ <p onclick="foo(&#039;&quot;u{2028})"></p>


❌ <!-- -- --- -->


❌ <a href="javascript:evilCode()">...</a>


❌ <div id="app"> {{ foo }} </div>

Το Twig απέτυχε σε έξι από τις εννέα δοκιμές!

Δυστυχώς, το αυτόματο escaping του Twig λειτουργεί μόνο σε κείμενο HTML και attributes, και επιπλέον μόνο όταν περικλείονται σε εισαγωγικά. Μόλις λείπουν τα εισαγωγικά, το Twig δεν αναφέρει κανένα σφάλμα και δημιουργεί μια τρύπα ασφαλείας XSS.

Αυτό είναι ιδιαίτερα δυσάρεστο, επειδή έτσι γράφονται οι τιμές των attributes σε δημοφιλείς βιβλιοθήκες όπως το React ή το Svelte. Ένας προγραμματιστής που χρησιμοποιεί ταυτόχρονα Twig και React, μπορεί έτσι εντελώς φυσικά να ξεχάσει τα εισαγωγικά.

Το autoescaping του Twig αποτυγχάνει και σε όλα τα άλλα παραδείγματα. Στα πλαίσια (5) και (6) είναι απαραίτητο το χειροκίνητο escaping με {{ str|escape('js') }}, για άλλα πλαίσια το Twig δεν προσφέρει καν συνάρτηση escaping. Δεν διαθέτει ούτε προστασία από την εμφάνιση κακόβουλου συνδέσμου (8) ούτε υποστήριξη για templates Vue (9).

Blade ❌❌

Ο δεύτερος συμμετέχων είναι το σύστημα template Blade (έκδοση 10.9), το οποίο είναι στενά ενσωματωμένο με το Laravel και το οικοσύστημά του. Και πάλι θα ελέγξουμε τις ικανότητές του στις ερωτήσεις του κουίζ μας. Μπορείτε επίσης να εξερευνήσετε τις απαντήσεις του στο playground.

   @php($str = "<'\"&")
1) <p>{{ $str }}</p>
2) <input value="{{ $str }}">
3) <input value='{{ $str }}'>

   @php($str = "foo onclick=evilCode()")
4) <input value={{ $str }}>

   @php($str = "'\"\n\u{2028}")
5) <script> let foo = {{ $str }}; </script>
6) <p onclick="foo({{ $str }})"></p>

   @php($str = "-- ---")
7) <!-- {{ $str }} -->

   @php($str = "javascript:evilCode()")
8) <a href="{{ $str }}">...</a>

   @php($str = "{{ foo }}")
9) <div id="app"> {{ $str }} </div>

✅ <p>&lt;&#039;&quot;&amp;</p>
✅ <input value="&lt;&#039;&quot;&amp;">
✅ <input value='&lt;&#039;&quot;&amp;'>


❌ <input value=foo onclick=evilCode()>


❌ <script>	let foo = &#039;&quot; ; </script>
❌ <p onclick="foo(&#039;&quot; )"></p>


❌ <!-- -- --- -->


❌ <a href="javascript:evilCode()">...</a>


❌❌ <div id="app"> &lt;?php echo e(foo); ?&gt; </div>

Το Blade απέτυχε σε έξι από τις εννέα δοκιμές!

Το αποτέλεσμα είναι παρόμοιο με του Twig. Και πάλι ισχύει ότι το αυτόματο escaping λειτουργεί μόνο σε κείμενο HTML και attributes και μόνο αν περικλείονται σε εισαγωγικά. Το autoescaping του Blade αποτυγχάνει και σε όλα τα άλλα παραδείγματα. Στα πλαίσια (5) και (6) είναι απαραίτητο το χειροκίνητο escaping με {{ Js::from($str) }}. Για άλλα πλαίσια το Blade δεν προσφέρει καν συνάρτηση escaping. Δεν διαθέτει προστασία από την εμφάνιση κακόβουλου συνδέσμου (8) ούτε υποστήριξη για templates Vue (9).

Αυτό που είναι όμως εκπληκτικό, είναι η αποτυχία της οδηγίας @php στο Blade, η οποία προκαλεί την εμφάνιση του ίδιου του κώδικα PHP απευθείας στην έξοδο, κάτι που βλέπετε στην τελευταία γραμμή.

Smarty ❌❌❌

Τώρα θα δοκιμάσουμε το παλαιότερο σύστημα template για PHP, το οποίο είναι το Smarty (έκδοση 4.3). Προς μεγάλη έκπληξη, αυτό το σύστημα δεν έχει ενεργό αυτόματο escaping. Πρέπει λοιπόν κατά την εμφάνιση μεταβλητών είτε κάθε φορά να δηλώνετε το φίλτρο {$var|escape}, είτε να ενεργοποιήσετε το αυτόματο escaping HTML. Η πληροφορία γι' αυτό είναι αρκετά κρυμμένη στην τεκμηρίωση.

   {$str = "<'\"&"}
1) <p>{$str}</p>
2) <input value="{$str}">
3) <input value='{$str}'>

   {$str = "foo onclick=evilCode()"}
4) <input value={$str}>

   {$str = "'\"\n\u{2028}"}
5) <script>	let foo = {$str}; </script>
6) <p onclick="foo({$str})"></p>

   {$str = "-- ---"}
7) <!-- {$str} -->

   {$str = "javascript:evilCode()"}
8) <a href="{$str}">...</a>

   {$str = "{{ foo }}"}
9) <div id="app"> {$str} </div>

✅ <p>&lt;&#039;&quot;&amp;</p>
✅ <input value="&lt;&#039;&quot;&amp;">
✅ <input value='&lt;&#039;&quot;&amp;'>


❌ <input value=foo onclick=evilCode()>


❌ <script> let foo = &#039;&quot;\u2028; </script>
❌ <p onclick="foo(&#039;&quot;\u2028)"></p>


❌ <!-- -- --- -->


❌ <a href="javascript:evilCode()">...</a>


❌ <div id="app"> {{ foo }} </div>

Το Smarty απέτυχε σε έξι από τις εννέα δοκιμές!

Το αποτέλεσμα είναι με την πρώτη ματιά παρόμοιο με των προηγούμενων βιβλιοθηκών. Το Smarty μπορεί να κάνει αυτόματο escape μόνο σε κείμενο HTML και attributes, και αυτό μόνο όταν οι τιμές περικλείονται σε εισαγωγικά. Παντού αλλού αποτυγχάνει. Στα πλαίσια (5) και (6) είναι απαραίτητο το χειροκίνητο escaping με {$str|escape:javascript}. Αλλά αυτό είναι δυνατό μόνο όταν δεν είναι ενεργό το αυτόματο escaping HTML, αλλιώς αυτά τα escapings συγκρούονται μεταξύ τους. Το Smarty είναι έτσι από άποψη ασφάλειας η απόλυτη αποτυχία αυτού του τεστ.

Latte ✅

Την τριάδα κλείνει το σύστημα template Latte (έκδοση 3.0). Θα δοκιμάσουμε το autoescaping του. Μπορείτε επίσης να εξερευνήσετε τις απαντήσεις και τη συμπεριφορά του στο playground.

   {var $str = "<'\"&"}
1) <p>{$str}</p>
2) <input value="{$str}">
3) <input value='{$str}'>

   {var $str = "foo onclick=evilCode()"}
4) <input value={$str}>

   {var $str = "'\"\n\u{2028}"}
5) <script>	let foo = {$str}; </script>
6) <p onclick="foo({$str})"></p>

   {var $str = "-- ---"}
7) <!-- {$str} -->

   {var $str = "javascript:evilCode()"}
8) <a href="{$str}">...</a>

   {var $str = "{{ foo }}"}
9) <div id="app"> {$str} </div>

✅ <p>&lt;'"&amp;</p>
✅ <input value="&lt;&apos;&quot;&amp;">
✅ <input value='&lt;&apos;&quot;&amp;'>


✅ <input value="foo onclick=evilCode()">


✅ <script> let foo = "'\"\n\u2028"; </script>
✅ <p onclick="foo(&quot;&apos;\&quot;\n\u2028&quot;)"></p>


✅ <!--  - -  - - -  -->


✅ <a href="">...</a>


✅ <div id="app"> {<!-- -->{ foo }} </div>

Το Latte διέπρεψε και στις εννέα εργασίες!

Κατάφερε να αντιμετωπίσει τα ελλείποντα εισαγωγικά στα HTML attributes, κατάφερε να επεξεργαστεί τη JavaScript τόσο στο στοιχείο <script> όσο και στα attributes και κατάφερε να αντιμετωπίσει ακόμη και την απαγορευμένη ακολουθία στα σχόλια HTML.

Επιπλέον, απέτρεψε την κατάσταση όπου το κλικ σε έναν πλαστό σύνδεσμο από έναν εισβολέα θα μπορούσε να εκτελέσει τον κώδικά του. Και κατάφερε να αντιμετωπίσει το escaping των tags για τη Vue.

Μπόνους τεστ

Μία από τις ουσιαστικές ικανότητες όλων των συστημάτων template είναι η εργασία με μπλοκ και η σχετική κληρονομικότητα των templates. Θα δοκιμάσουμε λοιπόν να δώσουμε σε όλα τα δοκιμαζόμενα συστήματα template ακόμη μία εργασία. Θα δημιουργήσουμε ένα μπλοκ description, το οποίο θα εμφανίσουμε σε ένα HTML attribute. Στον πραγματικό κόσμο, φυσικά, ο ορισμός του μπλοκ θα βρισκόταν στο child-template και η εμφάνισή του στο parent-template, δηλαδή για παράδειγμα στο layout. Αυτή είναι απλώς μια απλοποιημένη μορφή, αλλά αρκεί για να δοκιμάσουμε το autoescaping κατά την εμφάνιση μπλοκ. Πώς τα πήγαν;

Twig: απέτυχε ❌ κατά την εμφάνιση μπλοκ δεν επεξεργάζεται τους χαρακτήρες

{% block description %}
	rock n' roll
{% endblock %}

<meta name='description'
	content='{{ block('description') }}'>




<meta name='description'
	content=' rock n' roll '> ❌

Blade: απέτυχε ❌ κατά την εμφάνιση μπλοκ δεν επεξεργάζεται τους χαρακτήρες

@section('description')
	rock n' roll
@endsection

<meta name='description'
	content='@yield('description')'>




<meta name='description'
	content=' rock n' roll '> ❌

Latte: πέρασε ✅ κατά την εμφάνιση μπλοκ επεξεργάστηκε σωστά τους προβληματικούς χαρακτήρες

{block description}
	rock n' roll
{/block}

<meta name='description'
	content='{include description}'>




<meta name='description'
	content=' rock n&apos; roll '> ✅

Γιατί τόσες πολλές ιστοσελίδες είναι ευάλωτες;

Το autoescaping σε συστήματα όπως το Twig, το Blade ή το Smarty λειτουργεί έτσι ώστε απλά να αντικαθιστά πέντε χαρακτήρες <>"'& με οντότητες HTML και δεν διακρίνει καθόλου το πλαίσιο. Γι' αυτό λειτουργεί μόνο σε ορισμένες περιπτώσεις και σε όλες τις άλλες αποτυγχάνει. Το αφελές autoescaping είναι μια επικίνδυνη λειτουργία, επειδή δημιουργεί μια ψευδή αίσθηση ασφάλειας.

Δεν προκαλεί λοιπόν έκπληξη το γεγονός ότι σήμερα περισσότερο από το 27% των ιστοσελίδων έχουν κρίσιμες ευπάθειες, κυρίως XSS (πηγή: Acunetix Web Vulnerability Report). Πώς να βγούμε από αυτό; Να χρησιμοποιήσουμε ένα σύστημα template που διακρίνει τα πλαίσια.

Το Latte είναι το μοναδικό σύστημα template στην PHP που δεν αντιλαμβάνεται το template απλώς ως μια σειρά χαρακτήρων, αλλά κατανοεί την HTML. Κατανοεί τι είναι τα tags, τα attributes κ.λπ. Διακρίνει τα πλαίσια. Και γι' αυτό κάνει σωστά escape στο κείμενο HTML, διαφορετικά μέσα σε ένα HTML tag, διαφορετικά μέσα στη JavaScript κ.λπ.

Το Latte αποτελεί έτσι το μοναδικό ασφαλές σύστημα template.


Επιπλέον, χάρη στην κατανόηση της HTML, προσφέρει τα υπέροχα n:attributes, τα οποία αγαπούν οι χρήστες:

<ul n:if="$menu">
	<li n:foreach="$menu->getItems() as $item">{$item->title}</li>
</ul>

Πρόσφατες δημοσιεύσεις