Điều đó có nghĩa là gì khi họ nói React được bảo vệ bằng XSS?


109

Tôi đã đọc điều này trên hướng dẫn React. Điều đó có nghĩa là gì?

React là an toàn. Chúng tôi không tạo chuỗi HTML nên bảo vệ XSS là mặc định.

Các cuộc tấn công XSS hoạt động như thế nào nếu React an toàn? Làm thế nào để đạt được sự an toàn này?

Câu trả lời:


179

ReactJS khá an toàn theo thiết kế vì

  1. Biến chuỗi trong chế độ xem được thoát tự động
  2. Với JSX, bạn chuyển một hàm làm trình xử lý sự kiện, thay vì một chuỗi có thể chứa mã độc hại

vì vậy một cuộc tấn công điển hình như thế này sẽ không hoạt động

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>

nhưng ...

❗❗❗Cảnh báo❗❗❗

Vẫn còn một số vectơ tấn công XSS mà bạn cần tự xử lý trong React!

1. XSS qua dangerouslySetInnerHTML

Khi sử dụng dangerouslySetInnerHTMLbạn cần đảm bảo nội dung không chứa javascript. Ở đây React không thể làm gì cho bạn.

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 thông qua thuộc tính a.href

Ví dụ 1: Sử dụng javascript: code

Nhấp vào "Chạy đoạn mã" -> "Trang web của tôi" để xem kết quả

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>

Ví dụ 2: Sử dụng dữ liệu được mã hóa base64:

Nhấp vào "Chạy đoạn mã" -> "Trang web của tôi" để xem kết quả

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 thông qua đạo cụ do kẻ tấn công kiểm soát

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>

Đây là các tài nguyên khác


13
Câu trả lời này thật tuyệt vời! Với các đoạn mã và các tham chiếu ở cuối ...! Cảm ơn bạn!
Ioanna

Có bất kỳ ví dụ nào ở trên đã được React chăm sóc kể từ khi câu trả lời này được viết không? Tôi hỏi, vì tôi đọc trong slideshre sau: slideshare.net/kseniadmitrieva/... trượt # 20 mà đạo cụ sử dụng điều khiển nơi cố định trong Phản ứng 0.14 vào tháng 15'
omer

@omer không, và react quyết định không quan tâm đến các vectơ tấn công này trong cấp React. Dưới đây là một số nhận xét hay, giải thích lý do tại sao chúng không được xử lý ở cấp React github.com/facebook/react/issues/3473 ( github.com/facebook/react/issues/3473#issuecomment-91349525 , github.com/facebook/react / vấn đề / 3473 # issuecomment-90.594.748 )
CyberPanda Tư vấn

1
@omer vấn đề mà bạn đang đề cập là một lỗi bảo mật và nó đã được khắc phục, nhưng điểm 3 mà tôi đã liệt kê không liên quan đến vấn đề đó, bạn vẫn có thể kiểm tra điểm thứ 3 đó hoạt động bằng cách thực thi mã của tôi dưới bất kỳ phiên bản phản ứng nào.
CyberPanda Consulting

60

React tự động thoát các biến cho bạn ... Nó ngăn chặn việc tiêm XSS qua chuỗi HTML với Javascript độc hại .. Đương nhiên, các đầu vào được khử trùng cùng với điều này.

Ví dụ, giả sử bạn có chuỗi này

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

nếu bạn cố gắng hiển thị chuỗi này trong phản ứng

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

bạn sẽ thấy trên trang toàn bộ chuỗi bao gồm cả <span>thẻ phần tử. aka trong trình duyệt bạn sẽ thấy<img src="javascript:alert('XSS!')" />

nếu bạn xem html nguồn, bạn sẽ thấy

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

Đây là một số chi tiết hơn về cuộc tấn công XSS là gì

Về cơ bản React tạo ra nó nên bạn không thể chèn đánh dấu trừ khi bạn tự tạo các phần tử trong hàm kết xuất ... người ta nói rằng chúng có một chức năng cho phép hiển thị như vậy được gọi là dangerouslySetInnerHTML... đây là một số chi tiết hơn về nó


Biên tập:

Một vài điều cần lưu ý, có nhiều cách để giải quyết những gì React thoát ra. Một cách phổ biến hơn là khi người dùng xác định đạo cụ cho thành phần của bạn. Không mở rộng bất kỳ dữ liệu nào từ đầu vào của người dùng làm đạo cụ!


13
Chạy trốn mọi thứ? Có thật không? React KHÔNG an toàn theo mặc định, có rất nhiều thứ bạn phải làm thủ công và tấn công vectơ mà bạn phải hiểu. Tất cả những gì React làm là thoát html thành chuỗi khi bạn đang cố chèn nó bằng {html}. Nhưng có hàng triệu cách khác để cho phép XSS mà React KHÔNG bảo vệ chống lại. <a href="{...}" />, <img src = {...} />, <iframe src = "{...} /> và rất nhiều đạo cụ khác cho phép chèn javascript thực thi. Và sau đó là việc đưa tập lệnh CSS vào thông qua style = {...} prop. Câu trả lời dưới đây của @Marty Aghajanyan thực sự nêu ra những rủi ro có thể xảy ra.
andree

@andree cảm ơn vì đã chỉ ra lỗi đánh máy của tôi. Đó là một bài đăng 3 năm tuổi. Rõ ràng là có nhiều cách để giải quyết những gì React thoát ra và mỗi nhà phát triển phải mệt mỏi với điều đó.
John Ruddell

Cảm ơn bạn đã chỉnh sửa câu trả lời của bạn @John Ruddell. Không có gì xúc phạm, nhưng câu trả lời của bạn khiến React trông an toàn hơn so với thực tế, và vì câu trả lời của bạn là một trong những câu trả lời đầu tiên về chủ đề này, tôi chỉ muốn chỉ ra điều đó. Thật không may, đây là một chủ đề phổ biến mà tôi thấy trong bảo mật giao diện người dùng tổng thể (không chỉ React) - mọi thứ trông có vẻ an toàn hoặc dễ bảo mật trên bề mặt, nhưng khi bạn đào sâu vào, hóa ra có những lỗ hổng lớn. Các câu hỏi bảo mật cơ bản nên có câu trả lời dễ tìm được tóm tắt ở đâu đó, rất tiếc đó không phải là kinh nghiệm của tôi gần đây.
andree

Chà .. theo thời gian, tài liệu sẽ xuất hiện khi kiểm tra bảo mật. Những câu trả lời mà chúng tôi đã từng hữu ích sẽ không hữu ích bằng. Phần cứng là giữ tất cả các câu trả lời đến nay với công nghệ thay đổi
John Ruddell
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.