[하루한줄] CVE-2021-40346: HAProxy에서 발견된 Integer Overflow를 통한 HTTP Smuggling

URL

Critical Vulnerability in HAProxy (CVE-2021-40346): Integer Overflow Enables HTTP Smuggling

Target

  • HAProxy 2.0.25, 2.2.17, 2.3.14, 2.4.4 이전

Explain

HAProxy는 기존 하드웨어 스위치에서 제공하는 기능을 소프트웨어로 구현한 오픈소스 로드 밸런서입니다. 해당 소프트웨어에서 HTTP Request Smuggling 공격을 가능하게 하는 unsigned integer overflow 취약점의 세부 정보가 공개되었습니다.

취약점은 HTX block을 추가하는 htx_add_header 함수에서 발생합니다.

static inline struct htx_blk *htx_add_header(struct htx *htx, const struct ist name,
					     const struct ist value)
{
	struct htx_blk *blk;

	/* FIXME: check name.len (< 256B) and value.len (< 1MB) */
	blk = htx_add_blk(htx, HTX_BLK_HDR, name.len + value.len);
	if (!blk)
		return NULL;

	blk->info += (value.len << 8) + name.len;  //vuln!
	ist2bin_lc(htx_get_blk_ptr(htx, blk), name);
	memcpy(htx_get_blk_ptr(htx, blk)  + name.len, value.ptr, value.len);
	return blk;
}

htx_add_header 함수는 헤더 이름 name과 헤더 값 value를 매개변수로 받아 다음 작업을 수행합니다.

  1. 헤더 타입(b0010)의 새 HTX block을 추가합니다.
  2. 생성된 block의 info 필드에 name의 길이와 value의 길이를 저장합니다.
    1. 이때 value의 길이를 8 bit 만큼 left shift해 name 길이와 더해 저장합니다.
  3. namelowercase로 HTX block으로 복사되고, 바로 뒤에 value가 복사됩니다.

예를 들어 헤더 이름과 값이 MyName:MyValue인 경우 info 필드에는 다음 값이 저장됩니다.

// Type : b0010
// MyName length : 0x6
// MyValue Length : 0x7 
block->info = (0x2 << 28) + (0x7 << 8) + 0x06 = 0x20000706

이 과정에서 헤더 이름 name의 길이를 검증하지 않아 255 bytes보다 긴 이름의 헤더를 전달해 이후 파싱 과정에서 다른 헤더 이름으로 보이게 할 수 있어 HTTP Reuest Smuggling 공격이 가능합니다.