저번 웹 공부 글에 이어 이번에는 HTTP의 메세지 구조를 자세히 살펴보고 정리해보려 한다. 이번 학기에 수강한 '웹보안' 과목에서 과제로 제출했던 CRLF 취약점은 HTTP 응답이 줄바꿈문자를 필터링 하지 않아 발생하는 공격이기 때문에, 특히 HTTP의 요청과 응답 메세지 구조에 대해 궁금했다.
1. URL과 URI
HTTP를 정리하기 전에 URL과 URI에 대해서도 간단하게 공부해보았다. CRLF 취약점의 공격구문에 들어가는 코드를 URI값으로 인코딩해야하기 때문이다.
URI = Uniform Resource Identifier 식별자
URL = Uniform Resource Locator 위치
URN = Uniform Resource Name 이름
URL과 URI는 웹 브라우저 등에서 웹페이지를 보기 위해 입력하는 주소라고 생각하면 된다. URI는 어떤 서식을 사용해 특정 자원에 접근하기 위한 식별자이다. 인터넷에서는 자원에 접근하기 위해 해당 자원의 이름을 그대로 쓰는 방법을 사용한다.
-HTTP의 경우 'http'를 사용한다. 그 밖에 https나 mailto, ws, file 같은 것이 있다.
-URI는 리소스를 식별하기 위한 문자열 전체를 표시하는 반면, URL은 자원의 위치(네트워크상의 위치)를 표시한다.
-URL은 URI의 하위 집합이다. (따라서 나는 URL보다 URI라고 부르는게 더 정확하지 않을까 생각했다.)
-URL를 지정하는 방법은 필요한 정보 전체를 지정하는 절대 URI 또는 절대 URL과 현재 있는 위치의 URI로부터 상대적인 위치를 지정해 찾는 상대 URL이 있다.
URL와 URI에 대해 잘 정리한 티스토리가 있어 가져와보았다.
출처는 https://velog.io/@jch9537/URI-URL
1.1 퍼센트 인코딩
퍼센트 인코딩은 URI에서 사용할 수 없는 문자를 사용할 때 쓰는 인코딩 방식이다. URL인코딩이라고도 하며 RFC3986에 저장되어있다. 퍼센트 인코딩을 사용하면 대상이 되는 문자는 바이트 단위로 나뉘어 %xx(16진수) 형태로 표시된다. 예외로 HTTP의 POST 메서드를 사용해 웹 폼 문자열을 전송할 때 MIME의 Content-type에서는 공백이 %20이 아니라 +로 변경된다.
ex. I love you -> i+love+you
2. 단순 프로토콜 HTTP
TCP/IP 규약을 사용하는 다른 많은 프로토콜과 마찬가지로 HTTP는 클라이언트와 서버 사이에서 통신을 수행한다. 텍스트나 이미지 같은 자원을 요청하는쪽이 클라이언트가 되고 해당 리소스를 제공하는 쪽이 서버가 된다. 2대의 컴퓨터가 HTTP를 사용해 통신하는 경우 어느 한쪽은 반드시 클라이언트가 되고, 다른 한쪽이 서버가 된다. 때에 따라서는 역할이 바뀔수도 있겠지만 한 번의 통신에서는 클라이언트와 서버의 기능이 정해져있다. HTTP는 클라이언트와 서버의 역할이 명확히 구분된다.
2.1 통신은 요청(Request)와 응답(Response)의 교환
HTTP는 클라이언트로부터 요청을 받아 서버로 전달하고 서버에서 받은 응답을 클라이언트로 전달해준다. HTTP/1.1에서는 언제나 클라이언트로부터 통신이 시작된다. 서버쪽이 요청을 받지않고 응답을 먼저 보내는 일은 없다.
구체적인 HTTP통신 내용을 살펴보자
클라이언트가 GET요청을 전송하면 서버가 HTTP/1.1 200OK 응답을 전송한다.
여기서 교환하는 데이터는 HTTP 메세지라고 하며 요청하는 쪽의 HTTP메세지를 요청메세지, 응답하는 쪽의 메세지를 응답메세지라고 한다.
HTTP 메세지는 여러 줄(줄바꿈코드는 CR+LF)의 데이터로 구성된 문자열이다. HTTP 메세지는 메세지 헤더와 메세지 바디로 구성된다. 헤더와 바디를 구분하는 것은 빈 행 (CR+LF)이다. 참고로 헤더는 모든 메세지에 존재하지만 메세지 마디는 존재하지 않을 수도 있다.
-메세지 해더 : 서버나 클라이언트가 처리한 요청이나 응답내용 또는 속성
-빈행 (CR+LF) : (CR:케리지 리턴 0x0d, LF: 라인 피드 0x0a)
-메세지 바디 : 전송돼야 할 데이터
3. HTTP 메세지 구조
요청메세지
메세지 헤더 : 요청라인 / 요청헤더필드 / 일반 헤더 필드 / 엔티티 헤더 필드 / 기타
빈 행
메세지 바디
응답메세지
메세지 헤더 : 상태 표시 라인 / 요청헤더필드 / 일반 헤더 필드 / 엔티티 헤더 필드 / 기타
빈 행
메세지 바디
3.1 메세지 바디와 엔티티 바디의 차이
메세지 : HTTP 통신의 기본 단위로, 옥탯 시퀀스로 구성되며 통신을 통해 전송된다.
엔티티 : 요청이나 응답의 페이로드로 전송되는 정보로 엔티티 헤더 필드와 엔티티 바디로 구성된다.
-> HTTP 메세지 바디의 역할은 요청과 응답에 대한 엔티티 바디를 전달하는 것이다.
기본적으로 메세지 바디 = 엔티티바디 지만 전송 인코딩이 적용된 경우 엔티티 바디의 내용이 변하기 때문에 메세지 바디와는 달라지게 된다.
3.2 요청(Request) 메세지의 구성
첫줄
POST/GET:메서드 - 어떤 종류의 요청을 보내는지를 나타낸다
/어쩌고저쩌고/: 요청URI - 요청 대상이 되는 자원을 나타낸다.
HTTP/1.1:프로토콜버전 - 클라이언트의 기능을 식별하기 위한 HTTP버전번호
두번째줄
요청 헤더 필드
빈행
엔티티
3.3 응답(Response) 메세지의 구성
첫줄
HTTP/1.1 : 프로토콜 버전
200 : 상태코드
OK : 상태코드 설명
두번째줄
응답헤더필드
빈행
바디 : 자원의 본체
3.4 헤더 필드 구조
헤더 필드는 헤더 필드이름과 필드 값으로 구성되어있으며 :(콜론)으로 구분된다. 헤더필드 이름은 US-ASCII 문자로 구성되어있다.
예를들어 메세지 바디의 객체종류를 나타내기 위해서는 Content-Type이라는 헤더필드를 포함한다. 이 경우 Content-Type이 헤더필드 이름이 되고 문자열 text/html은 필드의 값이 된다. 또한 필드 값은 다음과 같이 한 개의 HTTP헤더필드에 여러값을 가질 수도 있다.
Keep-Alive:timeout15,max100
3.5 HTTP 헤더필드가 중복되면 어떻게 될까
HTTP 메세지 헤더 안에 같은 헤더 필드 이름이 2개이상 존재하는 경우, 이것은 정확한 사양이 정해져 있지않기 때문에 브라우저에 따라 다르게 동작한다. 어떤 브라우저에서는 가장 첫번째 등장하는 필드를 우선하여 처리하고, 또 어떤 브라우저에서는 가장 마지막 필드를 우선해서 처리할 수도 있다.
3.6 메서드로 서버에 명령 내리기
요청 URI를 통해 인터넷에 있는 자원에 요청을 보낼 때는 메서드라는 명령을 이용한다. 메서드는 자원에 어떤 식으로 요청할지 지시하기 위한 것이다. 메서드에는 대표적으로 GET,POST, HEAD와 같은 종류가 있다.
POST 메서드는 엔티티를 전송하기 위해 사용한다. 즉, 어떤 데이터를 웹 서버에 전달하기 위해 사용한다. GET으로도 엔티티를 전송할 수 있지만 일반적으로 POST를 사용한다. POST는 GET과 기능이 비슷하지만 목적이 다르다. GET은 자원을
휙득하는 것이 목적이고, POST는 클라이언트의 데이터를 웹 서버로 전송하는 것이 목적이다.
3.7 결과를 알려주는 HTTP 상태 코드
상태코드는 '200OK'와 같이 3자리 숫자와 문자열로 된 설명으로 구성된다.
세자리 숫자중 제일 첫번째 숫자는 응답의 클래스를 나타내며 다음 표와 같이 5가지 종류가 있다.
우리가 자주 보는 404 NOT FOUND도 HTTP 응답코드 중 하나이다.
4. HTTP는 상태를 보존하지 않는 프로토콜
HTTP는 상태를 보존하지 않는 상태 비보존형 프로토콜이다. HTTP는 요청과 응답을 하면서 주고 받는 상태를 프로토콜 자체에 저장하지 않는다. 즉, HTTP라는 프로토콜 레벨에서는 이전에 보낸 요청이나 받은 응답에 대해서는 아무것도 기억하지 않는다. 처음HTTP를 설계할 때는 많은 처리를 신속하고 안정적으로 처리할 수 있도록 확장성 확보를 위해 이렇게 단순하게 설계를 했다. 하지만 웹이 진화함에 따라 상태를 보존하지 않는 것이 문제가 되기 시작했다. 예를들어 쇼핑 사이트에 로그인 하면 다른 페이지로 이동해도 로그인 상태를 유지해야 한다. 그렇게 하기 위해서는 누가 어떤 요구를 하고 있는지 파악하기 위해 상태를 보존해야 한다.
4.1 쿠키를 통한 상태관리
HTTP를 상태 비보전형 프로토콜인 채로 사용하기 위해서 쿠키 Cookie라는 기술이 도입됐다. 쿠키를 활용한 세션관리를 수행함으로써 상태를 관리할 수 있게 됐다. 쿠키는 서버에서 응답으로 보내는 Set-Cookie 헤더필드를 사용해 클라이언트에게 쿠키를 저장할 것을 지시한다. 그리고 클라이언트는 이 응답을 받고 쿠키를 보존한다. 이후 클라이언트는 같은 서버에 요청을 보낼 때 자동으로 쿠키값을 넣어 서버로 전송한다. 서버는 클라이언트가 보낸 쿠기값을 보고 서버에 저장된 값과 확인해 어떤 클라이언트로 부터 온 요청인지 파악할 수 있다. (이후, 쿠키 세션 캐시에 대해 더 자세히 공부한 후 업로드 하겠다!)
쿠키와 관련하여 이 영상을 참고하면 이해가 잘 된다.
https://www.youtube.com/watch?v=OpoVuwxGRDI
'정보보안 공부 > 웹' 카테고리의 다른 글
[웹] 민감데이터 노출 (Sensitive Data Exposure) 유형 및 대응방안 (0) | 2021.07.10 |
---|---|
[웹] CRLF HTTP Splitting 공격 실습 (WebGoat v5.4) (1) | 2021.05.26 |
[웹] 웹 기초 (1) - HTTP, TCP/IP (0) | 2021.05.24 |
[웹] CRLF 취약점 (HTTP 응답 분할 공격) (0) | 2021.04.15 |