[reactjs] React가 XSS로 보호된다는 것은 무엇을 의미합니까?

나는 React 튜토리얼에서 이것을 읽었습니다. 이것은 무엇을 의미 하는가?

React는 안전합니다. HTML 문자열을 생성하지 않으므로 XSS 보호가 기본값입니다.

React가 안전하다면 XSS 공격은 어떻게 작동합니까? 이 안전은 어떻게 달성됩니까?



답변

ReactJS는 설계 상 매우 안전합니다.

  1. 뷰의 문자열 변수는 자동으로 이스케이프됩니다.
  2. JSX를 사용하면 악성 코드를 포함 할 수있는 문자열이 아닌 이벤트 핸들러로 함수를 전달합니다.

따라서 이와 같은 일반적인 공격은 작동하지 않습니다.

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>

하지만 …

❗❗❗ 경고 ❗❗❗

React에서 직접 처리해야하는 XSS 공격 벡터가 아직 있습니다!

1. XSS를 통해 dangerouslySetInnerHTML

사용할 때 dangerouslySetInnerHTML콘텐츠에 자바 스크립트가 포함되어 있지 않은지 확인해야합니다. React는 여기서 아무것도 할 수 없습니다.

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. a.href 속성을 통한 XSS

예 1 : javascript : code 사용

결과를 보려면 “코드 스 니펫 실행”-> “내 웹 사이트”를 클릭하십시오.

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>

예 2 : base64로 인코딩 된 데이터 사용 :

결과를 보려면 “코드 스 니펫 실행”-> “내 웹 사이트”를 클릭하십시오.

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

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>

더 많은 리소스가 있습니다.


답변

React는 자동으로 변수를 이스케이프합니다 … 악성 자바 스크립트를 사용하여 문자열 HTML을 통해 XSS 삽입을 방지합니다. 당연히 입력도 이와 함께 삭제됩니다.

예를 들어이 문자열이 있다고 가정 해 보겠습니다.

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

이 문자열을 반응으로 렌더링하려고하면

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

문자 그대로 페이지에서 <span>요소 태그를 포함한 전체 문자열을 볼 수 있습니다 . 브라우저에서 일명<img src="javascript:alert('XSS!')" />

소스 HTML을 보면

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

XSS 공격에 대한 자세한 내용은 다음과 같습니다.

React는 기본적으로 렌더링 함수에서 요소를 직접 생성하지 않는 한 마크 업을 삽입 할 수 없도록 만듭니다 … 그런 렌더링을 허용하는 함수가 있다고 말하면 dangerouslySetInnerHTML여기에 대한 자세한 내용이 있습니다.


편집하다:

몇 가지 주목할 점은 React가 이스케이프하는 것을 우회하는 방법이 있다는 것입니다. 한 가지 더 일반적인 방법은 사용자가 컴포넌트에 소품을 정의하는 것입니다. 사용자 입력의 데이터를 소품으로 확장하지 마십시오!


답변