본문 바로가기

정처기지식, 소프트웨어 공학

XSS, CSRF

https://www.youtube.com/watch?v=DoN7bkdQBXU

https://www.youtube.com/watch?v=nzoUgKPwn_A&list=PLRx0vPvlEmdDQxb41uc1G4ecjV-hklFDM&index=10

참고: https://velog.io/@minjae-mj/%EC%9B%B9%EC%82%AC%EC%9D%B4%ED%8A%B8-%EB%B3%B4%EC%95%88-%EA%B3%B5%EA%B2%A9-XSS-CSRF

XSS(Cross Site Scripting):

💡 Cross-Site Scripting (XSS) 공격

공격자가 클라이언트 코드에 악의적인 스크립트를 주입하는 공격이다. 웹 어플리케이션의 유효성 검사나 인코딩이 충분하지 않을 경우, 브라우저는 스크립트의 악의성을 감별할 수 없다. 공격자는 사용자를 가장하여, 쿠키와 세션 토큰, 사이트에 민감한 정보들에 접근이 가능해지며 클라이언트 코드를 재작성하여 해킹하기도 한다. 이러한 문제는 주로 1) 확인되지 않은 경로를 통해 데이터가 입력되거나 2) 동적인 데이터의 유효성 검사가 적절히 이루어지지 않고 사용자에게 보내지는 경우에 발생한다.

악의적인 콘텐츠는 대개 자바스크립트를 포함하나, 때에 따라 HTML, Flash 등 브라우저가 실행하는 어떤 종류의 코드든 가능하다. XSS 공격은 1) 쿠키나 세션 정보와 같은 기밀 정보를 빼가거나 2) 접속자를 자신들이 의도한 페이지로 리디렉트 하거나 3) 정상적인 사이트 흉내를 내며 사용자의 컴퓨터에 악의적인 공격 (악성코드를 다운로드하거나 개인정보를 입력하도록 유도) 을 하여 해를 입힌다. 대표적인 유형으로 다음 두 가지를 알아본다.

stored / persistent
XSS 취약점이 있는 타겟 서버에 악성 스크립트를 저장시킨 후, 브라우저가 서버에 데이터를 요청하면 희생자는 이 조작된 스크립트를 받게 된다. 만약 회사 등 조직의 개인 컴퓨터가 해킹될 경우, 조직 내부로 악성 코드가 이동하여 내부의 중요 정보가 탈취될 수 있다.

reflected / non-persistent
사용자가 악의적으로 조작된 링크를 누르거나, 폼을 제출하거나, 사이트에 방문을 하는 경우에 주입된 코드가 희생 대상이 되는 웹사이트로 퍼진다. 웹 서버는 주입받은 코드를 정상적인 요청으로 인식하여, 브라우저에 그에 대한 응답을 한다. 에러 메세지를 띄우거나, 특정 검색결과를 보여줄 수도 있고, 어떤 데이터를 포함할 수도 있다. 브라우저는 서버가 악의적으로 영향받았다는 사실을 인지하지 못하므로, 정상 응답으로 파악하여 코드를 실행한다. 만약 input 창에 댓글을 입력하면 화면에 보여주는 기능이 있다고 할때, 악의적으로 <script>alert('this website is hacked!')</script> 과 같이 입력하여 개발자의 의도를 무시하고 새로운 동작을 입힐 수 있다.

🧼 XSS 공격 예방

  • User input value 제한
    유저 입력값이 한정적인 범주안에서 예측 가능하다면, 드롭다운 등을 사용하여 미리 입력될 데이터값을 통제할 수 있다.
  • Sanitize value
    악성 HTML을 필터링해주는 라이브러리 사용도 가능하다.
  • 스크립트 문자 필터링
    DOM 상의 텍스트를 읽을 때 html 태그를 읽는 innerHTML 사용을 지양하고, textContent 등으로 메소드를 대체한다. 메소드 내용은 이전 블로그에 정리한 바 있다.

 

