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


110

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

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

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

답변:


181

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>

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


13
이 대답은 놀랍습니다! 코드 스 니펫과 참조는 끝에 ...! 감사합니다!
이오 나

이 답변이 작성된 이후 React에서 위의 예를 처리 했습니까? 나는 다음과 같은 slideshre 읽을 때부터, 부탁 해요 : slideshare.net/kseniadmitrieva/...의 슬라이드 # 20에서 수정 된 사용자 제어 소품 '11 월 15 0.14 반응 것을
메르

@omer no, 그리고 react는 React 수준에서이 공격 벡터를 처리하지 않기로 결정했습니다. 다음은 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에서 언급 한 문제는 보안 버그 였고 수정되었지만 제가 나열한 3 번 항목은 해당 항목과 관련이 없습니다. 여전히 모든 반응 버전에서 내 코드를 실행하여 3 번째 항목 작업을 확인할 수 있습니다.
CyberPanda Consulting

60

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가 이스케이프하는 것을 우회하는 방법이 있다는 것입니다. 한 가지 더 일반적인 방법은 사용자가 컴포넌트에 소품을 정의하는 것입니다. 사용자 입력의 데이터를 소품으로 확장하지 마십시오!


13
모든 것을 탈출? 정말? React는 기본적으로 안전하지 않습니다. 수동으로해야 할 일과 이해해야하는 공격 벡터가 많이 있습니다. React가하는 일은 {html}로 삽입하려고 할 때 html을 문자열로 이스케이프하는 것입니다. 그러나 React가 보호하지 않는 XSS를 허용하는 다른 방법은 백만 가지가 있습니다. <a href="{...}" />, <img src = {...} />, <iframe src = "{...} /> 및 실행 가능한 자바 스크립트 삽입을 허용하는 기타 다양한 소품 . 그리고 스타일을 통해 CSS 스크립트 주사를이 = {...} 소품 실제로 가능한 위험을 설명 @Marty Aghajanyan 아래 답변.
안드레

@andree 내 오타를 지적 해 주셔서 감사합니다. 3 년 된 포스트입니다. 분명히 React가 탈출하는 것을 피하는 방법이 있으며 각 개발자는 그것에 지쳐 야합니다.
John Ruddell

@John Ruddell의 답변을 수정 해 주셔서 감사합니다. 불쾌하지는 않지만 귀하의 답변으로 인해 React가 실제보다 더 안전 해 보였으며 귀하의 답변이 주제에 대한 첫 번째 답변 중 하나이기 때문에 저는 그것을 지적하고 싶었습니다. 안타깝게도 이것은 전반적인 프론트 엔드 (React뿐만 아니라) 보안에서 볼 수있는 공통된 주제입니다. 모든 것이 안전 해 보이거나 표면적으로 쉽게 보안이 가능해 보이지만 자세히 살펴보면 큰 구멍이있는 것으로 나타났습니다. 기본 보안 질문에는 어딘가에 요약 된 쉽게 찾을 수있는 답변이 있어야합니다. 불행히도 최근에는 제 경험이 아닙니다.
andree 2010 년

글쎄 .. 시간이 지남에 따라 보안이 테스트되면서 문서가 나옵니다. 한때 도움이되었던 답변은 그다지 도움이되지 않습니다. 하드 부분은 변화하는 기술로 현재까지 모든 대답을 유지하고있다
존 러델
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.