프로젝트를 진행 하던 중 textarea를 사용하고, 여기 사용자가 입력한 데이터를 서버로 전송 그리고 이를 받아 출력하는 과정에서 문제가 생겼다. 그 문제는 이제 사용자가 입력한 내용에 태그까지 포함이 되는 것이다.
위와 같이 내용에 태그까지 같이 포함된 것이다. 이는 내용 읽는데 문제 있을 뿐만 아니라 보안상의 문제가 생길수도 있다.
이렇게 입력값에 태그까지 포함된 이유가 있다. {} 내부의 값이 HTML 코드가 포함된 문자열인 경우
HTML 태그를 인코딩해서 처리하므로, 브라우저에는 태그가 그대로 보이게 된다. 이러한 이유로 태그가 보이는 것이다.
근데 여기에 문제가 태그가 그대로 보인다면 XSS 공격에 취약해진다.
1. XSS란?
웹 해킹 공격 중 XSS라는 공격 기법이 있다. 이는 Cross Site Scripting의 약자로, XSS는 게시판이나, 웹 메일 등에 자바 스크립트와 같은 스크립트 코드를 삽입 하여 개발자가 고려하지 않은 기능이 작동하게 하는 치명적인 공격이 될 수 있다. 이는 대부분의 웹 해킹 공격 방식이 아닌 클라이언트 즉, 사용자를 대상으로 한 공격이다.
이게 왜 위험하냐면, 위에 설명한 것처럼 개발자가 의도하지 않은 기능을 사용자가 그 기능을 하게 하는 그런 위험할 수 있다. 개인정보 유출을 할 수도 있고, 금융의 문제가 생길 수도 있다.
XSS의 공격 기법은 크게 Reflected XSS, Stored XSS, 그리고 DOM Based XSS 세가지가 있다.
1. Reflected XSS
다음과 같이 ID를 입력하면 Welcome 000 를 출력해주는 페이지가 있다고 가정하자,
이 페이지에 간단한 스크립트를 삽입하면 별다른 필터링 없이 실행이 된다.
공격자는 이러한 취약점을 존재하는 페이지를 미리 탐색한 후 XSS 공격을 위한 스크립트가 포함 된 URL을 공격 대상자에게 노출시키는 방법으로 공격할 수 있다.
Reflected XSS의 공격 순서는 다음과 같다.
사용자가 해당 URL을 클릭할 경우, 취약한 웹 사이트의 서버에 스크립트가 포함 된 URL을 통해 Request를 전송하고, 웹 서버에서는 해당 스크립트를 포함한 Response를 전송하게 된다. 이 과정에서 브라우저에서 실행되면 보안 취약점이 발생한다.
2. Stored XSS
Stored XSS는 Reflected XSS와는 달리 웹 사이트의 게시판에 스크립트 삽입하는 공격 방식이다.
공격자는 게시판에 스크립트를 삽입한 후 공격 대상자가 해당 게시물을 클릭하도록 유도한다.
공격자가 미리 XSS 공격에 취약한 웹사이트를 탐색하고 XSS 공격을 위한 스크립트를 포함한 게시글을 웹 사이트에 업로드 한다.
게시글의 URL을 사용자에게 노출하고, 사용자가 게시글이 확임함으로써 URL에 대한 요청을 서버에 전송하게 된다.
웹 서버에서 스크립트를 포함한 Response를 전송하며 공격이 수행된다.
3. DOM Based XSS
DOM Based XSS는 웹 애플리케이션의 클라이언트 측 코드(JS)에서 DOM을 직접 조작하는 과정에서 악성 스크립트가 실행되는 취약점을 말한다. 서버와의 통신 없이 클라이언트 측에서만 발생하기 때문에 탐지하기 어려운 특징이 있다.
- 클라이언트 측에서만 발생
- URL, 프래그먼트(#fragment), DOM 조작 등을 통해 입력 값이 처리된다.
- 서버는 문제없이 동작하지만, 브라우저에서 악성 스크립트가 실행된다.
이제 여러가지 해결 방법이 있지만 내가 해결한 방법은 dangerouslySetInnerHTML 속성을 사용하여 HTML 태그를 인코딩하지 않게 한다. 하지만 이는 완벽하지 않다. 이 이유는 문자열을 HTML로 렌더링 할 수 있게하여, 외부 데이터가 포함된 경우 XSS 공격에 매우 취약하다.
악성 코드가 포함된 HTML이나 스크립트를 실행할 위험이 있다.
그래서 여기에 추가 시킨 것이. DOMPurify라는 라이브러리를 다운 받아 사용하는 것이다. 이는 리액트에서dangerouslySetInnerHTML
를 사용할 때, 외부 데이터가 포함된 경우 DOMPurify를 통해 데이터를 정제한 후 렌더링함으로써 예방할 수 있다.
import DOMPurify from "dompurify";
const sanitizedContent = DOMPurify.sanitize(`${data?.item.content}`);
위와 같이 import를 하고 npm install dompurify 설치 해야한다. 그리고 사용하는 곳에
<span dangerouslySetInnerHTML={{__html: sanitizedContent,}}></span>
이렇게 실행하면 된다.
그러면 아래와 같이 태그를 삭제한 텍스트만 볼 수 있다.
'React > 다시 공부하는 리액트' 카테고리의 다른 글
React Zustand persist 미들웨어 (0) | 2024.12.10 |
---|---|
React Fetch-on-render, Fetch-then-render, Render-as-you-fetch, (3) | 2024.12.05 |
React useMutation (0) | 2024.12.04 |
React useQuery (0) | 2024.12.04 |
React Tagged Template Literal (0) | 2024.12.02 |