본문 바로가기

Web

공격하지 마세요! (CSRF, XSS)

시작하기에 앞서

내가 웹 프론트엔드 개발을 시작한지 1년 8개월? 정도가 지났다

지금까지는 웹 페이지 구현, 신기술 도입, 코드 최적화 이런 개발적인 부분에만 집중해 공부를 했었는데 결국 공격을 당하면 의미가 없다는 것을 깨달았다 그래서 웹 보안 부분도 공부를 해야겠다고 생각을어서 가장 흔하게 발생한다는 CSRF, XSS공격에 대한 글을 쓰게되었다

 

CSRF

CSRF(Cross Site Request Forgery) 공격은 다른 사이트간 요청 위조라는 뜻으로

사용자의 의지와 무관하게 사용자가 의도한 행위들(데이터 변경, 삭제 등등)을 특정 웹 사이트로 요청을 보내는 공격이다

 

CSRF 공격 과정

 

CSRF 공격이 성공하려면 사용자는 아래의 조건을 만족해야한다

  • 사용자는 웹 사이트로부터 로그인이 되어 있어야 한다
  • 로그인 인증 방식은 cookie 기반으로 되어있어야 한다

위와 같은 조건이 만족한다면 아래와 같은 과정으로 공격을 할 수 있다

편의를 위해 사용자가 원래 이용하고 있는 사이트를 네이버라고 하고 공격자의 페이지를 해킹 페이지라고 부르겠다

  1. 사용자가 네이버에 로그인을 한다
  2. 사용자가 해킹 페이지에 접속을 한다 (로그인해서 받은 쿠키가 그대로 해킹페이지에서도 사용가능)
  3. 해킹 페이지에 접속을 했다면 해킹 페이지에서 네이버로 악의적인 요청을 보낸다 (ex 네이버 페이 결제, 비밀번호 변경)
  4. 네이버는 사용자가 정상적으로 요청을 보냈다고 생각하여 요청을 처리한다

CSRF 공격 예방

CSRF 공격 예방 방법은 찾아봤을때 3가지 방법이 있는것 같다

 

Same-Site

 

웹 페이지에서 서버로 로그인을 요청을 보내면 브라우저로 인증 쿠키를 발행해주는데 쿠키를 발행할때 부여할수 있는 속성중 하나이다

 

same-site를 판별하는 기준으로는 public suffix(.com, .net)를 기준으로 한 단계 하위 도메인까지만 확인해서 같으면 same site 라고 판별하고 이 방식으로 first-party context라고 한다

public suffix 목록이 궁금하다면 https://publicsuffix.org/list/public_suffix_list.dat 해당 페이지에서 확인 가능하다

 

same-site의 속성 값은 아래와 같다

  • None : Cookie 가 모든 상황에서 붙어서 전송 (secure 플래그 필수)
  • Lax : 위에서 말한 first-party context 또는 a 태그 document.location으로 최상단 window에서 다른 사이트로 이동할때 쿠키가 붙어서 이동된다
  • Strict : first-party context 일때만 전송 가능

그렇다면 same-site가 Lax값일때 iframe을 사용해서 다른 사이트에 접속하면 어떻게 될까?

답은 쿠키가 같이 이동 되지 않는다 왜냐하면 Lax 값은 최상단 window에서 다른 사이트로 이동할때만 쿠키가 같이 이동되기 때문이다

 

 

CSRF Token

CSRF token은 서버에서 페이지를 브라우저로 보내줄때 같이 보내줘 cookie에 저장한다

그리고 사용자가 서버로 요청을 할 때 header에  CSRF token을 같이 보내고(주로 header에 넣어서 보냄) 서버에서 일치하는지 확인해 요청을 처리한다

만약 공격자 페이지에서 요청을 보낸다면 크로스 도메인 요청은 간단한 요청만 보낼수 있어 header 조작을 하지 못해 공격을 방어할수 있다

 

Referer

Referer는 이전 페이지의 주소를 뜻한다 referer 검증을해서 현재 주소와 이전 주소가 일치하는지를 검증하면 CSRF 공격 방어가 가능하다

 


XSS

