LoginSignup
158
156

More than 5 years have passed since last update.

Heartbleedバグのコードを解説

Last updated at Posted at 2014-04-10

今回バグってたのはheartbeat extension という機能の実装。

RFCはこちら
https://tools.ietf.org/html/rfc6520

Heartbleedバグに対する修正コミット
http://git.openssl.org/gitweb/?p=openssl.git;a=commit;h=96db9023b881d7cd9f379b0c154650d6c108e9a3

バグ解説

rfc6520

4.  Heartbeat Request and Response Messages

   The Heartbeat protocol messages consist of their type and an
   arbitrary payload and padding.

   struct {
      HeartbeatMessageType type;
      uint16 payload_length;
      opaque payload[HeartbeatMessage.payload_length];
      opaque padding[padding_length];
   } HeartbeatMessage;

Request,Response共にこのHeartbeatMessageを送る。

rfc6520
   When a HeartbeatRequest message is received and sending a
   HeartbeatResponse is not prohibited as described elsewhere in this
   document, the receiver MUST send a corresponding HeartbeatResponse
   message carrying an exact copy of the payload of the received
   HeartbeatRequest.

とあるので、HeartbeatResponseを返す側は送られてきたHeartbeatRequestのペイロードをコピーして返す必要がある。

今回問題となったコードはこのペイロードコピー部分。

t1_lib.c
2591         /* Read type and payload length first */
2592         hbtype = *p++;
2593         n2s(p, payload);
2594         pl = p;
(中略)
2616                 memcpy(bp, pl, payload);

HeartbeatRequestからペイロード長(コードではpayload)を取得して、HeartbeatResponseにペイロードをコピーするためにmemcpyしているが、ペイロード長について境界チェックを行っていないため、HeartbeatRequestに記載されたペイロード長が実際のペイロード長よりも長い場合 隣接するメモリの内容までmemcpy してHeartbeatResponseとして送り返してしまう。

そのため攻撃者は意図的に長いペイロード長を指定することで、1回のHeartbeatにつきメモリの内容を最大約64KB覗き見ることが可能。

修正

rfc6520
   If the payload_length of a received HeartbeatMessage is too large,
   the received HeartbeatMessage MUST be discarded silently.

ペイロード長が長すぎる場合は破棄とあり、そのように修正されている。

t1_lib.c
2596         /* Read type and payload length first */
2597         if (1 + 2 + 16 > s->s3->rrec.length)
2598                 return 0; /* silently discard */
2599         hbtype = *p++;
2600         n2s(p, payload);
2601         if (1 + 2 + payload + 16 > s->s3->rrec.length)
2602                 return 0; /* silently discard per RFC 6520 sec. 4 */
2603         pl = p;
158
156
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
158
156