The Alert attack

During the first, unprotected handshake, the peers authenticate the contents of the exchanged Handshake protocol messages by verifying the Finished message. Similarly, but implicitly, the peers authenticate the contents of Application data, by never accepting any Application data during the first handshake.

What is not authenticated during the first handshake, and exploited by our attack, is the content of the Alert protocol.

Alert messages are two bytes long, hence they can be fragmented. Our attack proceeds as depicted.

Alert attack depicted

As a client-server connection begins, the attacker injects a one-byte alert fragment [a0] during the first handshake; according to the standard, this byte is silently buffered; any time later, as the first genuine 2-byte alert [c0;c1] is sent and authenticated on the secure connection, the alert [a0;c0] is received and processed instead. This clearly breaks alerts authentication. Experimentally, we confirmed that at least OpenSSL is subject to this simple attack, transforming for instance a fatal alert into an ignored warning, while other implementations reject fragmented alerts.

The alert attack was discovered by our team on February 8, 2012.

Generalization of the attack

More generally, the attack works because, at the end of the first handshake, only the Handshake and Application data protocols are authenticated, while other protocols are not.

In particular, if a further protocol gets added to the TLS standard, it is necessary to ensure that there is some (at least implicit) agreement on it at the end of the first handshake.

The Heartbeat protocol happens to be fine with this respect, because messages of this protocol cannot be sent during handshakes (and anyway these messages don't alter the protocol session state).


Rejecting fragmented alerts is a quick (and partial) fix, albeit against the spirit of the standard.

In miTLS, all protocol buffers are reset on an epoch change (that is when sending or receiving the CCS message), thus ensuring we never mix data from different epochs. In effect, the definition of the global state in Dispatch ensures that all protocols are "aligned at" (more formally, indexed by) the same epoch. So, it is a typing error to carry on one buffer from a previous epoch to the successive one, because their indexes differ.