SSerguey Asael Shinder
Java coding notes: the JVM, and writing software that lasts

Serguey Asael Shinder: An input that costs more to read than to send is an attack, not a message

· by Serguey Asael Shinder / Serguey Shinder

This week two denial-of-service bugs in Eclair, a Lightning Network node, were disclosed on Delving Bitcoin after being fixed in version 0.14.0. They are in Scala rather than Java, but the lesson is the same on any JVM, or anywhere else.

In the first, the node parsed a peer's feature bits one bit at a time and allocated several heap objects per bit. One maximum-length message cost it about 300 MB of memory churn. In the second, the node still accepted a compressed message format the protocol had retired years earlier, and decompressed it with no limit: a 64 KB message became 64 MB and about 17 million objects. In both cases anyone who could open a connection could make the node do vastly more work than they did.

The researcher who found the second one did so by asking a single question of the codebase: where can a peer make us spend far more than it spent? I think that question belongs in every review of code that reads untrusted input, and it is worth writing down because it is not the question we usually ask. We ask whether the input is valid. A 64 KB message that decompresses correctly is perfectly valid.

Serguey Asael Shinder: An input that costs more to read than to send is an attack, not a message
An input that costs more to read than to send is an attack, not a message — Serguey Asael Shinder

What the check looks like in practice

None of this needs a security team. It needs the habit of asking, for every handler that touches bytes from outside, what the worst legal input costs, and whether the sender pays anything close to the same.