특정의도를 가진 스크립트를 입력창에 입력함으로써 웹프라우저가 그것을 읽어서 문제가 발생하게 함. JS는 XSS공격의 주 타켓이됨.

XSS방지대책

1.쿠키에 중요한 정보를 담지 않고 서버에 중요 정보를 저장하는 방식을 사용
2. httponly 속성을 다는 방식을 사용(document.cookie를 이용해서 쿠키에 직접 접근하는 것을 막는 옵션임)
3. 마지막으로 보안과 관련된 함수를 사용한 Secure coding을 통해 XSS를 방지할 수 있음.

💡 Cross-Site Request Forgery (CSRF 또는 XSRF) 공격

공격자가 '사용자의 동의없이 / 사용자가 인지하지 못하는 상황에서' 브라우저로 하여금 서버에 어떤 요청을 보내도록 한다. XSS 공격으로 탈취한 정보를 이 때 사용할 수 있다.

MDN 이 인용한 위키피디아의 예시를 살펴보자. 공격자는 이미지 태그를 가장하여, 실제로는 은행 서버로부터 돈을 인출하는 코드를 작성하였다.

&amount=1000000&for=me">

만약 희생자의 컴퓨터가 은행 사이트에 접속한 이후에 쿠키가 유효한 상태라면 (그리고 돈을 인출할 때 필요한 다른 유효성 검사가 없다고 가정하면) 위의 이미지가 포함된 HTML 이 로딩되는 순간, 돈이 인출되도록 할 수 있다. POST 요청을 하는 form 태그는 페이지 로딩이 되는 순간 submit 이 되도록 조작할 수 있기 때문이다.

method="POST">
  <input type="hidden" name="account" value="you">
  <input type="hidden" name="amount" value="1000000">
  <input type="hidden" name="for" value="me">
</form>

<script>
  window.addEventListener('DOMContentLoaded', 
    (e) => { document.querySelector('form').submit(); }
</script>

🧼 CSRF 공격 예방

일반적으로 CSRF 공격 방어는 GET 메소드와 같은 조회성 요청은 제외하고, 데이터 조작이 가능한 POST, PATCH, DELETE 메소드에 적용한다. 때에 따라 기밀 데이터이거나, GET 메소드를 통해 쓰기, 변경 등의 동작을 한다면 GET 메소드도 물론 방어해야 한다.

  • Referrer 검증 (SameSite 쿠키 설정)
    Back-end 단에서 request의 referrer를 확인하여 domain (e.g. *.instagram.com) 이 일치하는 지 검증하는 방법이다. referrer 검증만으로 대부분의 CSRF 공격을 방어할 수 있다. 민감한 정보를 담고 있는 쿠키 (세션 쿠키 등) 는 유효 시간을 짧게 설정하고, 쿠키의 SameSite 속성을 Strict 또는 Lax 로 설정한다. 이러한 세팅으로, 이를 지원하는 브라우저에서는 cross-site 요청에 세션 쿠키를 보내지 않는다. 하지만 같은 domain 내의 페이지에 XSS 취약점이 있는 경우 CSRF 공격에 취약해질 수 있다. domain 단위 검증에서 좀 더 세밀하게 페이지 단위까지 일치하는지 검증을 하면 도메인 내의 타 페이지에서의 XSS 취약점에 의한 CSRF 공격을 방어할 수 있다.
  • Security Token 사용 (A.K.A CSRF Token)
    Referrer 검증이 불가한 환경이라면, Security Token를 활용할 수 있다. 우선 사용자의 세션에 임의의 난수 값을 저장하고 사용자의 요청 마다 해당 난수 값을 포함 시켜 전송한다. 이후 Back-end 단에서 요청을 받을 때마다 세션에 저장된 토큰 값과 요청 파라미터에 전달되는 토큰 값이 일치하는 지 검증하는 방법이다. 이 방법도 결국 같은 도메인 내에 XSS 취약점이 있다면 CSRF 공격에 취약해진다. 아래는 간략한 샘플 코드이다.