Skip to content

SIP DoS: panic slicing message body on non-char-boundary Content-Length #108

Description

@ryanmurf

Summary

parse_message() extracts the body with a byte-index string slice using the
attacker-controlled Content-Length value. If Content-Length lands in the
middle of a multi-byte UTF-8 sequence, body[..cl] panics, aborting the task.

Location

crates/asterisk-sip/src/parser/mod.rs:793

let body = if let Some(cl) = content_length {
    if cl > MAX_CONTENT_LENGTH { return Err(...); }
    if cl > 0 && body.len() >= cl {
        body[..cl].to_string()   // <-- panics if cl is not a char boundary
    } else {
        body.to_string()
    }
} ...

SipMessage::parse first validates the whole datagram as UTF-8, so body is a
valid &str; slicing it on a non-char-boundary byte index is an immediate panic.

Trigger (malformed input)

A single unauthenticated SIP datagram:

INVITE sip:x@h SIP/2.0\r\n
Via: SIP/2.0/UDP h\r\n
Content-Length: 1\r\n
\r\n
é

é is 0xC3 0xA9 (2 bytes). cl = 1, body.len() = 2, so the guard
cl > 0 && body.len() >= cl passes and body[..1] panics:

end byte index 1 is not a char boundary; it is inside 'é' (bytes 0..2 of string)

(Reproduced against the exact expression on master.)

Impact — remote DoS (HIGH)

SipMessage::parse runs in UdpTransport::recv() (transport/mod.rs:144),
which is awaited inline in the single main SIP event loop
(stack.rs:713). The crate builds with the default panic = "unwind", so the
panic unwinds and kills the event-loop task — the entire SIP stack stops
processing signaling
from one malformed UDP packet, no auth required. Same
reachability over TCP/TLS/WebSocket transports.

Suggested fix

Slice on a char boundary, e.g. body.get(..cl) and fall back to the full
(already length-bounded) body when cl is not a boundary, or floor cl to the
nearest char boundary. Add a regression test feeding a multi-byte body with a
mid-character Content-Length and asserting no panic.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions