HTTP2 Analysis

jun4n·2023년 2월 19일
0

Web Spec

목록 보기
3/4

Background


  • 당연한 이야기지만 HTTP/1.x에서 보완하고 싶은 점이 있기 때문에 HTTP/2가 나오게 됨.

HTTP/1.1에서의 문제점

HOL (head-of-line)차단


  • HTTP/1.1에서는 파이프라이닝을 통해서 TCP연결을 계속해줘야하는 문제점을 해결했었음
  • 위 방식의 문제점은 병목 현상이 불가피하다는 점임.
    • 예를 들어서 웹페이지 하나를 로드하는데, 많은 패킷들을 받아오는데, 먼저 요청을 보낸 리소스에 대한 요청에서 시간이 소요되면 뒤에오는 요청들도 자연스럽게 지연되는 상황이 벌어짐.
    • 이러한 현상을 HOL(head-of-line)차단 이라고 한다.
      • 위 문제점은 TCP의 고질적인 문제인데, 패킷 로스가 생기면 해당 패킷에 대해서 ACK이 오지 않았기 때문에 패킷을 재전송하게 되고 이로 인해서 다음번에 전송하는 패킷들이 지연됨
      • 이 문제점은 요청의 순서와 응답의 순서는 같아야 한다고 HTTP1.1에 명세되어 있어서 그렇다고 함.
    • 별도의 TCP 연결을 추가해서 위 문제를 해결할 수 있지만 리소스의 소모가 너무 크다는 문제

RTT 증가


  • 하나의 Connection에 하나의 요청을 처리하기 때문에 요청을 새로 할경우 connection을 새로 만들기 때문에 자연스럽게 RTT가 증가한다.
  • Connect: keep-alive이지만 여기서 하는말은 (요청⇒ 응답, 요청 ⇒ 응답) 이렇게 하나의 Connection에 하나의 요청을 처리한다는 말임.

무거운 헤더 구조


  • HTTP헤더에 많은 정보가 들어간다는건 DevTools를 한번이라도 열어봤다면 안다.
  • 이러한 정보들은 중복되는 정보들이 많고, 동일한 정보를 지속적으로 전달해야 하기 때문에 매 패킷마다 차지하는 크기가 존재해서 무거워지게 된다.
    • 이런식으로는 전달하는 정보보다 헤더가 더 큰 경우도 다반사

HTTP2 DUDUDUNGA

HTTP2


  • HTTP2의 포커스는 퍼포먼스에 있는데, end-user의 latency, network와 server의 리소스 사용에 특히 초점을 둔다.
  • HTTP2는 우리가 알고있는 웬만한 사이트에서는 이미 도입되어 있는 상태이고, 전체적으로 봐도 30%정도는 도입되어 있다고 한다.
  • HTTP2에서는 HTTP/1.1에서의 주 문제점이었던 (요청⇒응답, 요청⇒응답)을 multiplexing 전송을 지원함으로써 성능을 향상시킨다.

HTTP2의 Frame, Stream


  • HTTP/1.1에서 요청, 응답은 Message 단위로 구성하는데, Message는 status line, head, body등으로 구성되어 있음.
  • Frame: HTTP/2 통신에서 제일 작은 정보의 단위
    • header or Data
  • Message: HTTP/1.1에서와 마찬가지로 요청, 혹은 응답의 단위
    • 다수의 Frame으로 이루어진다.
  • Stream: 클라이언트와 서버 사이에 맺어진 연결을 통해 양방향으로 주고받는 하나 이상의 복수개의 Message
    - 하나의 스트림에 여러개의 데이터 프레임이 들어가 병렬적으로 요청을 할 수 도 있고, 하나의 스트림에 하나의 요청만 존재할 수 도 있음.

HTTP2의 개선방식

