Escaping di stringhe HTML con jQuery


609

Qualcuno sa un modo semplice per sfuggire all'HTML dalle stringhe in jQuery ? Devo essere in grado di passare una stringa arbitraria e farla sfuggire correttamente per la visualizzazione in una pagina HTML (evitando attacchi di iniezione JavaScript / HTML). Sono sicuro che è possibile estendere jQuery per farlo, ma al momento non so abbastanza del framework per farlo.


Risposte:


445

Dato che stai usando jQuery , puoi semplicemente impostare la textproprietà dell'elemento :

// before:
// <div class="someClass">text</div>
var someHtmlString = "<script>alert('hi!');</script>";

// set a DIV's text:
$("div.someClass").text(someHtmlString);
// after: 
// <div class="someClass">&lt;script&gt;alert('hi!');&lt;/script&gt;</div>

// get the text in a string:
var escaped = $("<div>").text(someHtmlString).html();
// value: 
// &lt;script&gt;alert('hi!');&lt;/script&gt;

57
Hai perso il punto in cui devi accedere a $ ("div.someClass"). Html () per ottenere la versione con escape.
Morten Christiansen,

16
Questo non è sicuro per tutti i browser se la stringa contiene spazi bianchi e caratteri \ n \ r \ t
nivcaner

20
@travis Questo è documentato sul sito Web di jQuery: "A causa delle variazioni nei parser HTML in diversi browser, il testo restituito può variare in nuove righe e in altri spazi bianchi". api.jquery.com/text
geofflee

3
@mklement se stai già utilizzando questa soluzione, non avrai problemi a fare qualcosa del genere: $(element2).attr("some-attr", $(element1).html());vedi questo esempio: jsbin.com/atibig/1/edit
travis

16
Questo NON sfugge alle virgolette e alle doppie virgolette che è male! wonko.com/post/html-escaping
Lior

601

C'è anche la soluzione da moustache.js

var entityMap = {
  '&': '&amp;',
  '<': '&lt;',
  '>': '&gt;',
  '"': '&quot;',
  "'": '&#39;',
  '/': '&#x2F;',
  '`': '&#x60;',
  '=': '&#x3D;'
};

function escapeHtml (string) {
  return String(string).replace(/[&<>"'`=\/]/g, function (s) {
    return entityMap[s];
  });
}

7
Si noti che, curiosamente, 'è mappato su un'entità con un formato decimale , mentre /utilizza il formato esadecimale .
mklement0

43
Questa dovrebbe essere la risposta accettata: è semplice, efficiente, non richiede dipendenze e fa esattamente ciò che è inteso senza hack oscuri.
Lorefnon,

6
qual è la guida per la conversione \nin <br>?
tra il

2
Ecco un link aggiornato alla fonte: github.com/janl/mustache.js/blob/…
mjackson

