나는 React 튜토리얼에서 이것을 읽었습니다. 이것은 무엇을 의미 하는가?
React는 안전합니다. HTML 문자열을 생성하지 않으므로 XSS 보호가 기본값입니다.
React가 안전하다면 XSS 공격은 어떻게 작동합니까? 이 안전은 어떻게 달성됩니까?
답변
ReactJS는 설계 상 매우 안전합니다.
- 뷰의 문자열 변수는 자동으로 이스케이프됩니다.
- 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>
React는 기본적으로 렌더링 함수에서 요소를 직접 생성하지 않는 한 마크 업을 삽입 할 수 없도록 만듭니다 … 그런 렌더링을 허용하는 함수가 있다고 말하면 dangerouslySetInnerHTML
… 여기에 대한 자세한 내용이 있습니다.
편집하다:
몇 가지 주목할 점은 React가 이스케이프하는 것을 우회하는 방법이 있다는 것입니다. 한 가지 더 일반적인 방법은 사용자가 컴포넌트에 소품을 정의하는 것입니다. 사용자 입력의 데이터를 소품으로 확장하지 마십시오!