일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- SQL
- 자바스크립트
- db
- C#
- 트리플DES
- VMWare
- 스프링부트
- mysql
- springboot
- 자동증가열
- 데이터베이스
- CrossSiteScripting
- 이미지엑박
- ASP
- 프로그래머스
- HTML
- PHP
- 람다식함수
- 가상머신
- 코딩테스트
- 오라클
- ascx.cs
- 다중기본키
- mssql
- 쿼리
- oracle
- 다중pk
- windows7
- memoryDB
- javascript
- Today
- Total
개발바닥 아방수
CSRF(Cross-Site Request Forgery) 공격과 방어 본문
1. CSRF, Cross-Site Request Forgery
CSRF(Cross-Site Request Forgery) - 사이트 간 요청 위조
사용자가 자신의 의지와는 무관하게 공격자가 의도한 행위(수정, 삭제, 등록 등)를 특정 웹사이트에 요청하게 하는 공격을 말한다.
정상적인 사용자가 의도하지 않았지만, 자신도 모르게 서버를 공격하게 되는 경우입니다. 공격자가 만든 악성 페이지를 통해 사용자는 자신도 모르게 공격을 수행합니다. 어떻게 이런 공격이 가능한지 확인해보겠습니다.
1.1. Cookie and Session
우선 쿠키와 세션에 대한 간단한 이해가 필요합니다. 사용자가 특정 서버에 로그인하면 일반적으로 다음과 같은 작업들이 수행됩니다.
- 서버는 로그인 시 인증된 사용자의 정보를 세션(session)에 저장하고, 이를 찾을 수 있는 sessionID을 만듭니다.
- 서버는 저장된 세션 정보를 클라이언트(브라우저)가 사용할 수 있도록 sessionID를 Set-Cookie 헤더에 담아서 전달합니다.
- 클라이언트(브라우저)는 전달된 sessionID를 쿠키에 저장합니다.
- 클라이언트(브라우저)는 해당 도메인을 가진 서버로 요청 시 쿠키에 저장된 sessionID를 자동으로 전달합니다.
- 서버는 쿠키에 담긴 sessionID를 통해 인증된 사용자인지 여부를 확인합니다.
1.2. CSRF 전제 조건과 공격 과정
CSRF 공격을 위한 조건과 과정에 대해 알아보겠습니다. CSRF 공격을 시도하기 위해선 아래와 같은 몇 가지 조건이 필요합니다.
- 사용자가 보안이 취약한 서버로부터 이미 인증을 받은 상태여야 합니다.
- 쿠키 기반으로 서버 세션 정보를 획득할 수 있어야 합니다.
- 공격자는 서버를 공격하기 위한 요청 방법에 대해 미리 파악하고 있어야 합니다. 예상치 못한 파라미터가 있으면 불가능합니다.
위와 같은 조건이 만족되면 다음과 같은 과정을 통해 CSRF 공격이 수행됩니다.
- 사용자는 보안이 취약한 서버에 로그인합니다.
- 로그인 이후 서버에 저장된 세션 정보를 사용할 수 있는 sessionID가 사용자 브라우저 쿠키에 저장됩니다.
- 공격자는 서버에 인증된 브라우저의 사용자가 악성 스크립트 페이지를 누르도록 유도합니다.
- 해당 악성 스크립트가 담긴 페이지를 클릭하도록 유도하는 방법은 다양한 것 같으나 몇 가지 유형을 정리하자면 다음과 같습니다.
- 게시판에 악성 스크립트를 게시글로 작성하여 관리자 혹은 다른 사용자들이 게시글을 클릭하도록 유도합니다.
- 메일 등으로 악성 스크립트를 직접 전달하거나, 악성 스크립트가 적힌 페이지 링크를 전달합니다.
- 사용자가 악성 스크립트가 작성된 페이지 접근시 쿠키에 저장된 sessionID는 브라우저에 의해 자동적으로 함께 서버로 요청됩니다.
- 서버는 쿠키에 담긴 sessionID를 통해 해당 요청이 인증된 사용자로부터 온 것으로 판단하고 처리합니다.
2. CSRF 공격 방법
간단한 POC(Proof Of Concept) 코드를 작성하여 CSRF 공격을 재현해보겠습니다. 공격자는 취약 서버의 사용자 이름을 변경하는 방법을 파악하고, 악성 스크립트가 작성된 페이지를 사용자가 클릭하도록 유도했다고 가정합니다. GitHub 레포지토리에서 테스트와 관련된 프로젝트를 받을 수 있습니다.
- https://github.com/Junhyunny/blog-in-action/tree/master/2021-12-29-cross-site-request-forgery
- backend - 보안 취약 서버 (DOMAIN - localhost / PORT - 8081)
- attacker - 공격자 서버 (DOMAIN - 127.0.0.1 / PORT - 8080)
보안 취약 서버의 AuthenticationInterceptor
- 보안 취약 서버에는 다음과 같은 인증 인터셉터(interceptor)가 존재합니다.
- 쿠키 정보를 바탕으로 세션에 저장된 사용자 정보 유무를 확인합니다.
- 사용자 정보가 없다면 로그인 페이지로 리다이렉트(redirect)시킵니다.
- 해당 코드로 인해 사용자가 로그인하기 전에 악성 페이지에 접근하더라도 사용자 정보를 변경할 수 없습니다.
2.1. GET 방식 공격
<img /> 태그(tag)를 사용하거나 하이퍼링크를 걸어주는 <a></a> 태그를 이용합니다. 이번 테스트에서는 <img /> 태그를 사용하였습니다.
공격자 악성 페이지 - GET 방식
- 이미지 태그를 통해 페이지 로딩시 보안 취약 서버로 GET 요청을 보냅니다.
- width, height 값이 0px이므로 화면에서 보이지 않습니다.
2.2. POST 방식 공격
<form></form> 태그와 hidden 타입의 <input /> 태그를 사용합니다. JavaScript를 이용해 페이지 렌더링이 수행되자마자 폼 전송을 시도합니다.
공격자 악성 페이지 - POST 방식
- form 태그와 hidden 타입의 input 태그로 POST 요청을 수행합니다.
3. CSRF 방어 방법
공격 방법에 대해 알아보았으니 방어 방법에 대해 정리해보겠습니다. GitHub 레포지토리에서 테스트와 관련된 프로젝트를 받을 수 있습니다.
- https://github.com/Junhyunny/blog-in-action/tree/master/2021-12-29-cross-site-request-forgery
- enhanced-backend - 보안 강화 서버 (DOMAIN - localhost / PORT - 8081)
3.1. Referrer 검증
서버에서 사용자의 요청에 Referrer 정보를 확인하는 방법이 있습니다. 요청 헤더(request header) 정보에서 Referrer 정보를 확인할 수 있습니다. 보통이라면 호스트(host)와 Referrer 값이 일치하므로 둘을 비교합니다. CSRF 공격의 대부분 Referrer 값에 대한 검증만으로 방어가 가능하다고 합니다.
3.2. CSRF 토큰 검증
임의의 CSRF 토큰을 만들어 세션에 저장합니다. 요청하는 페이지에 hidden 타입 input 태그를 이용해 토큰 값을 함께 전달합니다. 이후 서버에서 세션에 저장된 CSRF 토큰 값과 요청 파라미터에 담긴 토큰 값을 비교합니다.
3.3. Double Submit Cookie 검증
브라우저의 Same Origin 정책을 이용합니다. Same Origin이 아닌 경우 JavaScript로 쿠키 값을 확인하거나 수정하지 못한다는 점을 이용한 검증 방법입니다. 클라이언트(브라우저)에서 JavaScript로 임의의 생성한 토큰을 쿠키와 요청 헤더에 각각 담아서 서버에게 전달합니다. 서버는 전달받은 쿠키와 요청 헤더에서 각자 토큰 값을 꺼내어 이를 비교합니다. 이때, 쿠키에 저장된 토큰 정보는 이후에 재사용하지 못하도록 만료 처리합니다.
4. CSRF disable 설정 안전한가?
Spring Security 프레임워크는 기본적으로 CSRF 공격에 대한 방지를 수행합니다. CSRF 공격에 대처할 수 설정을 disable 시키는 것이 과연 좋은 방법인지 찾아봤습니다.
예전에 많이 사용했던 MVC 구조는 세션과 쿠키를 통해 사용자 인증을 수행했기 때문에 CSRF 공격에 취약합니다. Stateful 한 서비스를 제공하기 위해 인증된 사용자 정보를 세션에 저장하고, 세션 ID가 쿠키에 저장되기 때문에 문제가 발생합니다.
StackExchange - Should I use CSRF protection on Rest API endpoints?
No cookies = No CSRF
네, 쿠키가 없으면 CSRF 공격도 없습니다. 브라우저에 저장되는 쿠키가 CSRF 공격의 매개체입니다. 최근 많이 사용하는 REST API 방식은 쿠키나 세션에 의존하지 않는 경향이 크기 때문에 CSRF 공격에 대한 방어 설정을 비활성화시키는 경우가 많다고 합니다. 쿠키 대신에 로컬 스토리지(localStorage)와 요청 헤더(Request Header) 사용하거나, 세션 대신에 JWT(Json Web Token)을 사용하기 때문입니다. 하지만, CSRF 공격에 대한 방지를 disable 시키더라도 인터셉터 등에서 적절한 방어 코드를 통해 보안 수준을 높이는 것이 좋을 것 같습니다.
'정보보안' 카테고리의 다른 글
XSS(Cross Site Scripting) 공격기법, 시큐어 코딩 (1) | 2022.11.22 |
---|---|
[암호화] 초기화 벡터, 3DES, 3중 DES, 트리플 DES(triple DES) (0) | 2022.11.22 |