8
@amwinter, ho esteso lo script sopra aggiungendo "\ n": '<br>' alla mappa entità e aggiornato regexp a / [& <> "'\ /] | [\ n] / g
walv

182
$('<div/>').text('This is fun & stuff').html(); // "This is fun &amp; stuff"

Fonte: http://debuggable.com/posts/encode-html-entities-with-jquery:480f4dd6-13cc-4ce9-8071-4710cbdd56cb


11
Come menzionato nella risposta sopra, questa soluzione non è garantita per preservare gli spazi bianchi.
Geofflee,

47
Va notato che questo non fa nulla per sfuggire alle virgolette singole o doppie. se hai intenzione di inserire il valore in un attributo HTML, questo può essere un problema.
Kip

6
@Kip: @travis ha scoperto che il attr()metodo di jQuery (almeno 1.8.3) esegue la propria codifica, in modo che le stringhe non codificate possano essere passate direttamente ; ad es .:$('<div/>').attr('test-attr', '\'Tis "fun" & stuff')[0].outerHTML
mklement0

1
@tarekahf È strano. Quale versione di jQuery stai usando? Il codice di esempio funziona se lo si copia e incolla alla lettera? Funziona bene con l'ultima jQuery (3.1.0) qui: jsbin.com/fazimigayo/1/edit?html,js,console,output (e dovrebbe funzionare anche su tutte le versioni precedenti)
Henrik N

1
@tarekahf $('<div/>')crea un nuovo divelemento non collegato al DOM. Quindi non cambierà alcun elemento esistente. È un po 'confuso il modo in cui jQuery utilizza la stessa $()funzione sia per trovare elementi ( $('div')) che per crearli, e per qualche altra cosa oltre a ... :)
Henrik N

61

Se stai scappando per HTML, ce ne sono solo tre che posso pensare che sarebbe davvero necessario:

html.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");

A seconda del caso d'uso, si potrebbe anche bisogno di fare cose come "a &quot;. Se l'elenco diventasse abbastanza grande, utilizzerei solo un array:

var escaped = html;
var findReplace = [[/&/g, "&amp;"], [/</g, "&lt;"], [/>/g, "&gt;"], [/"/g, "&quot;"]]
for(var item in findReplace)
    escaped = escaped.replace(findReplace[item][0], findReplace[item][1]);

encodeURIComponent() lo sfuggirà solo per gli URL, non per HTML.


13
Questa espressione regolare produrrà strani risultati se l'HTML in questione ha già eseguito la escape di entità. Ad esempio, la fuga da "Tom & amp; Jerry" produrrà "Tom & amp; amp; Jerry"
Ryan

12
Si prega di utilizzare varper dichiarare itemlocalmente; in ogni caso, non usare affatto un for … inloop durante il looping di un array! Utilizzare invece un normale forciclo. Oh, e non lo encodeURIComponentè escapeURIComponent.
Marcel Korpel,

3
Se stai lavorando con gli attributi dei tag, dovrai anche evitare le virgolette e / o le virgolette doppie. La documentazione di PHP per htmlspecialchars contiene un utile elenco di conversioni che esegue. php.net/htmlspecialchars
geofflee

4
Solo un promemoria sorta di nuove persone, non utilizzare questo se avete intenzione di avere i caratteri non inglesi da qualche parte sul tuo sito web ... Ovviamente questo non lo farà a causa dei caratteri con accenti come 'é': &eacute; Ecco un elenco di entità html, per riferimento: w3schools.com/tags/ref_entities.asp
LoganWolfer

11
@Ryan: Anche se vale la pena sottolineare che questa soluzione non gestisce correttamente le stringhe già codificate, non vale nulla che lo stesso valga per la maggior parte - possibilmente per tutte - le soluzioni in questa pagina.
mklement0,

37

Abbastanza facile da usare il trattino basso:

_.escape(string) 

Underscore è una libreria di utilità che fornisce molte funzionalità che js nativo non fornisce. C'è anche lodash che è la stessa API del trattino basso ma è stato riscritto per essere più performante.


36

Ho scritto una piccola funzione che fa questo. Sfugge solo ", &, <e >(ma di solito questo è tutto quello che in ogni caso bisogno). È leggermente più elegante delle soluzioni proposte in precedenza in quanto ne utilizza solo una .replace() per fare tutta la conversione. ( EDIT 2: complessità del codice ridotta che rende la funzione ancora più piccola e più ordinata, se sei curioso del codice originale vedi fine di questa risposta.)

function escapeHtml(text) {
    'use strict';
    return text.replace(/[\"&<>]/g, function (a) {
        return { '"': '&quot;', '&': '&amp;', '<': '&lt;', '>': '&gt;' }[a];
    });
}

Questo è Javascript semplice, non utilizzato jQuery.

Escaping /e 'troppo

Modifica in risposta al commento di mklement .

La funzione sopra può essere facilmente espansa per includere qualsiasi carattere. Per specificare più caratteri da scappare, è sufficiente inserirli entrambi nella classe di caratteri nell'espressione regolare (ovvero all'interno di /[...]/g) e come una voce chrnell'oggetto. ( EDIT 2: abbreviata anche questa funzione, allo stesso modo.)

function escapeHtml(text) {
    'use strict';
    return text.replace(/[\"&'\/<>]/g, function (a) {
        return {
            '"': '&quot;', '&': '&amp;', "'": '&#39;',
            '/': '&#47;',  '<': '&lt;',  '>': '&gt;'
        }[a];
    });
}

Nota l'uso sopra di &#39;per apostrofo (l'entità simbolica &apos;potrebbe essere stata usata invece - è definita in XML, ma originariamente non era inclusa nelle specifiche HTML e potrebbe quindi non essere supportata da tutti i browser. Vedi: Articolo di Wikipedia sulle codifiche di caratteri HTML ). Ricordo anche di aver letto da qualche parte che l'uso di entità decimali è più ampiamente supportato rispetto all'uso di esadecimali, ma non riesco a trovare l'origine per quello ora. (E non ci possono essere molti browser là fuori che non supportano le entità esadecimali.)

Nota: aggiungere /e 'all'elenco dei caratteri di escape non è poi così utile, poiché non hanno alcun significato speciale in HTML e non devono essere sottoposti a escape.

escapeHtmlFunzione originale

EDIT 2: la funzione originale utilizzava una variabile ( chr) per memorizzare l'oggetto necessario per il .replace()callback. Questa variabile necessitava anche di una funzione anonima aggiuntiva per la sua portata, rendendola (inutilmente) un po 'più grande e complessa.

var escapeHtml = (function () {
    'use strict';
    var chr = { '"': '&quot;', '&': '&amp;', '<': '&lt;', '>': '&gt;' };
    return function (text) {
        return text.replace(/[\"&<>]/g, function (a) { return chr[a]; });
    };
}());

Non ho testato quale delle due versioni sia più veloce. In tal caso, sentiti libero di aggiungere informazioni e collegamenti al riguardo qui.


Grazie per aver dedicato del tempo, @Zrajm. Un buon punto per non aver bisogno di scappare; qualche idea del perché entrambi mustache.jse underscore.jsfarlo? A proposito di quest'ultimo: riconosce solo le entità numeriche (che rappresentano 'e /'), in forma esadecimale maiuscola quando non fuoriesce. Pertanto, il testo è evaso mustache.js- che utilizza curiosamente un mix di esadecimali. e formati decimali - non verrebbero correttamente eliminati underscore.js. Mi chiedo come lo facciano altre biblioteche popolari.
mklement0

1
La forma esagonale inferiore caso è la forma più supportato, così che è (probabilmente) la forma che le librerie dovrebbero convertire a . (Naturalmente entrambi i moduli dovrebbero funzionare durante la conversione da .) - Gli apostrofi 'hanno una sorta di funzione riservata in XML (e quindi XHTML, immagino?), Motivo per cui XML (ma non HTML) hanno l'entità denominata &apos;. Non so esattamente perché o in che modo sia "riservato". - Le barre sono speciali negli URL, ma ciò non le garantisce effettivamente l' inclusione nell'evasione dell'HTML (poiché la codifica URL è qualcosa di completamente diverso).
zrajm,

Ri &apos;: corretto: uso sicuro solo in XHTML ; direttamente dalla bocca del pubblico - sottolineatura mia: "(...) letto da un processore HTML conforme , (...) l'uso di & apos; o riferimenti a entità personalizzate potrebbero non essere supportati (...)" - in pratica : i browser moderni lo supportano anche in HTML . Caso in numeri esadecimali. (stessa fonte; sottolineatura mia): "La x deve essere minuscola nei documenti XML. […] L'hhhh può mescolare maiuscole e minuscole, anche se maiuscole è il solito stile ." Ci lascia stupiti su chi abbia deciso di codificare le barre; forse davvero solo una confusione tra URI e codifica HTML?
mklement0

2
Considerazioni finali: sembra che la codifica /non sia necessaria, ma la codifica 'sembra comunque utile per gestire in modo sicuro il caso in cui una stringa codificata viene utilizzata come valore di attributo racchiuso tra virgolette singole .
mklement0

Entrambi sono lenti. La soluzione più veloce con un margine a doppia cifra è una serie di sostituzioni che vengono passate stringhe anziché funzioni.
Adam Leggett,

34

Mi rendo conto di quanto sono in ritardo per questa festa, ma ho una soluzione molto semplice che non richiede jQuery.

escaped = new Option(unescaped).innerHTML;

Modifica: questo non sfugge alle virgolette. L'unico caso in cui è necessario eseguire l'escape delle virgolette è se il contenuto verrà incollato in linea in un attributo all'interno di una stringa HTML. È difficile per me immaginare un caso in cui fare questo sarebbe un buon design.

Modifica 3: per la soluzione più veloce, controlla la risposta sopra da Saram. Questo è il più corto.


Questo non cambia le virgolette - almeno adesso in Firefox 52.
getsetbro il

1
L'escape delle virgolette è funzionalmente rilevante solo negli attributi. Dal momento che stiamo scappando <e >non vi è alcun vantaggio a sfuggire anche alle virgolette, a meno che l'intento del contenuto generato non sia quello di inserire un attributo.
Adam Leggett,

31

Ecco una funzione JavaScript pulita e chiara. Sfuggirà a testi come "pochi <molti" in "pochi & molti".

function escapeHtmlEntities (str) {
  if (typeof jQuery !== 'undefined') {
    // Create an empty div to use as a container,
    // then put the raw text in and get the HTML
    // equivalent out.
    return jQuery('<div/>').text(str).html();
  }

  // No jQuery, so use string replace.
  return str
    .replace(/&/g, '&amp;')
    .replace(/>/g, '&gt;')
    .replace(/</g, '&lt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&apos;');
}

28

Dopo gli ultimi test, posso consigliare la soluzione javaScript (DOM) nativa più veloce e completamente compatibile con browser :

function HTMLescape(html){
    return document.createElement('div')
        .appendChild(document.createTextNode(html))
        .parentNode
        .innerHTML
}

Se lo ripeti più volte puoi farlo con variabili una volta preparate:

//prepare variables
var DOMtext = document.createTextNode("test");
var DOMnative = document.createElement("span");
DOMnative.appendChild(DOMtext);

//main work for each case
function HTMLescape(html){
  DOMtext.nodeValue = html;
  return DOMnative.innerHTML
}

Guarda il mio confronto finale delle prestazioni ( domanda sullo stack ).


2
È necessario utilizzare due nodi? Che ne dici di uno solo:var p = document.createElement('p'); p.textContent = html; return p.innerHTML;
Dan Dascalescu,

2
@DanDascalescu: Secondo MDN , la textContentfunzione è supportata solo da Chrome 1+, Firefox 2, IE9, Opera 9.64 e Safari 3 (questi ultimi due annotati "forse prima"). In tal modo infrangerebbe l'affermazione "completamente compatibile tra browser" dei PO.
zb226,

p.innerText = html; return p.innerHTML
Bekim Bacaj,

24

Prova Underscore.string lib, funziona con jQuery.

_.str.escapeHTML('<div>Blah blah blah</div>')

produzione:

'&lt;div&gt;Blah blah blah&lt;/div&gt;'

20
La libreria di sottolineatura principale ora ha una _.escape()funzione di utilità.
codeape,

15

Ho migliorato l'esempio mustache.js aggiungendo il escapeHTML()metodo all'oggetto stringa.

var __entityMap = {
    "&": "&amp;",
    "<": "&lt;",
    ">": "&gt;",
    '"': '&quot;',
    "'": '&#39;',
    "/": '&#x2F;'
};

String.prototype.escapeHTML = function() {
    return String(this).replace(/[&<>"'\/]/g, function (s) {
        return __entityMap[s];
    });
}

In questo modo è abbastanza facile da usare "Some <text>, more Text&Text".escapeHTML()


Utile, ma mi sono anche spostato __entityMapnella funzione ambito locale. E tutto if (typeof String.prototype.escapeHTML !== 'function'){...}
finito

15

escape()e unescape()intendono codificare / decodificare stringhe per URL, non HTML.

In realtà, uso il seguente frammento per fare il trucco che non richiede alcun framework:

var escapedHtml = html.replace(/&/g, '&amp;')
                      .replace(/>/g, '&gt;')
                      .replace(/</g, '&lt;')
                      .replace(/"/g, '&quot;')
                      .replace(/'/g, '&apos;');

Se stai per avere "s allora devi aggiungere almeno 'e `` alla mischia. Questi sono davvero necessari solo per i dati dei tag stringa all'interno di elementi in HTML. Per i dati html stessi (tag esterni) sono richiesti solo i primi 3.
Marius,

10

Se hai underscore.js, usa _.escape(più efficiente del metodo jQuery pubblicato sopra):

_.escape('Curly, Larry & Moe'); // returns: Curly, Larry &amp; Moe

5

Se stai seguendo la rotta regex, c'è un errore nell'esempio sopra riportato.

<!-- WON'T WORK -  item[0] is an index, not an item -->

var escaped = html; 
var findReplace = [[/&/g, "&amp;"], [/</g, "&lt;"], [/>/g,"&gt;"], [/"/g,
"&quot;"]]

for(var item in findReplace) {
     escaped = escaped.replace(item[0], item[1]);   
}


<!-- WORKS - findReplace[item[]] correctly references contents -->

var escaped = html;
var findReplace = [[/&/g, "&amp;"], [/</g, "&lt;"], [/>/g, "&gt;"], [/"/g, "&quot;"]]

for(var item in findReplace) {
     escaped = escaped.replace(findReplace[item[0]], findReplace[item[1]]);
}

2
Credo che dovrebbe essere per (var item in findReplace) {escaped = escaped.replace (findReplace [item] [0], findReplace [item] [1]); }
Chris Stephens,

5

Questo è un bell'esempio sicuro ...

function escapeHtml(str) {
    if (typeof(str) == "string"){
        try{
            var newStr = "";
            var nextCode = 0;
            for (var i = 0;i < str.length;i++){
                nextCode = str.charCodeAt(i);
                if (nextCode > 0 && nextCode < 128){
                    newStr += "&#"+nextCode+";";
                }
                else{
                    newStr += "?";
                }
             }
             return newStr;
        }
        catch(err){
        }
    }
    else{
        return str;
    }
}

4
Quali tipi di eccezioni stai sopprimendo lì?
Stefan Majewsky,

3

Puoi farlo facilmente con js alla vaniglia.

Aggiungi semplicemente un nodo di testo al documento. Sarà evaso dal browser.

var escaped = document.createTextNode("<HTML TO/ESCAPE/>")
document.getElementById("[PARENT_NODE]").appendChild(escaped)

2
(function(undefined){
    var charsToReplace = {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;'
    };

    var replaceReg = new RegExp("[" + Object.keys(charsToReplace).join("") + "]", "g");
    var replaceFn = function(tag){ return charsToReplace[tag] || tag; };

    var replaceRegF = function(replaceMap) {
        return (new RegExp("[" + Object.keys(charsToReplace).concat(Object.keys(replaceMap)).join("") + "]", "gi"));
    };
    var replaceFnF = function(replaceMap) {
        return function(tag){ return replaceMap[tag] || charsToReplace[tag] || tag; };
    };

    String.prototype.htmlEscape = function(replaceMap) {
        if (replaceMap === undefined) return this.replace(replaceReg, replaceFn);
        return this.replace(replaceRegF(replaceMap), replaceFnF(replaceMap));
    };
})();

Nessuna variabile globale, qualche ottimizzazione della memoria. Uso:

"some<tag>and&symbol©".htmlEscape({'©': '&copy;'})

il risultato è:

"some&lt;tag&gt;and&amp;symbol&copy;"

2

2 metodi semplici che richiedono NO JQUERY ...

Puoi codificare tutti i caratteri nella tua stringa in questo modo:

function encode(e){return e.replace(/[^]/g,function(e){return"&#"+e.charCodeAt(0)+";"})}

O semplicemente indirizzare i personaggi principali di cui preoccuparsi &, interruzioni di linea, <, >, "e 'come:

function encode(r){
return r.replace(/[\x26\x0A\<>'"]/g,function(r){return"&#"+r.charCodeAt(0)+";"})
}

var myString='Encode HTML entities!\n"Safe" escape <script></'+'script> & other tags!';

test.value=encode(myString);

testing.innerHTML=encode(myString);

/*************
* \x26 is &ampersand (it has to be first),
* \x0A is newline,
*************/
<p><b>What JavaScript Generated:</b></p>

<textarea id=test rows="3" cols="55"></textarea>

<p><b>What It Renders Too In HTML:</b></p>

<div id="testing">www.WHAK.com</div>


2

Esempio di escape JavaScript semplice:

function escapeHtml(text) {
    var div = document.createElement('div');
    div.innerText = text;
    return div.innerHTML;
}

escapeHtml("<script>alert('hi!');</script>")
// "&lt;script&gt;alert('hi!');&lt;/script&gt;"

3
Le risposte di solo codice sono sconsigliate perché non spiegano come risolvono il problema. Aggiorna la tua risposta per spiegare come questo migliora rispetto alle altre risposte accettate e votate che questa domanda ha già. Inoltre, questa domanda ha 9 anni, i tuoi sforzi sarebbero più apprezzati dagli utenti che hanno recenti domande senza risposta. Per favore, leggi Come posso scrivere una buona risposta .
FluffyKitten,

1
@FluffyKitten ecco un post sul blog estremamente ben scritto sui vantaggi e gli svantaggi di tale funzione che spiega in dettaglio tutto ciò che vorresti sapere :) shebang.brandonmintern.com/…
db306

@ db306 La risposta è stata contrassegnata come di bassa qualità perché la risposta di solo codice non soddisfa le linee guida Stack Overflow - vedere Come scrivere una buona risposta . Il mio commento è stato aggiunto durante il processo di revisione per spiegare cosa è necessario per migliorarlo, ovvero la risposta deve essere aggiornata per spiegare cosa fa il codice e come migliora le risposte esistenti. I voti sono di altri revisori per approvare questo. L'aggiunta di un collegamento esterno ai commenti non soddisfa ancora le linee guida SO. Invece Andrew deve includere le informazioni pertinenti direttamente nella sua risposta.
FluffyKitten,

Si noti che il DOT com brandonmintern è scaduto e ora è parcheggiato. Il nuovo indirizzo shebang è shebang.mintern.net/foolproof-html-escaping-in-javascript/.
Brandon,

0
function htmlEscape(str) {
    var stringval="";
    $.each(str, function (i, element) {
        alert(element);
        stringval += element
            .replace(/&/g, '&amp;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#39;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(' ', '-')
            .replace('?', '-')
            .replace(':', '-')
            .replace('|', '-')
            .replace('.', '-');
    });
    alert(stringval);
    return String(stringval);
}

0
function htmlDecode(t){
   if (t) return $('<div />').html(t).text();
}

funziona come un fascino


il testo rimuove i tag html, ma $ ('<div />'). html (t) .html (); funziona
Bass Jobsen

0

Questa risposta fornisce i metodi jQuery e JS normali, ma questa è la più breve senza usare il DOM:

unescape(escape("It's > 20% less complicated this way."))

Stringa con escape: It%27s%20%3E%2020%25%20less%20complicated%20this%20way.

Se gli spazi di escape ti danno fastidio, prova:

unescape(escape("It's > 20% less complicated this way.").replace(/%20/g, " "))

Stringa con escape: It%27s %3E 20%25 less complicated this way.

Sfortunatamente, la escape()funzione era obsoleta in JavaScript versione 1.5 . encodeURI()o encodeURIComponent()sono alternative, ma ignorano ', quindi l'ultima riga di codice si trasformerebbe in questo:

decodeURI(encodeURI("It's > 20% less complicated this way.").replace(/%20/g, " ").replace("'", '%27'))

Tutti i principali browser supportano ancora il codice funzione e, dato il numero di vecchi siti Web, dubito che cambierà presto.


Questo è per la codifica URL. La domanda era sull'evasione dell'HTML, che è molto diversa.
entro il

@thelem, non se le stringhe sono incorporate negli array JavaScript incorporati nell'HTML, ma sono d'accordo che si trattava di un semplice escape HTML in modo che possa essere immediatamente visualizzato come testo.
Cees Timmerman,

0

ES6 un liner per la soluzione da moustache.js

const escapeHTML = str => (str+'').replace(/[&<>"'`=\/]/g, s => ({'&': '&amp;','<': '&lt;','>': '&gt;','"': '&quot;',"'": '&#39;','/': '&#x2F;','`': '&#x60;','=': '&#x3D;'})[s]);

-2

Se stai salvando queste informazioni in un database , è sbagliato sfuggire all'HTML usando uno script sul lato client , questo dovrebbe essere fatto nel server . Altrimenti è facile bypassare la protezione XSS.

Per chiarire il mio punto, ecco un esempio usando una delle risposte:

Diciamo che stai usando la funzione escapeHtml per sfuggire all'Html da un commento nel tuo blog e quindi pubblicarlo sul tuo server.

var entityMap = {
    "&": "&amp;",
    "<": "&lt;",
    ">": "&gt;",
    '"': '&quot;',
    "'": '&#39;',
    "/": '&#x2F;'
  };

  function escapeHtml(string) {
    return String(string).replace(/[&<>"'\/]/g, function (s) {
      return entityMap[s];
    });
  }

L'utente potrebbe:

  • Modifica i parametri della richiesta POST e sostituisci il commento con il codice javascript.
  • Sovrascrivi la funzione escapeHtml utilizzando la console del browser.

Se l'utente incolla questo frammento nella console, ignorerebbe la convalida XSS:

function escapeHtml(string){
   return string
}

Non sono d'accordo. Per aggirare questa protezione XSS dovresti usare un attacco XSS (iniettando uno script che disabilita la fuga), che è ciò che stai effettivamente bloccando. In alcuni casi è in realtà più appropriato eseguire l'escape sul client, ad esempio se i dati provengono da un'API REST che deve restituire JSON standard.
ItalyPaleAle

@Qualcuno Se stai eseguendo questa convalida nel client e pubblicando queste informazioni sul server confidando che sia stata convalidata, l'utente potrebbe semplicemente modificare la richiesta e lo script verrebbe salvato nel database.
Kauê Gimenes,

@Qualcuno ho incluso alcuni esempi per chiarire il mio punto di vista.
Kauê Gimenes,

1
La domanda riguardava l'escape delle stringhe ricevute dal server per visualizzarle sul browser. Quello che stai dicendo è di scappare dalle stringhe prima di inviarle al server, che è una cosa diversa (anche se hai ragione, lì, e risale alla vecchia regola non accetta mai ciecamente alcun input dal client )
ItalyPaleAle

@Qualcuno Questa è una domanda popolare in StackOverflow e credo che questo sia un punto importante da affrontare. Ecco perché ho risposto.
Kauê Gimenes,

-2

Tutte le soluzioni sono inutili se non prevenire una nuova fuga, ad esempio, la maggior parte delle soluzioni avrebbero continuato la fuga &a &amp;.

escapeHtml = function (s) {
    return s ? s.replace(
        /[&<>'"]/g,
        function (c, offset, str) {
            if (c === "&") {
                var substr = str.substring(offset, offset + 6);
                if (/&(amp|lt|gt|apos|quot);/.test(substr)) {
                    // already escaped, do not re-escape
                    return c;
                }
            }
            return "&" + {
                "&": "amp",
                "<": "lt",
                ">": "gt",
                "'": "apos",
                '"': "quot"
            }[c] + ";";
        }
    ) : "";
};

4
Si chiama doppio escape e dovrebbe essere corretto assicurandosi che i dati di input non siano già stati salvati. E se volessi mostrare letteralmente & lt; per l'utente? O forse il testo verrà riutilizzato altrove e dipenderà dalla fuga avvenuta?
entro il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.