[CVE] CVE 분석 · 작성: 2026-07-19 19:39:08 · 수정: 2026-07-21 23:17:42 · 조회 21
패치(t1_lib.c, d1_both.c의 *_process_heartbeat())는 딱 한 지점 — "클라이언트가 주장하는 payload 길이"와 "실제 수신한 레코드 전체 길이"를 비교하는 검증을 추가하는 것으로 요약된다.
tls1_process_heartbeat() — 길이 검증 부재Before (1.0.1f 이하)
hbtype = *p++;
n2s(p, payload); // 클라이언트가 보낸 길이 필드를 그대로 읽음
pl = p;
// ↓ payload가 실제 수신 데이터 크기보다 커도 여기서 걸러지지 않음
buffer = OPENSSL_malloc(1 + 2 + payload + padding);
bp = buffer;
*bp++ = TLS1_HB_RESPONSE;
s2n(payload, bp);
memcpy(bp, pl, payload); // pl 뒤의 인접 힙 메모리까지 그대로 복사됨
After (1.0.1g)
hbtype = *p++;
n2s(p, payload);
// 추가된 검증: 클라이언트가 주장한 payload가 실제 수신 레코드 길이(s->s3->rrec.length)를
// 초과하면 즉시 무시하고 응답하지 않는다
if (1 + 2 + 16 > s->s3->rrec.length) return 0;
hbtype = *p++;
n2s(p, payload);
if (payload + padding > s->s3->rrec.length) return 0; // 핵심 한 줄
pl = p;
buffer = OPENSSL_malloc(1 + 2 + payload + padding);
...
memcpy(bp, pl, payload);
payload + padding > s->s3->rrec.length 검사 한 줄이, "클라이언트가 주장하는 길이"가 "실제로 받은 바이트 수"를 넘어설 수 없도록 강제한다. 이 검증이 없던 시절에는 memcpy가 pl 포인터 뒤에 물리적으로 이어진 힙 메모리를 최대 64KB까지 그대로 읽어 응답에 담아 보냈다.
type=1(request), 실제 payload는 1바이트만 담고 길이 필드에는 0xFFFF를 기록해 전송memcpy(bp, pl, 65535) 실행, 힙에서 pl 뒤에 이어지는 최대 64KB가 응답에 그대로 담겨 반환