[시큐어코딩 가이드] HTTP 응답분할
- 정보보안/시큐어코딩 가이드
- 2022. 8. 9.
■ 입력데이터 검증 및 표현
프로그램 입력 값에 대한 검증 누락 또는 부적절한 검증, 데이터의 잘못된 형식지정, 일관되지 않은 언어셋 사용 등으로 인해 발생되는 보안약점으로 SQL 삽입, 크로스사이트 스크립트(XSS) 등의 공격을 유발할 수 있다.
HTTP 응답분할
■ 개요
HTTP 요청에 들어 있는 파라미터(Parameter)가 HTTP 응답헤더에 포함되어 사용자에게 다시 전달될 때, 입력값에 CR(CarriageReturn)이나 LF(LineFeed)와 같은 개행문자가 존재하면 HTTP 응답이 2개 이상으로 분리될 수 있다. 이 경우 공격자는 개행문자를 이용하여 첫 번째 응답을 종료 시키고, 두 번째 응답에 악의적인 코드를 주입하여 XSS 및 캐시훼손(CachePoisoning) 공격 등을 수행할 수 있다.
Python 3.9.5+ 버전에서의 URLValidator에서 HTTP 응답분할 취약점이 보고되기도 했고 해당 라이브러리를 사용하는 Django버전에도 영향이 있다. HTTP 응답분할 공격으로부터 어플리케이션을 안전하게 지키려면 최신 버전의 라이브러리, 프레임 워크를 사용하고 외부 입력값에 대해서는 철저한 검증 작업을 수행해야 한다.
■ 안전한 코딩 기법
요청 파라미터의 값을 HTTP 응답헤더(예를 들어, Set-Cookie 등)에 포함시킬 경우 CR(\r), LF(\n)와 같은 개행문자를 제거한다. 외부 입력값이 헤더, 쿠키, 로그등에 사용될 경우에는 항상 개행 문자를 검증하고 헤더에 사용되는 예약어 등은 화이트리스트로 제한 할 수 있으면 화이트리스트로 제한하여야 한다.
코드예제
사용자 요청에 포함된 값을 필터링 및 검증 없이 응답에 사용하는 경우 개행문자로 인해 여러 개의 응답으로 분할되어 사용자에게 전달될 수 있다.
안전하지 않은 코드의 예 |
from django.http import HttpResponse def route(request): content_type = request.POST.get('contnet-type') # 외부 입력값을 검증 또는 필터링 하지 않고 # 응답헤더의 값으로 포함시켜 회신한다. ...... res = HttpResponse() res['Content-Type'] = content_type return res |
응답 분할을 예방하기 위해 \r, \n과 같은 문자에 대해서 치환 또는 예외처리 하여 응답분할이 발생하지 않도록 예방하여야한다.
안전한 코드의 예 |
from django.http import HttpResponse def route(request): content_type = request.POST.get('contnet-type') # 응답헤더에 포함될 수 있는 외부 입력값에 대해 개행문자를 제거한다. content_type = content_type.replace('\r', '') content_type = content_type.replace('\n', '') ...... res = HttpResponse() res['Content-Type'] = content_type return res |