Apa artinya ketika mereka mengatakan Bereaksi dilindungi XSS?

110

Saya membaca ini di tutorial React. Apa artinya ini?

Bereaksi aman. Kami tidak membuat string HTML jadi perlindungan XSS adalah defaultnya.

Bagaimana cara kerja serangan XSS jika React aman? Bagaimana keamanan ini tercapai?

pengguna1210233
sumber

Jawaban:

181

ReactJS secara desain cukup aman sejak saat itu

  1. Variabel string dalam tampilan di-escape secara otomatis
  2. Dengan JSX, Anda meneruskan fungsi sebagai pengendali kejadian, bukan string yang bisa berisi kode berbahaya

jadi serangan biasa seperti ini tidak akan berhasil

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>

tapi ...

❗❗❗Peringatan❗❗❗

Masih ada beberapa vektor serangan XSS yang perlu Anda tangani sendiri di React!

1. XSS melalui dangerouslySetInnerHTML

Saat Anda menggunakan, dangerouslySetInnerHTMLAnda perlu memastikan konten tidak mengandung javascript. React tidak dapat melakukan apa pun di sini untuk Anda.

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 melalui atribut a.href

Contoh 1: Menggunakan javascript: code

Klik "Jalankan cuplikan kode" -> "Situs Saya" untuk melihat hasilnya

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>

Contoh 2: Menggunakan data berenkode base64:

Klik "Jalankan cuplikan kode" -> "Situs Saya" untuk melihat hasilnya

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 melalui alat peraga yang dikendalikan penyerang

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>

Berikut lebih banyak sumber daya

Konsultasi CyberPanda
sumber
13
Jawaban ini luar biasa! Dengan potongan kode dan referensi di bagian akhir ...! Terima kasih!
Ioanna
Apakah salah satu contoh di atas telah ditangani oleh React sejak jawaban ini ditulis? Saya bertanya, karena saya membaca di slideshre berikut: slideshare.net/kseniadmitrieva/… slide # 20 bahwa alat peraga yang dikontrol pengguna ditetapkan di React 0.14 pada 15 November '
omer
@omer no, dan react memutuskan untuk tidak menangani vektor serangan ini di level React. Berikut beberapa komentar bagus, menjelaskan mengapa mereka tidak menangani di level 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 masalah yang Anda maksud adalah bug keamanan dan telah diperbaiki, tetapi poin 3 yang saya cantumkan tidak terkait dengan masalah itu, Anda masih dapat memeriksa pekerjaan poin ke-3 itu dengan menjalankan kode saya di bawah versi react apa pun.
CyberPanda Consulting
60

React secara otomatis meloloskan variabel untuk Anda ... Ini mencegah injeksi XSS melalui string HTML dengan Javascript berbahaya .. Biasanya, masukan dibersihkan bersama ini.

Misalnya, Anda memiliki string ini

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

jika Anda mencoba membuat string ini bereaksi

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

Anda benar-benar akan melihat di halaman seluruh string termasuk <span>tag elemen. alias di browser Anda akan melihat<img src="javascript:alert('XSS!')" />

jika Anda melihat html sumber, Anda akan melihat

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

Berikut adalah beberapa detail lebih lanjut tentang apa itu serangan XSS

React pada dasarnya membuatnya sehingga Anda tidak dapat menyisipkan markup kecuali Anda membuat elemen sendiri dalam fungsi render ... yang dikatakan memiliki fungsi yang memungkinkan rendering tersebut dipanggil dangerouslySetInnerHTML... berikut ini beberapa detail lebih lanjut tentangnya


Edit:

Beberapa hal yang perlu diperhatikan, ada cara untuk menghindari apa yang lolos React. Satu cara yang lebih umum adalah ketika pengguna mendefinisikan props ke komponen Anda. Jangan memperluas data apa pun dari input pengguna sebagai alat peraga!

John Ruddell
sumber
13
Lolos dari segalanya? Betulkah? Secara default, React TIDAK aman, ada banyak hal yang harus Anda lakukan secara manual dan menyerang vektor yang harus Anda pahami. Semua yang dilakukan React adalah melarikan diri dari html ke string ketika Anda mencoba memasukkannya dengan {html}. Tetapi ada jutaan cara lain untuk mengizinkan XSS, yang TIDAK dilindungi oleh React. <a href="{...}" />, <img src = {...} />, <iframe src = "{...} /> dan banyak alat peraga lain yang memungkinkan untuk memasukkan javascript yang dapat dijalankan. . dan kemudian ada suntikan naskah CSS melalui style = {...} prop Jawaban bawah oleh @Marty Aghajanyan sebenarnya menguraikan kemungkinan resiko.
andree
@ andree, terima kasih telah menunjukkan kesalahan ketik saya. Ini adalah posting berusia 3 tahun. Jelas ada cara untuk menghindari apa yang lolos dari React dan setiap pengembang harus bosan dengan itu.
John Ruddell
Terima kasih telah mengedit jawaban Anda @John Ruddell. Jangan tersinggung, tetapi jawaban Anda membuat React terlihat lebih aman daripada yang sebenarnya, dan karena jawaban Anda adalah salah satu jawaban pertama yang muncul pada topik tersebut, saya hanya ingin menunjukkannya. Sayangnya ini adalah tema umum yang saya lihat di keamanan frontend keseluruhan (bukan hanya React) - segala sesuatunya terlihat aman atau mudah diamankan di permukaan, tetapi ketika Anda menggali, ternyata ada lubang besar. Pertanyaan keamanan dasar harus memiliki jawaban yang mudah ditemukan yang dirangkum di suatu tempat, sayangnya itu bukan pengalaman saya belakangan ini.
andree
Yah .. seiring waktu dokumentasi keluar saat keamanan diuji. Jawaban yang pernah kami bantu tidak begitu membantu. Bagian yang sulit adalah menjaga semua jawaban tetap up to date dengan teknologi yang berubah
John Ruddell