d1_pkt.c:dtls1_get_record() processes DTLS records which it gets from
the wire. At the same time, this function performs replay protection: It
memorizes the (explicit) sequence numbers of the records and drops
records that have already been processed.
The sequence numbers of the processed records are saved in a sliding
bitmap window. The corresponding bit in the window is set to 1, if a
specific sequence number is processed. The key point is that the MAC of
the record is usually verified *before* the bitmap of sequence numbers
is updated. This requires the receiving end to be in possession of the
symmetric key used for integrity control.
With every renegotiation, the keys are renewed and a new epoch begins.
Due to reordering on the network, it may happen that a record from a
future epoch arrives during renegotiation. Because the keying material
is not yet available, the integrity of these records can not be verified.
The aspect I'm complaining about is that OpenSSL updates the record
bitmap *without* prior verification of the integrity of the record *iff*
the record is from a future epoch.
Here's the code:
/* If this record is from the next epoch (either HM or ALERT),
* buffer it since it cannot be processed at this time. Records
* from the next epoch are marked as received even though they
* are not processed, so as to prevent any potential resource
* DoS attack */
if (is_next_epoch)
{
dtls1_record_bitmap_update(s, bitmap);
dtls1_buffer_record(s, &(s->d1->unprocessed_rcds), rr->seq_num);
rr->length = 0;
s->packet_length = 0;
goto again;
}
In my opinion, there's no potential for resource DoS attacks because
dtls1_buffer_record() limits the number of buffered records to 100.
However, as the code stands today, there is a potential for a DoS
attack. An attacker might guess the source and destination UDP port as
well as the number of the next epoch. They then send a faked DTLS record
with a high sequence number, say n. As a result, OpenSSL moves forward
the bitmap window and will drop any future record carrying a sequence
number that is smaller than (n-64) i.e. which lies outside the window.
I suggest to improve on that situation by doing the following:
- Do *not* update the record bitmap if the record belongs to the next
epoch. As a result, two records carrying the same sequence number may be
buffered at the same time. However, one of these records might be
invalid or faked.
- Buffer records from the next epoch only if a re-handshake is currently
in progress.
Does that make sense?
Please let me know your opinions.
-Daniel
______________________________________________________________________
OpenSSL Project http://www.openssl.org
Development Mailing List [email protected]
Automated List Manager [email protected]