XSS(Cross Site Scripting)는 관리자가 아닌 사람이 웹페이지에 악의적인 script를 주입해 공격 할 수 있는 취약점이다

 

XSS 종류

  • Stored XSS (저장형 크로스사이트스크립트)
  • Reflected XSS (반사형 크로스사이트스크립트)
  • DOM Based XSS (DOM 기반 크로스사이트스크립트)

Stored XSS

저장형 XSS 공격은 게시판, 댓글과 같은곳에서 사용할수 있는 공격 방법이다

  1. 공격자가 악의적인 스크립트가 담긴 게시물을 취약한 서버에 올린다
  2. 피해자가 악의적인 스크립트가 담긴 게시물을 클릭한다
  3. 악의적인 스크립트가 실행되어 피해자의 정보가 털린다(ex. token)

Reflected XSS

반사형 XSS 공격은 input에 값을 넣어 요청을 보냈을때 서버에서 그대로 반환할때 공격할수 있는 방법이다

  1. 공격자가 악의적인 스크립트가 담긴 링크를 만들어 피해자가 클릭하도록 유도한다(ex. email)
  2. 피해자가 링크를 클릭한다
  3. 악의적인 스크립트가 실행되어 피해자의 정보가 털린다(ex. token)

 

 

 

DOM Based XSS

DOM 기반 XSS 공격은 반사형 XSS 공격처럼 악의적인 스크립트가 담긴 URL을 클릭하게 만들어 클릭시 문제가 발생하게 만든다

  1. 공격자가 악의적인 스크립트가 담긴 링크를 만들어 피해자가 클릭하도록 유도한다(ex. email)
  2. 피해자가 링크를 클릭한다
  3. 악의적인 스크립트가 실행되어 피해자의 정보가 털린다(ex. token)

 

Reflected XSS와 같다고 생각할수 있지만 Reflected XSS는 값을 그대로 반환하는 server가 있어야 하는 반면에

DOM Based XSS는 server가 필요없고 URL을 기반으로 화면에 페이지를 그리는 경우에 DOM Based XSS 공격이 가능하다

ex. '주소?step=1', '주소?step=2', '주소?step=3' step의 값을 가져와서 사용한다

 

XSS 공격 예방

InnerHTML 사용하지 않기

innerHTML은 HTML태그를 삽입할때 사용하는데 개발자들이 그냥 text를 삽입할때도 사용을 하여 XSS 공격에 취약하게 만든다

웬만하면 text를 삽입할때는 innerText나 textContent를 사용해 삽입하는게 더 안전하다

 

HTML Entity악성 스크립트가 삽입 되어도 동작하지 않도록 스크립트에 사용되는 <, > 등의 특수문자를 HTML Entity로 변환하여 사용한다

 

<!DOCTYPE html>
<html lang="en">
  <body>
    <div id="div">submit</div>
    <script>
      const div = document.getElementById("div");
      div.innerHTML = "&lt;img src=x /&gt;";
    </script>
  </body>
</html>

실행 결과

dangerouslySetInnerHTML

dangerouslySetInnerHTML은 React에서 InnerHTML 사용을 대체하기 위해서 만들어졌다

이유는 React에서 InnerHTML로 element를 추가하면 추적하기 못하기 때문에 dangerouslySetInnerHTML로 사용한다

const Component = () => {

  return <div dangerouslySetInnerHTML={{ __html: '<div style={{backgroundColor:"red"}}>hi</div>' }} />;
}

 

dangerouslySetInnerHTML prop에 값으로는 __html 필드가 담긴 객체를 전달하여 사용할수 있다

 

리액트에서는 dangerouslySetInnerHTML의 사용을 최대한 자제하라고한다

 

마무리

오늘은 내가 여태까지는 공부하지 않았던 보안 분야를 공부해서 그런지 어렵기도 했고 자료도 상당히 많이 찾아보았다

보안은 신뢰성있는 웹을 만드려면 필수적으로 챙겨야 하므로 다른 웹 취약점도 더 공부해보고 싶기도 하다

728x90

'Web' 카테고리의 다른 글

light house 사용해서 서비스 개선하기  (0) 2025.02.07
Web Storage  (0) 2023.12.11