모던 리액트 Deep Dive 마지막 챕터인 리액트 보안을 읽으며 추가적으로 프론트엔드 개발을 위한 보안을 공부하며 적어보았습니다. ( Feat : 프런트엔드 개발을 위한 보안 입문 )
🐹클릭재킹이란?
- 사용자의 의도와 다르게 버튼과 링크를 클릭해 의도하지 않은 처리를 실행하게 하는 해킹 방식입니다.
1) 클릭재킹의 구조
- 공격 대상의 웹 애플리케이션 페이지를 iframe을 사용해 피싱 사이트와 중첩합니다.
- CSS를 사용해 iframe이 보이지 않게 만듭니다.
- 피싱 사이트 상의 버튼 위치와 공격 대상의 페이지에서 중요한 기능이 중첩되도록 CSS 조정합니다.
- 피싱 사이트에 접속한 사용자가 피싱 사이트에서 버튼을 클릭하도록 유도합니다.
- 사용자가 피싱 사이트에서 버튼을 클릭해도 실제로는 투명하게 겹쳐진 공격 대상의 페이지 버튼이 클릭하게 만듭니다.
2) 그렇다면 모방된 사이트로 유도하는 방법
- 피싱 - 악성 메일, 문자 메세지, SNS 채팅을 통해 합법적인 서비스인 것처럼 유도.
- 소셜 엔지니어링 - 사용자에게 신뢰할 수 있는 출처 있는 것처럼 보이게 해서 클릭을 유도. 예를 들어, ‘긴급한 보안 업데이트’, ‘당신의 계정이 해킹되었습니다.’
- 광고 및 악성 링크.
3) 클릭재킹의 예시
- 악성 메일 또는 악성 링크를 통해 특정 사이트의 로그인 페이지로 유도 사용자들이 로그인을 했을 경우 사용자들의 개인정보 탈취합니다.
4) 클릭재킹의 대책
- 클릭재킹을 막으려면 iframe과 같은 프레임에 페이지를 삽입하는 것을 제한해야합니다.
- 프레임 안에 삽입을 제한하려면 응답에 X-Frame-Options나 frame-ancestors의 directive를 사용해 CSP 헤더를 포함해야 합니다.
- X-Frame-Options (구)
- 프레임 내부에 삽입이 제한됩니다.
- X-Frame-Options : DENY : 모든 출처의 프레임 내부에 삽입을 제한
- X-Frame-Options : SAMEORIGIN : 동일 출처의 내부에 삽입을 허가합니다.
- X-Frame-Options : ALLOW-FROM uri : 출처를 지정한 것만 허가합니다.
- CSP frame-ancestors (신)
- 프레임 내부에 삽입을 제한합니다.
- Content-Security-Policy : frame-ancestors ‘none’ : 모든 출처의 프레임 내부에 삽입을 제한
- Content-Security-Policy : frame-ancestors ‘self’ : 동일 출처의 내부에 삽입을 허가합니다.
- Content-Security-Policy : frame-ancestors uri : 출처를 지정한 것만 허가합니다.
5) 클릭재킹 방지 프론트엔드 측에서
- 웹 애플리케이션의 보안을 강화하기 위해 보안 헤더가 서버 측에서 적절히 설정되었는지 확인합니다.
- 보안 팀이나 서버 관리자가 이러한 헤더를 올바르게 설정하도록 협력합니다.
- 특정 보안 정책이 필요할 경우, 해당 요구 사항을 명확히 전달합니다.
프론트엔드 코드에서는 보안 헤더를 직접 설정할 수 없기에, 이를 이해하고 서버 설정을 검토하는 것이 중요합니다.
🐹오픈 리다이렉트이란?
- 웹 애플리케이션 내부의 리다이렉트 기능을 통해 공격자가 준비한 피싱 페이지로 리다이렉트 시키는 방법입니다.
1) 오픈 리다이렉트의 구조
- 피싱 사이트로 이동하는 파라미터를 포함하는 URL을 사용자에게 전달합니다.
- 전달된 URL을 요청합니다.
- 피싱 사이트로 이동하는 작업을 포함하는 페이지 전송합니다.
- 자동으로 피싱 사이트 이동합니다.
- 피싱 사이트 렌더합니다.
2) 오픈 리다이렉트 대책
- React를 사용한다면 react-router-dom에 Redirect 컴포넌트를 사용해서 하드코딩된 경로를 통해 리다이렉트합니다.
return <Redirect to="/home" />;
- 상대 경로만 허용합니다.
const redirectAfterLogin = (redirectUrl) => {
const isRelativeUrl = redirectUrl.startsWith('https://velog.io/');
if (isRelativeUrl) {
window.location.href = redirectUrl;
} else {
window.location.href = '/';
}
};
- 신뢰 가능한 도메인 목록만 허용합니다.
const trustedDomains = ['trusted-site.com'];
const isTrustedUrl = (url) => {
try {
const parsedUrl = new URL(url);
return trustedDomains.includes(parsedUrl.hostname);
} catch {
return false;
}
};
🐹결론
- 그동안은 간과했지만 보안은 웹 애플리케이션 개발의 필수적인 부분입니다. 특히 프론트엔드 개발자는 사용자 인터페이스와 직접적으로 상호작용하는 부분을 다루기 때문에 보안에 더욱 신경 써야 합니다. 앞으로 CSP를 비롯한 다양한 보안 대책을 종합적으로 적용하여 웹 애플리케이션의 보안을 강화해야겠다고 느꼈습니다.