Bug 1211293 (CVE-2015-3310)

Summary: CVE-2015-3310 ppp: buffer overflow in radius plug-in's rc_mksid()
Product: [Other] Security Response Reporter: Martin Prpič <mprpic>
Component: vulnerabilityAssignee: Red Hat Product Security <security-response-team>
Status: CLOSED WONTFIX QA Contact:
Severity: medium Docs Contact:
Priority: medium    
Version: unspecifiedCC: anemec, charlieb-fedora-bugzilla, chilek, jrusnack, jsynacek, msekleta, sisharma, thozza, ysoni
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2015-10-09 20:27:48 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On: 1211294    
Bug Blocks: 1211295    

Description Martin Prpič 2015-04-13 14:07:00 UTC
A buffer overflow flaw was found in the way PPP's RADIUS plug-in processed a "start" accounting message if the PID of the pppd process is greater than 65535. A remote attacker could use this flaw to crash pppd.

CVE request with additional impact details:

http://seclists.org/oss-sec/2015/q2/119

Original report (including a proposed patch):

https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=782450

Comment 1 Martin Prpič 2015-04-13 14:07:44 UTC
Created ppp tracking bugs for this issue:

Affects: fedora-all [bug 1211294]

Comment 2 Siddharth Sharma 2015-10-09 20:25:53 UTC
Analysis

ppp package contains the ppp ( Point-to-Point Protocol) daemon, which provides method of tranmitting datagrams over serial point-to-point links. RADIUS plugin enabled pppd to do PAP,CHAP, MS-CHAP , MS-CHAPv2 etc authentication against RADIUS server. rc_mksid() function is used to generate pseudo-unique string. rc_mksid() function is implemented in pppd/plugins/radius/util.c, following is the problematic function

/* Purpose : generate a quite unique string */

char * rc_mksid (void) {

        static char buf[15];
        static unsigned short int cnt = 0;

In the sprintf function , getpid() is used to get the pid of the pppd, which the rc_mksid function converts to hex to generate pseudo unique string. It expects hex representation to 4 chars long only so if pid is 65535 then hex representation would be 0xFFFF , where as even if pid value increases by 1 , that is 65536 hex representation would become 0x10000, which would lead to buffer overflow. 
 
        sprintf (buf, "%08lX%04X%02hX",
                 (unsigned long int) time (NULL),
                 (unsigned int) getpid(),
                  cnt & 0xFF);
        cnt++;

}

*** buffer overflow detected ***: ./pppd_demo terminated
======= Backtrace: =========
/lib64/libc.so.6[0x3977c77e15]
/lib64/libc.so.6(__fortify_fail+0x37)[0x3977d14747]
/lib64/libc.so.6[0x3977d128d0]
/lib64/libc.so.6[0x3977d11e39]
/lib64/libc.so.6(_IO_default_xsputn+0x80)[0x3977c7bc10]
/lib64/libc.so.6(_IO_vfprintf+0x1a9c)[0x3977c4d3ac]
/lib64/libc.so.6(__vsprintf_chk+0x8c)[0x3977d11ecc]
/lib64/libc.so.6(__sprintf_chk+0x7d)[0x3977d11e1d]
./pppd_demo[0x4006db]
/lib64/libc.so.6(__libc_start_main+0xf0)[0x3977c20580]
./pppd_demo[0x4005b9]
======= Memory map: ========
00400000-00401000 r-xp 00000000 fd:05 7733470                            <REDACTED>/SEC/secure-code/pppd_demo
00600000-00601000 r--p 00000000 fd:05 7733470                            <REDACTED>/SEC/secure-code/pppd_demo
00601000-00602000 rw-p 00001000 fd:05 7733470                            <REDACTED>/SEC/secure-code/pppd_demo
00dd3000-00df4000 rw-p 00000000 00:00 0                                  [heap]
336b000000-336b016000 r-xp 00000000 fd:02 2099497                        /usr/lib64/libgcc_s-5.1.1-20150618.so.1
336b016000-336b215000 ---p 00016000 fd:02 2099497                        /usr/lib64/libgcc_s-5.1.1-20150618.so.1
336b215000-336b216000 r--p 00015000 fd:02 2099497                        /usr/lib64/libgcc_s-5.1.1-20150618.so.1
336b216000-336b217000 rw-p 00016000 fd:02 2099497                        /usr/lib64/libgcc_s-5.1.1-20150618.so.1
3977800000-3977821000 r-xp 00000000 fd:02 2096962                        /usr/lib64/ld-2.22.so
3977a20000-3977a21000 r--p 00020000 fd:02 2096962                        /usr/lib64/ld-2.22.so
3977a21000-3977a22000 rw-p 00021000 fd:02 2096962                        /usr/lib64/ld-2.22.so
3977a22000-3977a23000 rw-p 00000000 00:00 0 
3977c00000-3977db7000 r-xp 00000000 fd:02 2096964                        /usr/lib64/libc-2.22.so
3977db7000-3977fb7000 ---p 001b7000 fd:02 2096964                        /usr/lib64/libc-2.22.so
3977fb7000-3977fbb000 r--p 001b7000 fd:02 2096964                        /usr/lib64/libc-2.22.so
3977fbb000-3977fbd000 rw-p 001bb000 fd:02 2096964                        /usr/lib64/libc-2.22.so
3977fbd000-3977fc1000 rw-p 00000000 00:00 0 
7ff9df9bb000-7ff9df9be000 rw-p 00000000 00:00 0 
7ff9df9df000-7ff9df9e1000 rw-p 00000000 00:00 0 
7fff32cf9000-7fff32d1b000 rw-p 00000000 00:00 0                          [stack]
7fff32dcc000-7fff32dce000 r--p 00000000 00:00 0                          [vvar]
7fff32dce000-7fff32dd0000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Aborted (core dumped)

