OpenSSL Heartbleed
TLS는 확장 프로토콜로 Heartbeat를 사용한다. ( RFC 6520 ) Heartbeat는 Client와 Server가 connection이 제대로 유지되고 있는지 확인하기 위해 사용한다.
Client는 Heartbeat를 이용하여 임의의 값을 그 길이와 함께 Server에 전송, Server는 받은 임의의 값을 Client에게 돌려보내는 과정으로 이루어진다.
임의의 값과 그 값의 길이 정보가 일치하지 않는다면 응답하지 않는 것이 정상이나, Heartbleed 취약점은 Server가 이것이 일치하는지 검증하지 않고 응답하면서 발생하는 취약점이다. Client가 “Hi!”, 30Byte라고 보내면 Server는 “Hi!:?aw^er?435ˇs……..awe23.4.rw234”, 30Byte와 같이 추가적인 data가 송신되어 system memory 상의 랜덤한 정보가 유출된다
1
2
3
4
5
6
struct {
ContentType type;
ProtocolVersion version;
uint16 length;
opaque fragment[TLSPlaintext.length];
} TLSPlaintext;
The struct HeartbeatMessage is placed inside the above fragment[]
.
1
2
3
4
5
6
struct {
HeartbeatMessageType type;
uint16 payload\_length;
opaque payload[HeartbeatMessage.payload\_length];
opaque padding[padding\_length];
} HeartbeatMessage;
type
: heartbeat_request or heartbeat_response.payload_length
: The length of the payload.payload
: The payload consists of arbitrary content.padding
: The padding is random content that MUST be ignored by the receiver. The length of a HeartbeatMessage is TLSPlaintext.length for TLS and DTLSPlaintext.length for DTLS. Furthermore, the length of the type field is 1 byte, and the length of the payload_length is 2.
Therefore, the padding_length is TLSPlaintext.length - payload\_length - 3
for TLS and c DTLSPlaintext.length - payload_length - 3
for DTLS. The padding_length MUST be at least 16.
이런식이다. TLSPlaintext.length 값은 3 이고, 실제로 Type 1byte, Playload length에서 2byte로 총 3byte가 Hearbeat Message의 size인데, Payload length가 16384 ( 2^14 ) 인 것을 확인할 수 있다.