Skip to content

Infinite onion message parse #4139

@morehouse

Description

@morehouse

While fuzzing onion_message_target, @dergoegge found the following (base64-encoded) input which triggers an infinite loop in the onion parsing logic:

AuT//////////52dIwCdnZ2dAgr///////j///8ACAAAAGL/AgBWAf0AgP3/AAD/Av//AAAAYv8CAgCGAQAA/39zAJ0C//8AAAAAAAEABPv//wP///8AAf8A////AAAAAAADAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=

From my investigation, the root cause is something like this:

  1. The hop_data for the onion packet is wrapped in a Cursor and sent off for TLV parsing here:

    let mut chacha_stream = ChaChaReader { chacha: &mut chacha, read: Cursor::new(&hop_data[..]) };
    match R::read(&mut chacha_stream, read_args) {

  2. The type and length for the first TLV are parsed. In this case, the type is encrypted_recipient_data and the specified length is larger than the remaining data in hop_data. Nevertheless, the remaining hop_data is wrapped in a FixedLengthReader of the larger length and passed off for decryption here:

    let length: ser::BigSize = $crate::util::ser::Readable::read(stream_ref)?;
    let mut s = ser::FixedLengthReader::new(stream_ref, length.0);
    match typ.0 {
    $(_t if $crate::_decode_tlv_stream_match_check!(_t, $type, $fieldty) => {
    $crate::_decode_tlv!($stream, s, $field, $fieldty);

  3. The FixedLengthReader is read and decrypted, and any extra bytes are handled in this loop:

    while chacha_stream.read.bytes_remain() {
    let mut buf = [0; 256];
    chacha_stream.read(&mut buf)?;
    }
    In that loop, once the underlying hop_data is exhausted, every read from the FixedLengthReader becomes a no-op since Cursor::read returns 0. At the same time, FixedLengthReader::bytes_remaining always returns true because there's still bytes remaining from its point of view. The loop continues forever.


It looks like this bug was introduced here: 8ee02eb

Prior to that commit, chacha_stream.read.eat_remaining() would return an error once hop_data was exhausted.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions