CSRF공격방어하기(ft. 로그인 방법)

악음·2022년 1월 4일
0

보안

목록 보기
2/2
post-thumbnail

CSRF를 방어해보자

참고한 싸이트

일단 CSRF 가 뭔지 알아야 방어를 할수있겠다.

CSRF(Cross Stie Request Forgery) : 사이트간 요청 위조

웹 애플리케이션 취약점 중 하나로 사용자가 자신의 의지와 무관하게 공격자가 의도한 행동을 하여 특정 웹페이지를 보안에 취약하게 한다거나 수정, 삭제 등의 작업을 하게 만드는 공격방법을 의미한다 - 나무위키

CSRF공격에 대한 유명한 일화가 있다.

2008년 옥션을 뚫어버렸던 공격 방식이다.

<img src="http://auction.com/changeUserAcoount?id=admin&password=admin" width="0" height="0">

위 옥션 사건을 예로 들어보자.

  1. 옥션 관리자 중 한명이 관리 권한을 가지고 회사내에서 작업을 하던 중 메일을 조회한다. (로그인이 이미 되어있다고 가정하면 관리자로서의 유효한 쿠키를 갖고있음)
  2. 해커는 위와 같이 태그가 들어간 코드가 담긴 이메일을 보낸다. 관리자는 이미지 크기가 0이므로 전혀 알지 못한다.
  3. 피해자가 이메일을 열어볼 때, 이미지 파일을 받아오기 위해 URL이 열린다.
  4. 해커가 원하는 대로 관리자의 계정이 id와 pw 모두 admin인 계정으로 변경된다.

위와같은 방법을 실행하려면 두가지 조건이 선행되어야한다.

  1. 위조 요청을 전송하는 서비스에 희생자가 로그인 상태
  2. 희생자가 해커가 만든 피싱 사이트에 접속

로그인 정보가 쿠키에 들어있다고하면 자동으로 url을 통해 서버로 전달되면 auth을 통과하게 될것이다.
이러한 과정을 통해 희생자가 해커가 올린 게시물이나 이메일 등을 통해 자기 정보를 바꾸거나 팀킬
하게 만든다는 것이다.

xss 공격과 다르게 클라이언트에서가 아닌 서버쪽에서 문제를 발생시킨다.

이제 진짜 방어를 해보자

하지만 방어를 알아보기전 로그인은 어떤방식으로 이루어지는지 알아보자

로그인은 어떻게 이루어지나?

  1. 세션 id를 이용하는 방식

    • 유저가 로그인한다(id와 password를 체크)
    • 서버는 세션을 생성한후 해당 세션의 id를 클라이언트에 보내준다
    • 클라이언트는 세션을 로컬스토리지, redux...에 저장한다.
    • 인증이 필요할때마다 로컬에 저장한 id를 가져와 서버에 보낸다
    • 서버는 받은 id가 유효한지 확인하여 인증한다.

  1. JWT를 이용하는 방식(FT. refreshToken, accessToken)
    • 유저가 로그인한다 (id와 password를 체크)
    • 서버가 인증 정보를 보내준다(id를 이용하여 jwt를 만든다.)
    • 인증정보는 accessToken과 refreshToken을 반환하며 이 두개의 토큰을 클라이언트에 저장한다.
    • accessToken은 만료시간이 있어 일정 시간이 지나면 사용할수없다.
    • 이를 방지하기위해 refreshToken을 사용하여 accessToken의 지속시간을 늘리거나 새로운 accessToken을 발급한다.(refreshToken사용은 옵션이다)
    • 즉 서버에 accessToken을 보내서 이 토큰이 유효한지(유효기간)지 체크한뒤 인증한다.
    • 유효시간이 지났다면 refreshToken으로 유효시간을 늘리고 refreshToken의 유효시간도 지났다면 로그아웃처리(쿠키에서 token모두 제거)

자이제 로그인 방법에 대해서 알았으니 방어를 해보자

그전에 보안은 어떤 공격에 의해서 뚫리는지 알아보자

공격종류

  1. xss공격
    • 공격자가 클라이언트 브라우저에 javascript를 삽입해 실행하는 공격이다.
      여러가지 html테그를 통해 (input, form,, 등등) javascript으로 서버로 전송하는 방 식처럼 클라이언트에서 스크립트 실행이 가능하다면 공격자가 사이트에 스크립트를 심어 xss공격을 할수있다. 대부분 게시판의 게시물 등을 통해 실행시킨다.
    • react에선 html이나 스크립트는 jsx를 통해서만 실행할수있기 때문에 비교적 안전하다.
      하지만 html에디터로 만든 게시물에경우 불가피하게 html render를 사용해야한다 하지만 html render를 자동으로 소톡해주는 라이브러리들이 있기 때문에 적절하게 방어가 가능하다.
    • 또한 React는 공격자가 string에 html / Javascript를 담아 JSX에 삽입할 경우 자동으로 escape 처리한다.
  2. CSRF공격은 위에 서술했으니 넘어가도록하겠다.

보통 React에선 세션 id이나 accesstoken은 llocalstorage 에 저장하거나 cookie에 저장한다. 비교적 안전하다고는 하지만 방심할수없다 어떤 취약점이 발견될지는 아무도 알수 없는 일이기 때문이다

로그인 정보 저장방법의 취약점

  1. localStorage
    • 브라우저에 저장하는 방식 떄문에 javascripta로 글로벌 변수 읽기/쓰기로 접근이가능하다.
      => 떄문에 xss공격에 취약
  2. 쿠키 저장방식
    • 이또한 javascript으로 읽기/쓰기가 가능하다.
      => xss공격과 CSRF공격에 취약
  3. secure, httpOnly 쿠키 저장방식
    • httpOnly 쿠기저장방식은 클라이언트에서 쿠키를 탈취할수 없게만든다.(때문에 서버에서 가져와야한다)
    • 하지만 xss 취약점으로 api콜을 때리면 서버에서 자동으로 쿠키를 가져오기때문에 (클라이언트에선 쿠키를 가져올수없기때문) 취약점이 생길수있다.

이제 진짜로 방어해보자ㅋ

자 어떤방법으로도 취약점이 발견될수도있다 이제 본격적으로 CSRF방어해보자.

JWT를 이용한 방식을 사용할것이다

로그인에 성공하면
1. refereshToken: secure httpOnly 쿠키로
2. accessToken은 JSON payload으로 받아와 리덕스에 넣는다.

위에 방법으로 어떤식으로 사용되고 방어하는지 알아보자

2가지 api으로 토큰 2개를 컨트롤해야한다.

  1. 화면이 리플레시되어 accessToken없어질경우 자동으로 refreshToken만 사용하는 api를 이용하여 accessToken재발급
    1-1. refreshToken의 유효성이 검증될경우 accessToken 재발급
    1-2. refreshToken의 유효성이 검증안될경우 로그아웃처리(쿠키에서 지움)
  2. auth가 필요한 로직들 (CRUD)에선 accessToken과 RefreshToken이 모두 유효성이 검증되어있는지 확인한다. (accessToken은 header bearer에 넣는다)
    2-1. accessToken이 없을경우 실행불가
    2-2. 두 토큰의 유효성이 전부 검증될경우 BR 실행
    2-3. accessToken의 유효시간이 지났더라도 RefreshToken의 유효시간이 있다면 accessToken을 재발급시킨다음 BR실행
    2-4. refreshToken은 무조건 accessToken보다 유효시간이 길어야한다.
    2-5. refreshToken의 유효시간이 지났을경우 로그아웃처리한다.
<img src="http://auction.com/changeUserAcoount?id=admin&password=admin" width="0" height="0">

위와같이 url으로만 공격한다고하면

  1. 서버에서 cookie에 접근하여 refreshToken을 가져오지만 accessToken은 헤더에서 찾기때문에
    (url으로만으로는 헤더에 넣어서 보낼방법이 없다) 서버에선 refreshToken만 받아온다 = auth 실패
  2. refreshToken은 클라이언트에서 알아낼수 없도록 httpOnly옵션이 있기 때문에 클라이언트에서 refreshToken을 탈취할수 없다.
  3. refreshToken을 어떤 방법으로 알아내서accessToken을 받아온다고해도 그즉시 변수에 할당하기때문에 accessToken을 알수없다.
profile
RN/react.js개발자이며 배운것들을 제가 보기위해서 정리하기 때문에 비속어 오타가 있을수있습니다.

0개의 댓글