CSRF Attack
• bamjun
CSRF (Cross-Site Request Forgery) 공격은 웹 애플리케이션의 보안 취약점을 이용한 공격 유형 중 하나입니다. 이 공격은 사용자가 현재 인증된 상태에서 공격자가 조작한 요청을, 사용자가 모르게 웹 애플리케이션에 전송하게 만듭니다. 이러한 요청은 웹 사이트에 변경을 가하는 행위(비밀번호 변경, 전송 실행 등)를 포함할 수 있습니다.
CSRF 공격의 핵심은 사용자의 웹 브라우저가 자동적으로 쿠키를 포함해 요청을 보내는 웹의 기본 동작을 악용하는 것입니다. 예를 들어, 사용자가 은행 웹사이트에 로그인해 있다면, 공격자는 사용자가 은행 사이트에 대한 요청을 보낼 수 있는 링크나 이미지를 포함한 이메일을 보낼 수 있습니다. 사용자가 그
링크를 클릭하면, 사용자의 브라우저는 은행 사이트에 대한 요청을 자동으로 인증된 상태로 보내고, 은행은 그 요청을 정당한 것으로 간주합니다. 만약 이 요청이 송금과 같은 금융 거래를 지시하는 것이라면, 사용자의 의도와는 무관하게 거래가 이루어질 수 있습니다.
CSRF 공격을 방지하기 위한 일반적인 방법은 다음과 같습니다:
-
CSRF 토큰 사용: 서버에서는 각 폼 요청에 대해 고유한 CSRF 토큰을 생성하여 클라이언트에 전송하고, 클라이언트는 폼 제출 시 이 토큰을 함께 전송합니다. 서버는 폼 데이터를 처리하기 전에 이 토큰을 검증합니다.
-
SameSite 쿠키 속성 사용: 최신 브라우저는 쿠키에
SameSite
속성을 지원합니다. 이 속성을 설정하면 브라우저는 다른 사이트에서 발생한 요청에는 쿠키를 전송하지 않습니다. -
사용자 인증 요구: 중요한 작업을 수행하기 전에 사용자에게 비밀번호를 다시 입력하거나 다른 형태의 인증을 요구합니다.
-
Referer 검증: 서버에서 HTTP Referer 헤더를 검증하여 요청이 신뢰할 수 있는 페이지로부터 발생했는지 확인합니다.
-
사용자의 동작 패턴 분석: 사용자의 정상적인 동작 패턴과 다르게 비정상적인 요청이 감지되면, 이를 차단할 수 있습니다.
CSRF 공격에 대한 예제를 들자면, 웹 애플리케이션이 사용자가 로그인한 상태에서 사용자의 의지와는 무관하게 특정 작업을 수행하도록 만드는 시나리오를 들 수 있습니다. 아래는 CSRF 공격의 간단한 시나리오입니다:
시나리오:
Alice는 bank.com
에서 인터넷 뱅킹을 사용합니다. 은행 웹사이트는 사용자가 로그인한 상태에서 송금 요청을 처리할 수 있는 폼을 제공합니다.
- Alice는
bank.com
에 로그인하고, 브라우저는 이 사이트에 대한 인증 쿠키를 저장합니다. - Alice는 이메일을 확인하고, 공격자 Bob이 보낸 메일에 포함된 이미지를 클릭합니다.
- 이 이미지 태그는 실제로는 사용자가 인지하지 못하는
bank.com
으로의 송금 요청을 포함하고 있습니다:
<img src="https://bank.com/transfer?amount=1000&toAccount=bob-account" style="display:none;">
- Alice의 브라우저는 이미지를 불러오기 위해
bank.com
에 요청을 보내고, 요청과 함께 Alice의 인증
쿠키도 자동으로 포함하여 보냅니다.
bank.com
은 요청을 받고, 인증 쿠키를 검증한 후 Alice의 계좌에서 Bob의 계좌로 1000달러를 이체합니다.
Alice는 자신이 송금을 승인했다는 사실조차 모르고 있었기 때문에, 공격자 Bob은 CSRF 공격을 성공적으로 수행했습니다.
방어 메커니즘: 은행 웹사이트는 CSRF 공격을 방지하기 위해 각 폼 요청에 대한 CSRF 토큰을 사용할 수 있습니다.
<form action="https://bank.com/transfer" method="post">
<input type="hidden" name="amount" value="1000">
<input type="hidden" name="toAccount" value="bob-account">
<!-- 서버에서 생성된 CSRF 토큰을 포함 -->
<input type="hidden" name="csrf_token" value="서버에서 생성된 토큰">
<input type="submit" value="송금">
</form>
서버는 폼을 제출할 때 csrf_token
을 검증하여, 요청이 실제 사용자의 의도에
따라 만들어진 것인지 확인합니다. 만약 요청에 유효한 csrf_token
이 포함되어 있지 않다면, 서버는 요청을 거부합니다. 이 방식으로, 사용자가 실제로 의도하고 직접 폼을 제출한 것이 아니라면, 악의적인 송금 요청을 방지할 수 있습니다.
이 방법은 Bob이 위와 같은 이미지 태그를 통해 송금 요청을 보내도록 한 경우, bank.com
이 이 요청을 거부하게 만듭니다. 이미지 태그는 CSRF 토큰을 포함할 수 없기 때문에, 서버는 이것이 유효하지 않은 요청임을 알고 처리하지 않을 것입니다.