Cosa significa quando dicono che React è protetto da XSS?


110

L'ho letto nel tutorial di React. Cosa significa questo?

React è sicuro. Non stiamo generando stringhe HTML, quindi la protezione XSS è l'impostazione predefinita.

Come funzionano gli attacchi XSS se React è sicuro? Come si ottiene questa sicurezza?

Risposte:


181

ReactJS è abbastanza sicuro in base alla progettazione da allora

  1. Le variabili stringa nelle viste vengono sottoposte a escape automaticamente
  2. Con JSX si passa una funzione come gestore di eventi, piuttosto che una stringa che può contenere codice dannoso

quindi un attacco tipico come questo non funzionerà

const username = "<img onerror='alert(\"Hacked!\")' src='invalid-image' />";

class UserProfilePage extends React.Component {
  render() {
    return (
      <h1> Hello {username}!</h1>
    );
  }
}

ReactDOM.render(<UserProfilePage />, document.querySelector("#app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

ma ...

❗❗❗Warning

Ci sono ancora alcuni vettori di attacco XSS che devi gestire da solo in React!

1. XSS tramite dangerouslySetInnerHTML

Quando lo usi dangerouslySetInnerHTMLdevi assicurarti che il contenuto non contenga alcun javascript. React non può fare niente qui per te.

const aboutUserText = "<img onerror='alert(\"Hacked!\");' src='invalid-image' />";

class AboutUserComponent extends React.Component {
  render() {
    return (
      <div dangerouslySetInnerHTML={{"__html": aboutUserText}} />
    );
  }
}

ReactDOM.render(<AboutUserComponent />, document.querySelector("#app"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

2. XSS tramite l'attributo a.href

Esempio 1: utilizzo di javascript: code

Fare clic su "Esegui snippet di codice" -> "Il mio sito Web" per vedere il risultato

const userWebsite = "javascript:alert('Hacked!');";

class UserProfilePage extends React.Component {
  render() {
    return (
      <a href={userWebsite}>My Website</a>
    )
  }
}

ReactDOM.render(<UserProfilePage />, document.querySelector("#app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

Esempio 2: utilizzo di dati codificati in base64:

Fare clic su "Esegui snippet di codice" -> "Il mio sito Web" per vedere il risultato

const userWebsite = "data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGFja2VkISIpOzwvc2NyaXB0Pg==";

class UserProfilePage extends React.Component {
  render() {
    const url = userWebsite.replace(/^(javascript\:)/, "");
    return (
      <a href={url}>My Website</a>
    )
  }
}

ReactDOM.render(<UserProfilePage />, document.querySelector("#app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

3. XSS tramite oggetti di scena controllati dall'attaccante

const customPropsControledByAttacker = {
  dangerouslySetInnerHTML: {
    "__html": "<img onerror='alert(\"Hacked!\");' src='invalid-image' />"
  }
};

class Divider extends React.Component {
  render() {
    return (
      <div {...customPropsControledByAttacker} />
    );
  }
}

ReactDOM.render(<Divider />, document.querySelector("#app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

Qui ci sono più risorse


13
Questa risposta è sorprendente! Con i frammenti di codice e i riferimenti alla fine ...! Grazie!
Ioanna

Qualcuno degli esempi sopra è stato curato da React da quando è stata scritta questa risposta? Sto chiedendo, dato che ho letto nella seguente presentazione: slideshare.net/kseniadmitrieva/… diapositiva # 20 che gli oggetti di scena controllati dall'utente sono stati fissati in React 0.14 nel 15 novembre
omer

@omer no, e React ha deciso di non occuparsi di questi vettori di attacco a livello di React. Ecco alcuni buoni commenti, che spiegano perché non vengono gestiti nel livello React github.com/facebook/react/issues/3473 ( github.com/facebook/react/issues/3473#issuecomment-91349525 , github.com/facebook/react / issues / 3473 # issuecomment-90594748 )
CyberPanda Consulting

1
@omer il problema a cui ti riferisci era un bug di sicurezza ed è stato risolto, ma il punto 3 che ho elencato non è correlato a quello, puoi comunque controllare quel terzo punto di lavoro eseguendo il mio codice con qualsiasi versione di React.
CyberPanda Consulting

60

React evita automaticamente le variabili per te ... Impedisce l'iniezione XSS tramite stringa HTML con JavaScript dannoso .. Naturalmente, gli input vengono disinfettati insieme a questo.

Ad esempio, diciamo che hai questa stringa

var htmlString = '<img src="javascript:alert('XSS!')" />';

se provi a rendere questa stringa in react

render() {
    return (
        <div>{htmlString}</div>
    );
}

vedrai letteralmente sulla pagina l'intera stringa incluso il <span>tag dell'elemento. aka nel browser vedrai<img src="javascript:alert('XSS!')" />

se visualizzi il codice sorgente html vedresti

<span>"<img src="javascript:alert('XSS!')" />"</span>

Ecco qualche dettaglio in più su cosa sia un attacco XSS

React fondamentalmente lo fa in modo che tu non possa inserire markup a meno che tu non crei gli elementi tu stesso nella funzione di rendering ... detto questo hanno una funzione che consente tale rendering è chiamato dangerouslySetInnerHTML... ecco qualche dettaglio in più a riguardo


Modificare:

Poche cose da notare, ci sono modi per aggirare ciò che React sfugge. Un modo più comune è quando gli utenti definiscono gli oggetti di scena per il tuo componente. Non estendere i dati dall'input dell'utente come oggetti di scena!


13
Sfugge a tutto? Veramente? React NON è sicuro per impostazione predefinita, ci sono molte cose che devi fare manualmente e attaccare i vettori che devi capire. Tutto ciò che React fa è passare da html a stringa quando provi a inserirlo con {html}. Ma ci sono un milione di altri modi per consentire XSS, da cui React NON protegge. <a href="{...}" />, <img src = {...} />, <iframe src = "{...} /> e tonnellate di altri oggetti di scena che consentono di iniettare javascript eseguibili. E poi ci sono le iniezioni di script CSS tramite style = {...} prop. La risposta di seguito di @Marty Aghajanyan delinea effettivamente i possibili rischi.
andree

@andree grazie per aver segnalato il mio errore di battitura. È un post di 3 anni. Ovviamente ci sono modi per aggirare ciò che React sfugge e ogni sviluppatore dovrebbe stancarsene.
John Ruddell,

Grazie per aver modificato la tua risposta @John Ruddell. Senza offesa, ma la tua risposta ha fatto sembrare React più sicuro di quanto non sia in realtà, e poiché la tua risposta è una delle prime che emerge sull'argomento, volevo solo sottolinearlo. Sfortunatamente questo è un tema comune che vedo nella sicurezza generale del frontend (non solo React): le cose sembrano sicure o facilmente fissabili in superficie, ma quando si scava, si scopre che ci sono grossi buchi. Le domande di sicurezza di base dovrebbero avere risposte facili da trovare e riassunte da qualche parte, sfortunatamente questa non è la mia esperienza ultimamente.
andree

Ebbene ... nel tempo la documentazione esce man mano che la sicurezza viene testata. Le risposte che una volta siamo stati utili non sono altrettanto utili. La parte difficile è mantenere tutte le risposte aggiornate con la tecnologia in evoluzione
John Ruddell,
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.