은행 앱에서 한 사용자가 로그인을 통해 세션까지 발급받으며 인증(authentication) 받았고 해당 송금 기능을 사용하려고 한다. 사용자는 송금 페이지에 들어가 ‘송금하기’ 기능을 눌러 성공적으로 송금을 완료하였다. 그렇다면, 시스템 입장에서는 해당 송금 트랜잭션이 과연 ‘그’ 사용자로부터 이뤄졌는지 어떻게 확신할 수 있을까? 만약 ‘그’ 사용자는 의도하지 않았지만, 그를 위장한 또 다른 사용자로부터 행해진 것이라면?
CSRF(Cross Site Request Forgery)란 인증된 사용자가 웹 애플리케이션에 특정 요청을 보내도록 유도하는 공격 행위를 말하며, 생성된 요청이 사용자의 동의를 받았는지 확인할 수 없는 웹 애플리케이션의 CSRF 취약점을 이용한다. 즉, 세션을 통해 사용자를 인증하였다 하더라도 이후에 일어나는 요청이 정상적인 요청인지 비정상적인 요청인지 웹 애플리케이션은 구분할 수 없는 것이다.
CSRF는 데이터의 값을 변경하는 요청을 대상으로 하며, 대표적으로 제품 구입, 계정 설정, 기록 삭제, 비밀번호 변경, 문자 전송 등이 해당될 수 있다. 공격자는 자금 송금이나 로그인 정보 변경 등 자신이 원하는 요청으로 위조한 후, 이메일이나 웹사이트에 요청이 삽입된 하이퍼링크를 심어 놓는다. 이후, 인증된 사용자가 해당 하이퍼링크를 클릭하면 요청이 자동으로 전송된다. 특히, 관리자 계정이 이러한 공격을 받는 경우, 서비스 전체 통제권이 공격자에게 넘어갈 수 있으므로 큰 보안적인 위험이 초래될 수 있다.
크로스 사이트 스크립팅(XSS, Cross Site Scripting)과 크로스 사이트 요청 위조(CSRF, Cross Site Request Forgery)는 사용자의 브라우저를 대상으로 한다는 공통점이 있지만, 다음과 같은 차이점이 존재한다.
CSRF(Cross Site Request Forgery) | XSS(Cross Site Scripting) |
---|---|
웹 애플리케이션이 인증된 사용자의 요청을 신뢰한다는 사실을 이용 | 사용자가 특정 사이트를 신뢰한다는 사실을 이용 |
사용자의 인증된 세션을 악용 | 인증된 세션 없이도 공격을 진행할 수 있음 |
서버에서 스크립트가 실행됨 | 사용자로부터 스크립트가 실행됨 |
요청을 위조함으로써 특정 행위를 수행 | 사용자 PC에서 스크립트를 실행 |
로그아웃
CSRF는 인증된 사용자에게 미끼를 던지는 것과 같으므로, 사용자는 애플리케이션을 떠날 때 로그아웃하는 습관을 들이는 것이 좋으며, 설계자는 로그아웃을 어느 페이지에서나 할 수 있도록 페이지를 설계하는 것이 권장된다.
CSRF 토큰
토큰을 사용하여 요청이 사용자가 전송한 것이 맞는지 확인하거나 재인증을 요구한다. 이 때, 토큰 자체를 스니핑 당하는 것을 방지하기 위해 토큰은 일회성으로 만든다. 또한, 아래 예시에서는 토큰명을 ‘csrf_token’로 노골적으로 명시하였지만 실제 구현시에는 그렇게 하지 않는 것이 권장된다.
hidden
타입의 input
태그에 값으로써 숨겨서 보낼 수 있게 한다.)글 저장시 토큰 대조
서버는 동봉된 종이에 적힌 문자열과 자신의 토큰의 문자열의 일치여부를 확인한다.
(공격자의 위조 폼에는 token이 들어있지 않을 것이다.)
글 저장 완료시 토큰 파기
서버는 자신의 토큰을 파기한다. 이로써, 작성자(사용자)가 가지고 있던 종이는 그저 종이 조각에 불과해진다.
참고한 자료
[NordVPN] 크로스 사이트 요청 위조란?
도움될 만한 자료
[화이트해커][웹모의해킹] 24강. 아무도 모르게 비밀번호 변경을? CSRF 공격 개념