티스토리 뷰
1. XSS(Cross‑Site Scripting)란?
XSS(Cross‑Site Scripting) : 웹 애플리케이션에서 자주 등장하는 취약점으로, 공격자가 악성 스크립트를 주입해 사용자의 브라우저에서 실행시키는 기법
- 세션·쿠키 탈취 : 악성 스크립트가 실행되면 로그인 세션 쿠키를 탈취해 계정 탈취로 이어질 수 있습니다.
- 피싱·악성 행위 : DOM을 조작해 가짜 로그인 창을 띄우거나, 숨은 네트워크 요청으로 토큰·개인정보를 외부로 전송할 수 있습니다.
- 연계 공격 : CSRF 등 다른 취약점과 결합해 결제·게시물 작성 등 의도치 않은 동작을 수행시키기도 합니다.
발생 원인
- 사용자 입력을 검증·필터링·인코딩 없이 그대로 HTML이나 속성(src 등)에 삽입하는 경우
- React, Vue 등에서 dangerouslySetInnerHTML이나 v-html을 무분별하게 사용
- URL 파라미터(location.state?.src, querystring 등)를 <iframe>에 직접 주입하며, javascript: 스킴 등을 막지 않는 경우
2. 문제 발견: iframe src 무분별 삽입
프로젝트에서 Fortify 보안 검사를 진행한 결과, <iframe>의 src 속성에 화이트리스트나 필터링 없이 외부 입력(location.state?.src)을 그대로 주입하는 구간에서 XSS 취약점이 지적되었습니다.
// 취약점이 발생한 예시
<iframe src={location.state?.src} />
공격자가 location.state?.src 에 javascript:alert(document.cookie) 같은 악성 스킴을 넘기면, 최종적으로 사용자의 브라우저에서 임의 코드가 실행될 수 있습니다.
3. 개선 목표
- 허용된 URL만 <iframe> 에 주입한다.
- 외부 입력 값이 화이트리스트에 없으면 로드하지 않도록 차단한다.
- 추후 메뉴 구성이 변경 되었어도 확장하기 쉬운 구조로 만든다.
4. 화이트리스트 기반 접근(WhiteList Approach)
- 이미 메뉴 정보(menuList)에 어떤 URL이 iframe으로 열려야 되는지 정의되어 있음
이 중 menuTypeCd === 'L'인 route만 iframe 허용 URL 이라고 간주 - menuList를 재귀적으로 순회하여, menuTypeCd === 'L'에 해당하는 모든 route를 화이트리스트로 모음.
- <iframe>에 넣으려는 URL(location.state?.src)이 이 화이트리스트 안에 속해 있지 않으면, iframe을 비워두거나 다른 화면으로 대체한다.
4.1. 기존 메뉴 정보 활용
서비스에는 이미 메뉴 정보(zustand 스토어의 menuList)에 iframe으로 띄울 수 있는 URL이 정의되어 있습니다.
- menuTypeCd === 'L' 인 메뉴 항목만 정상 iframe URL로 간주
// store/menuStore.js (예시)
menuList: [
{
key: 'menu-1',
menuTypeCd: 'B', // 일반 페이지
route: '/board',
children: [
{
key: 'menu-1-1',
menuTypeCd: 'L', // iframe 대상
route: 'https://example.com/iframePage',
}
]
},
{
key: 'menu-2',
menuTypeCd: 'L', // iframe 대상
route: 'https://another.com/reportView',
}
]
4.2. 재귀함수로 화이트리스트 수집
중첩된 children 까지 모두 순회해, menuTypeCd==='L' 인 route 들을 한곳에 모읍니다.
const collectIframeRoutes = (menuList, result = []) => {
menuList.forEach(item => {
if (item.menuTypeCd === 'L') {
result.push(item.route);
}
if (Array.isArray(item.children)) {
collectIframeRoutes(item.children, result);
}
});
return result;
}
4.3. IFrameLayout 컴포넌트 적용
최종적으로 렌더링 시점에, 사용자가 넘긴 urlSrc 가 화이트리스트에 포함되어야만 <iframe> 에 주입됩니다.
import React from 'react';
import { Box } from '@mui/material';
import { useLocation } from 'react-router-dom';
import { useMenuStore } from '@/stores/menuStore';
const collectIframeRoutes = (menuList, result = []) => {
menuList.forEach(item => {
if (item.menuTypeCd === 'L') {
result.push(item.route);
}
if (Array.isArray(item.children)) {
collectIframeRoutes(item.children, result);
}
});
return result;
}
const IFrameLayout = () => {
const menuList = useMenuStore(state => state.menuList);
const location = useLocation();
const urlSrc = location.state?.src;
// 화이트리스트 생성
const iframeWhiteList = collectIframeRoutes(menuList);
// 허용 URL 여부 판단
const isValid = iframeWhiteList.includes(urlSrc);
return (
<Box sx={{ height: '100%', width: '100%' }}>
<iframe
src={isValid ? urlSrc : '/no-permission'}
style={{ height: '100%', width: '100%' }}
title="iframeLayout"
/>
</Box>
);
};
export default IFrameLayout;
이로써 메뉴 정보에 등록되지 않은 URL은 <iframe> 에 로드되지 않아, XSS 위험을 효과적으로 차단할 수 있습니다.
'FrontEnd' 카테고리의 다른 글
Fortify 보안 점검 대응 : Dockerfile 보안 설정과 Trivy 활용하기 (1) | 2025.05.02 |
---|---|
GitLab CI/CD, Docker를 활용하여 Vite 프로젝트 Nginx 배포하기 (에러상황 해결 포함) (1) | 2025.01.24 |
[HTTP] Cookie 와 Session (0) | 2024.07.01 |
코드 스플리팅 ( Code Splitting ) - 웹 애플리케이션 성능 최적화 하기 (0) | 2024.06.21 |
Axios를 이용하여 Excel Download 하는법 + blob (content-disposition 접근 오류 해결) (0) | 2024.01.23 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- Location
- Chart
- package
- SCSS
- chartjs
- npm
- BarChart
- 깊은복사
- 얕은복사
- Figma 기초
- echarts
- vscode
- piechart
- web
- VUE
- 객체
- 프론트엔드
- SASS
- Legend
- Figma 버튼
- javascript
- Vscode단축키
- frontend
- package-lock
- 객체복사
- figma
- Figma Style
- 환경설정
- x축스크롤
- npm install
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
글 보관함