Multiplexed Streams & binary frames


  • 한개의 Connection으로 동시에 여러개의 메시지를 주고 받을 수 있다.
    • HTTP/1.1에서와 다르게 (요청⇒응답, 요청⇒응답)순서로 와야 하는게 아닌 여러개의 요청이 응답을 기다리지 않고 보낼 수 있음.

  • 위와 같이 병렬적으로 처리될 수 있는 이유는 HTTP/2에서 지원하는 최소 단위인 Frame으로 쪼개서 보내기 때문에 가능하다.
    • 윗 그림의 윗그림을 확인해보면 하나의 Connection에 여러개의 Stream이 들어가 있고, 그안에 Message, 그안에 Frame이 들어가 있는 구조를 볼 수 있다.
    • 스트림을 다중화 함으로써 버퍼오버플로우도 방지할 수 있다.
      • TCP연결에서 클라이언트와 서버 모두 아직 처리되지 않은 들어오는 요청을 보유하는 데 사용할 수 있는 특정 양의 버퍼 공간을 가지고 있는데, 이 버퍼의 양이 처리 불가능한 수준의 데이터가 온다면 문제가 됨.
      • 이러한 상황을 막기 위해서 흐름 제어 메커니즘이 필요한데, HTTP/2에서는 스트림을 다중화 해서 스트림 수준에서 사용가능한 버퍼의 크기를 클라이언트와 서버가 설정한다.
        • 이러한 흐름 제어는 WINDOW_UPDATE프레임을 통한 초기 연결 후에 수정, 유지관리한다.

Header Compression


  • 중복된 헤더정보를 압축하기 우해서 Header Table, Huffman Encoding기법을 사용해서 처리
    • HPACK압축 방식 (RFC 7531)
  • 중복값이 존재하는 경우 Static/Dynamic Header Table개념을 사용해서 중복된 Header를 검출하고, 중복된 Header는 index값만 전송하고 중복되지 않은 Header정보의 값은 Huffman Encoding기법으로 인코딩 처리 하여 전송

Header reuse vulnerability

  • 위에 존재하는 그림처럼 한번 사용한 헤더는 Dynamic Table에 존재하는 인덱스값만 보내서 헤더의 크기를 줄임.
  • 이방법을 이용해서 index를 브루트포싱해서 header reuse attack이 수행될 수 있다.

Stream Prioritization


  • HTTP/2에서는 소스 간의 의존관계에 따라서 우선순위를 설정해줘서 리소스 로드 문제를 해결

Server Push


  • 클라이언트가 요청하지 않은 리소스를 서버가 푸쉬해줄 수 있어서 클라이언트가 어차피 요청해야 하는 리소스를 요청하지 않아도 되도록 함.

HTTP2 Format


  • RFC 7540에 정의 되어이 있는 HTTP2의 Format은 위와 같음.

  • 이런식으로 Frame payload에 헤더 정보들이 binary로 들어가 있음을 볼 수 있다.
  • 아래 나온 Header들은 wireshark에서 보기 좋게 보여준거고, 실제 바이너리로 전달되는 값은 Header Block Fragment에 나와있는 값으로 전달됨.

pseudo headers


POST /login HTTP/1.1\r\n
Host: psres.net\r\n
User-Agent: burp\r\n
Content-Length: 9\r\n
\r\n
x=123&y=4
	:method	POST
		:path	/login
:authority	psres.net
	:scheme	https
user-agent	burp
x=123&y=4
  • 위 두개의 요청은 각각 HTTP/1.1, HTTP/2로 동일한 요청을 보냈을때의 포멧임.

  • 위에서 내가 날렸던 HTTP/2패킷도 decompressed된 데이터를 확인해보면 유사함을 알 수 있다.
  • HTTP2에서 보내는 이런식의 Header를 pseudo-Headers라고 부르는데, 5가지 종류가 잇고, 딱봐도 잘 모르겠는건 :authority로 HTTP/1.1의 host헤더라고 보면 됨.
    • :status헤더도 존재하는데, 이건 reponse에서 볼 수 있는 헤더이다.
  • HTTP/2에서는 위에서 본 format처럼 length에대한 명시가 되어 있기 때문에 desync공격이 힘듦
    • 하지만 HTTP2 downgrade를 통해서 desync attack이 가능하다.

HTTP/2 Desync attack

Request Smuggling via HTTP/2 Downgrade

  • 위 그림을 보면 알 수 있다 시피 기존의 http smuggling과 비슷하게 front-end서버에서 HTTP/2로 받은 데이터를 back-end서버에 HTTP/1.1로 받을 때 취약점이 발생한다.
  • front-end에서 back-end에 전송할 때 Content-Length나 Transfer-Encoding헤더를 사용해야 할 수 밖에 없고 여기서 취약점이 발생
    • H2.TE, H2.CL

0개의 댓글