As the crash happens in sprintf, If compiled with -D_FORTIFY_SOURCE , __sprintf_chk() would be used which would detect the crash, otherwise it would go undetected. This attack vector can be used by attacker to cause remote DOS to devices using this, though there is not evidence of this being exploited in wild.

Comment 4 Charlie Brady 2017-06-21 20:08:45 UTC
"This attack vector can be used by attacker to cause remote DOS..." - so why not fix this bug?

The Debian patch is very straightforward:

--- ppp-2.4.6.orig/pppd/plugins/radius/util.c
+++ ppp-2.4.6/pppd/plugins/radius/util.c
@@ -77,7 +77,7 @@ rc_mksid (void)
   static unsigned short int cnt = 0;
   sprintf (buf, "%08lX%04X%02hX",
 	   (unsigned long int) time (NULL),
-	   (unsigned int) getpid (),
+	   (unsigned int) getpid () % 65535,
 	   cnt & 0xFF);
   cnt++;
   return buf;

BTW, IIUC there doesn't need to be an attacker. This bug will simply cause pppd to sometimes crash. Again, why not fix it?

Comment 5 Charlie Brady 2017-06-21 20:09:59 UTC
BTW, IIUC, this bug affects RHEL7.

Comment 6 Yogita 2017-06-22 06:59:48 UTC
Hello,

Can we have justification for why bug is not fixed as mentioned by Charlie. 
Any workaround suggestion are also much appreciated.

Comment 7 Tomas Hoger 2017-06-22 21:48:25 UTC
(In reply to Charlie Brady from comment #4)
> BTW, IIUC there doesn't need to be an attacker. This bug will simply cause
> pppd to sometimes crash.

That's fairly accurate statement - it's not much of a security issue, but more of a bug.  If ppp runs with pid higher than 65535, it crashes when reaching this code, regardless of whether it's communicating with malicious or non-malicious user.  On many systems, this problem can not be triggered at all, as pid_max is below 65536.  The following solution article explains how pid_max is determined (note that it discusses Red Hat Enterprise Linux 5 and 6 currently):

https://access.redhat.com/solutions/28908

This problem can only be triggered on systems with more than 64 CPUs by default.  Reducing pid_max should be a workaround for those systems if they do not need to run more than 65535 process at the same time.

Given all the above, this was not classified to have sufficient security impact to trigger a security update.  If you're hitting it as a regular bug in your usage, please open a support case and work with out support to open a bug report against the product version you're interested in and have the bug properly prioritized.

Comment 8 Tomasz Chilinski 2020-09-23 13:55:02 UTC
Yeap - this is not security bug probably, but still it's a BUG.
I've also met this problem w CentOS 8.2 using:
ppp-2.4.7-26
from within rp-pppoe server and freeradius.
By default kernel starts with max_pid > 65535 and rp-pppoe
acts properly for some hour until assigned pid for new PPPoE session
is bigger than 65535 - then no new PPPoE session can be established.
Please let me know if I should submit separate bug report, but
definitely closing this report, because error type doesn't match someone's definition
is not sane.