\n\n\n\n\n\n\n\n\n\n\n
flawopen.com/시뮬레이터/Heartbleed 버퍼 오버리드
브라우저에서 직접 실행되는 메모리 모델 시뮬레이터: 검증되지 않은 TLS Heartbeat 길이 필드가 서버 힙 메모리 유출(Buffer Overread)을 초래하는 과정을 시각화합니다.
훈련된 앵무새에게 4글자 단어 'BIRD'를 건네며 '내가 말한 단어를 반복하되, 총 64,000글자로 길게 대답해줘'라고 요구하는 상황을 상상해 보세요. 앵무새는 'BIRD'라고 외친 뒤, 자신의 최근 기억 속에 남아 있던 다음 63,996자의 내용—다른 손님들의 비밀번호, 개인 암호키, 계좌번호 등—을 줄줄 읊기 시작합니다. 하트블리드(Heartbleed) 취약점에서도 OpenSSL은 실제 수신된 패킷 길이를 확인하지 않고 클라이언트가 주장한 길이를 그대로 신뢰하여, 서버의 민감한 힙 메모리를 공격자에게 그대로 복사해 전송했습니다.
공격자는 단 1바이트('A')의 페이로드만 전송하면서 길이 필드는 65,535바이트(0xFFFF)로 조작.
OpenSSL은 n2s(p, payload)로 길이를 읽어들이지만, 1 + 2 + payload + 16 <= rrec.length 여부를 검증하지 않음.
서버는 공격자의 주장을 신뢰하여 힙에 64KB 크기의 응답 버퍼를 할당.
memcpy()가 1바이트 패킷을 넘어 인접 힙 메모리를 복사하여 RSA 개인키와 세션 쿠키를 공격자에게 전송.
/* 패킷 경계 검증 없이 16비트 길이를 직접 읽음 */
n2s(p, payload);
pl = p;
/* 클라이언트가 주장한 크기를 바탕으로 응답 버퍼 할당 */
buffer = OPENSSL_malloc(1 + 2 + payload + padding);
bp = buffer;
/* 치명적 결함: 서버 힙 인접 메모리를 최대 64KB까지 복사! */
memcpy(bp, pl, payload);
r = ssl3_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, 3 + payload + padding);
/* 패킷에서 16비트 길이 추출 */
n2s(p, payload);
pl = p;
/* 패치: 선언된 페이로드가 실제 수신된 레코드 크기를 초과하지 않는지 검증 */
if (1 + 2 + payload + 16 > s->s3->rrec.length)
return 0; /* 비정상적인 하트비트 패킷을 조용히 폐기 */
buffer = OPENSSL_malloc(1 + 2 + payload + padding);
bp = buffer;
memcpy(bp, pl, payload);