본문 바로가기
파이썬 웹 프로그래밍 기본

5. 입력 처리 - 5.1. 비밀 토큰(secret token)

by 영바이트 2020. 8. 18.

블로그 글쓰기, 서비스 가입 등 웹 서버는 사용자로부터 데이터를 전달받는다. 사용자가 입력한 데이터의 처리 과정을 본격적으로 이야기하기 앞서 사용자로부터 데이터를 전달받는데 있어서 보안(security) 문제를 먼저 살펴보고자 한다. 최소한의 것이라도 보안 대책 없이 웹 서비스를 개설하는 것은 오히려 손해가 될 수 있다. 한번 잃어버린 개인정보나 적절한 권한없이 이루어진 서비스는 다시 돌이킬 수 없는 경우가 많기 때문이다.

 

사용자가 보내온 데이터 처리와 관련한 대표적인 보안 위험이 CSRF(Cross Site Request Forgery)다. 예를 들어 사용자의 비밀번호 재설정 요청과 처리를 살펴보자.

 

웹 서버의 동작 관점에서 비밀번호 재설정은 서버에 저장되어 있는 특정 사용자의 비밀번호 데이터를 새 비밀번호로 교체하는 동작으로 요약할 수 있다. 일반적으로 가장 많이 쓰이는 방법은 등록된 이메일로 비밀번호 재설정 페이지를 전달하고 해당 페이지를 통해 비밀번호를 재설정하는 것이다.

 

<정상적인 암호변경 요청>

 

하지만 이메일을 받지 않은 임의의 (악의를 가진) 사용자가 암호 변경 페이지를 흉내내어 만들고 암호 변경을 요청할 수도 있다.

 

<비정상적인 페이지를 통한 암호변경>

 

이와 같이 허가된 페이지가 아닌 임의의 페이지나 요청을 통해 서버 내의 데이터를 조작하고자 하는 시도들을 통틀어 CSRF 공격이라고 부른다. CSRF를 의미하는 ‘Cross Site Request Forgery’라는 용어의 뜻 자체가 ‘사이트 바꿔 쳐 요청 위조하기’이다.

 

CSRF 공격을 막기 위해 사용자로부터 데이터를 제공받고 이를 서버에 저장하거나 서버에 저장된 데이터를 수정하는 요청이 포함된 페이지는 웹 서버와 약속한 일정 크기의 데이터인 비밀 토큰(secret token)을 사용자가 입력한 데이터와 함께 전송한다. 웹 서버는 이 비밀 토큰을 받고 확인함으로써 정상적인 웹 페이지에서 데이터가 전달된 것인지 판단하게된다.

 

주고 받는 비밀 토큰은 그 내용을 예측하기 어려운 데이터 조각이면 된다. 따라서 파이썬 프로그래밍 관점에서 비밀 번호는 여러가지 방법으로 만들 수 있다. 그 중 한 방법인 secrets 패키지를 이용한 방법을 살펴보자. 파이썬 인터랙티브 툴인 IDLE(Integrated DeveLopment Environment, 윈도우 운영체제의 경우) 혹은 REPL(Read Evaluate Print Loop, Unix 계열 운영체제의 경우)을 실행시키고 아래 명령을 차례로 입력하자.

>>> import secrets

>>> secrets.token_hex(16)

 

<secrets 패키지를 이용한 비밀토큰 생성>

 

token_hex() 함수에 인자로 전달한 '16'은 16 byte 크기의 임의의 데이터를 생성하라는 의미이다. 이 비밀 토큰은 Flask 객체에 config변수에 설정되고 아래의 {{ form.hidden_tag() }}와 같이 웹 페이지에 삽입되어 사용된다.

<form method="POST" action="">
    {{ form.hidden_tag() }}
    <div>
        ...
        사용자 데이터 입력 필드들
        ...
    </div>
</form>

 

Flask 웹 서버는 페이지로부터 전달받은 비밀 토큰과 자신이 가지고 있는 비밀 토큰을 비교해서 페이지의 진위 여부를 가리게 된다. 이어지는 글들에서 사용자가 전달한 데이터를 처리하는 과정을 차례로 살펴보자.

 

댓글