블로그 글쓰기, 서비스 가입 등 웹 서버는 사용자로부터 데이터를 전달받는다. 사용자가 입력한 데이터의 처리 과정을 본격적으로 이야기하기 앞서 사용자로부터 데이터를 전달받는데 있어서 보안(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)
token_hex() 함수에 인자로 전달한 '16'은 16 byte 크기의 임의의 데이터를 생성하라는 의미이다. 이 비밀 토큰은 Flask 객체에 config변수에 설정되고 아래의 {{ form.hidden_tag() }}와 같이 웹 페이지에 삽입되어 사용된다.
<form method="POST" action="">
{{ form.hidden_tag() }}
<div>
...
사용자 데이터 입력 필드들
...
</div>
</form>
Flask 웹 서버는 페이지로부터 전달받은 비밀 토큰과 자신이 가지고 있는 비밀 토큰을 비교해서 페이지의 진위 여부를 가리게 된다. 이어지는 글들에서 사용자가 전달한 데이터를 처리하는 과정을 차례로 살펴보자.
'파이썬 웹 프로그래밍 기본' 카테고리의 다른 글
5. 입력 처리 - 5.3. Flask WTF를 이용한 입력처리 프로젝트 (0) | 2020.08.21 |
---|---|
5. 입력 처리 - 5.2. Flask WTF를 이용한 입력처리 (0) | 2020.08.20 |
4. 웹 페이지 - 4.2. 템플릿 예제 코드분석 (0) | 2020.08.17 |
4. 웹 페이지 - 4.1. 템플릿(template) 엔진 (0) | 2020.08.16 |
3. 웹 프로그램 동작 원리 - 3.2. Flask 예제 분석 (0) | 2020.08.15 |
댓글