CSRF란, CSRF 동작원리, CSRF 방어방법
CSRF란
CSRF란, Cross Site Request Forgery의 약자로, 한글 뜻으로는 사이트간 요청 위조를 뜻합니다.
CSRF는 웹 보안 취약점의 일종이며, 사용자가 자신의 의지와는 무관하게 공격자가 의도한 행위(데이터 수정, 삭제, 등록 등) 을 특정 웹사이트에 요청하게 하는 공격입니다.
예를 들어, 피해자의 전자 메일 주소를 변경하거나 암호를 변경하거나 자금이체를 하는 등의 동작을 수행하게 할 수 있습니다.
특성에 따라, 공격자는 사용자의 계정에 대한 완전한 제어권을 얻을 수 있을 수도 있습니다.
CSRF 동작원리
CSRF가 성공하려면, 아래 3가지 조건이 만족되어야 합니다.
1. 사용자는 보안이 취약한 서버로부터 이미 로그인되어 있는 상태여야 합니다.
2. 쿠키 기반의 서버 세션 정보를 획득할 수 있어야 합니다.
3. 공격자는 서버를 공격하기 위한 요청 방법에 대해 미리 파악하고 있어야 합니다.
예상하지 못한 요청 매개변수가 없어야 합니다.
이 조건이 만족되면 다음과 같은 과정을 통해 CSRF 공격을 할 수 있습니다.
1. 사용자는 보안이 취약한 서버에 로그인합니다.
2. 서버에 저장된 세션 정보를 사용할 수 있는 session ID가 사용자의 브라우저 쿠키에 저장됩니다.
3. 공격자는 사용자가 악성 스크립트 페이지를 누르도록 유도합니다.
악성 스크립트 페이지를 누르도록 유도하는 방식은 아래와 같은 방식들이 있습니다.
- 게시판이 있는 웹사이트에 악성 스크립트를 게시글로 작성하여 사용자들이 게시글을 클릭하도록 유도
- 메일 등으로 악성 스크립트를 직접 전달하거나, 악성 스크립트가 적힌 페이지 링크를 전달
4. 사용자가 악성 스크립트가 작성된 페이지 접근시 웹 브라우저에 의해 쿠키에 저장된 session ID와 함께 서버로 요청됩니다.
5. 서버는 쿠키에 담긴 session ID를 통해 해당 요청이 인증된 사용자로부터 온 것으로 판단하고 처리합니다.
예를 들어 설명해보겠습니다.
취약점이 있는 웹사이트에서 패스워드를 바꾸는 요청형식이 다음과 같다고 가정해보겠습니다.
POST /password/change HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 30
Cookie: session=yvthwsztyeQkAPzeQ5gHgTvlyxHfsAfE
password=passw0rd
그러면 공격자는 아래와 같은 html 문서를 사용자에게 열도록 유도하기만 한다면 mypassword라는 공격자가 의도한 패스워드 변경이 일어나게 됩니다.
<form action="https://vulnerable-website.com/password/change" method="POST">
<input type="hidden" name="password" value="mypassword">
</form>
<script>
document.forms[0].submit();
</script>
GET 형식으로도 간단히 처리할 수 있는것이라면 아래와 같이 img 태그가 포함된 글을 보기만 해도 로그아웃을 시킬 수도 있습니다.
<img src="http://vulnerable-website.com/logout" />
img 태그로 요청된 SRC 주소는 GET형식으로 처리가 되기 때문이지요.
CSRF 방어방법 - 사용자 입장
사용자 입장에서는 이상한 URL 을 함부로 클릭하지 않고, 의심이 되는 메일을 열어보지 않는것이 중요합니다.
위에서 설명드렸듯이, CSRF는 클릭만해도 바로 내가 의도하지 않은 action이 수행될 수 있기 때문입니다.
CSRF 방어방법 - 웹개발자/운영자 입장
1. Referer check (리퍼러 체크)
HTTP 요청 헤더(request header) 정보에서 Referrer 정보를 확인할 수 있습니다.
보통이라면 호스트(host)와 Referrer 값이 일치하므로 둘을 비교합니다.
CSRF 공격의 대부분 Referrer 값에 대한 검증만으로도 많은 수의 공격을 방어할 수 있다고 합니다.
Java servlet을 사용하신다면 아래와 같이 intercepter 클래스를 만들어서 모든 요청에 대해 referer check 할 수 있도록 방어가 가능합니다.
public class ReferrerCheck implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String referer = request.getHeader("Referer");
String host = request.getHeader("host");
if (referer == null || !referer.contains(host)) {
response.sendRedirect("/");
return false;
}
return true;
}
}
2. CAPTCHA 도입
요청시에 CAPTCHA 를 이용하여, CAPTHCA 인증코드가 없거나 틀리면 요청을 거부하도록 할 수 있습니다.
3. CSRF 토큰사용
사용자 세션에 임의에 값을 저장하여 모든 요청마다 해당 값을 포함하여 전송하도록 합니다.
서버에서 요청을 받을때마다, 세션에 저장된 값과 요청으로 전송된 값이 일치하여 검증하여 방어하는 방법입니다.
Java를 사용하신다면 아래와 같은 코드를 사용할 수 있습니다.
//로그인시 session value에 CSRF_TOKEN값 저장
session.setAttribute("CSRF_TOKEN", UUID.randomUUID().toString());
<!---요청시 CSRF_TOKEN 값을 전송하도록 해줌---->
<form action="http://example/path" method="POST">
<input type="hidden" name="CSRF_TOKEN" value="${CSRF_TOKEN}">
<!-- ... -->
</form>
// 요청을 받을시, 인터셉터에서 CSRF_TOKEN값 검증하도록 함.
public class CsrfTokenInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession httpSession = request.getSession();
String csrfTokenParam = request.getParameter("CSRF_TOKEN");
String csrfTokenSession = (String) httpSession.getAttribute("CSRF_TOKEN");
if (csrfTokenParam == null || !csrfTokenParam.equals(csrfTokenSession)) {
response.sendRedirect("/");
return false;
}
return true;
}
}
총평
대부분의 웹사이트 제작 프레임워크들은 CSRF공격을 잘 방어할 수 있게 플러그인들을 잘 제공하고 있습니다.
하지만, 제공하고 있다고 해서 모든 웹사이트들이 안전하다는 것은 아닙니다.
모던 프레임워크를 쓰더라도 플러그인을 사용하지 않은 경우가 있다던가,
웹개발자/운영자가 보안에 대한 개념이 없어 이러한 예방책을 웹 사이트에 탑재하지 않은 경우도 많습니다.
보안이 중시되는 금융등의 사이트에서는 이러한 보안공격에 대한 대처가 잘 되어있겠지만,
아직도 많은 여러 사이트들은 간단한 조치조차도 안되어있는 경우가 많습니다.
따라서 본인이 개발자라면 보안에 조금씩 관심을 가져 보안이슈가 발생하지 않도록 해야겠고,
사용자 입장에서는 이상한 웹사이트를 방문하거나 URL을 클릭, 혹은 수상한 메일을 열어보지 않는 등 여러 안전을 기해야 겠습니다.
결국엔 피해보는것은 개인이고, 피해에 대한 보상은 그 누구도 해주지 않는 경우가 많기 때문에 조심해야겠습니다.
CSRF란, CSRF 동작원리, CSRF 방어방법, 캡챠, CAPTCHA
#CSRF, #cross,#site,#request,#forgery,#CAPTHCA,#공격,#해킹,#방어,#보안,#웹사이트,#사이트간요청위조,#사이트,#요청위조,#요청,#위조,#캡챠
'개발용어' 카테고리의 다른 글
디자인패턴 - 싱글턴 패턴, singleton pattern (0) | 2022.10.15 |
---|---|
SOLID 원칙 - 의존성 역전 원칙, DIP (Dependency Inversion Principle) (0) | 2022.10.15 |
MVC패턴이란, Spring MVC란, Spring MVC 장점, Spring MVC (0) | 2022.07.06 |
code bad smell - 중첩 if문 (0) | 2022.06.27 |
FTP - passive 모드/ active 모드 차이점 (0) | 2022.05.23 |
댓글