리액트 엘리먼트에 $$typeof 속성이 존재하는 이유
리액트 엘리먼트에 $$typeof 속성이 존재하는 이유를 알아봅니다.
TLDR : XSS 공격 방지
원문입니다 : https://overreacted.io/why-do-react-elements-have-typeof-property/
Why Do React Elements Have a $$typeof Property?
It has something to do with security.
overreacted.io
JSX는 사실 리액트 엘리먼트로 컴파일되고
리액트 엘리먼트는 JSON으로 컴파일됩니다.
<marquee bgcolor="#ffa7c4">hi</marquee>
JSX를 작성한다 생각했지만, 실제로, 당신은 함수를 호출하고 있습니다:
React.createElement(
/* type */ 'marquee',
/* props */ { bgcolor: '#ffa7c4' },
/* children */ 'hi'
)
그리고 그 함수는 객체를 리턴합니다. 우리는 이 객체를 React 엘리먼트라고 부릅니다.
다음에 무엇을 렌더링할지 React에게 알려줍니다. 컴포넌트는 엘리먼트 트리를 반환합니다.
{
type: 'marquee',
props: {
bgcolor: '#ffa7c4',
children: 'hi',
},
key: null,
ref: null,
$$typeof: Symbol.for('react.element'), // 🧐 Who dis}
React를 사용했다면 type, props, key 및 ref 필드에 익숙할 것입니다.
하지만 $$typeof는 뭐죠? 왜 Symbol()이 값으로 있을까요?
const messageEl = document.getElementById('message');
messageEl.innerHTML = '<p>' + message.text + '</p>';
message.text가 '<img src onerror="stealYourPassword()">'와 같은 경우를 제외하고는 잘 작동합니다.
낯선 사람이 작성한 내용이 앱의 렌더링된 HTML에 그대로 표시되는 것을 원하지 않기 때문입니다.
<p>
{message.text}
</p>
message.text가 <img> 또는 다른 태그가 있는 악성 문자열인 경우 실제 <img> 태그로 바뀌지 않습니다.
React는 콘텐츠를 이스케이프한 다음 DOM에 삽입합니다. 따라서 <img> 태그를 보는 대신 마크업(문자열 구조)만 볼 수 있습니다.
React는 시간이 지남에 따라 더 많은 보호를 제공할 수 있지만(could)
대부분의 경우 이러한 결과는 서버에서 해결되어야 합니다(should).
그러나 텍스트 콘텐츠를 이스케이프하는 것은 많은 잠재적 공격을 포착하는 합리적인 첫 번째 방어선입니다.
이런 코드가 안전하다는 것을 아는 것이 좋지 않습니까?
// Escaped automatically
<p>
{message.text}
</p>
{
type: 'marquee',
props: {
bgcolor: '#ffa7c4',
children: 'hi',
},
key: null,
ref: null,
$$typeof: Symbol.for('react.element'),
}
그러나 클라이언트는 문자열을 예상하하지만
서버에 사용자가 임의의 JSON 개체를 저장할 수 있는 구멍이 있는 경우 문제가 될 수 있습니다.
서버에서 짝퉁 리액트 엘리먼트 json을 보내면 막을 방법이 없었음
// Server could have a hole that lets user store JSON
let expectedTextButGotJSON = {
type: 'div',
props: {
dangerouslySetInnerHTML: {
__html: '/* put your exploit here */'
},
},
// ...
};
let message = { text: expectedTextButGotJSON };
// Dangerous in React 0.13
<p>
{message.text}
</p>
이 경우 React 0.13은 XSS 공격에 취약(vulnerable)합니다.
다시 한 번 명확히 하자면 이 공격은 기존 서버의 구멍에 의존합니다.
그래도 React는 사람들을 더 잘 보호할 수 있습니다. 그리고 React 0.14부터 가능합니다.
React 0.14의 수정 사항은 모든 React 요소에 Symbol을 태그로 지정하는 것이었습니다.
(tag every React element with a Symbol)
{
type: 'marquee',
props: {
bgcolor: '#ffa7c4',
children: 'hi',
},
key: null,
ref: null,
$$typeof: Symbol.for('react.element'),
}
브라우저가 심볼(Symbol)을 지원하지 않으면요?
이 추가 보호를 받지 못합니다.
React는 일관성을 위해 요소에 $$typeof 필드를 여전히 포함하지만 숫자 0xeac7로 설정됩니다.
0xeac7은 "React"처럼 생겼습니다.
참고 :
바닐라 JavaScript에서 innerHTML을 사용할 때 사이트 간 스크립팅 공격 방지
Preventing cross-site scripting attacks when using innerHTML in vanilla JavaScript
IMPORTANT: some of the information in this article is out-of-date. Please read this update article instead. I generally use innerHTML to inject HTML into an element with vanilla JavaScript. Yesterday, one of my students asked me about the danger of cross-s
gomakethings.com