New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 390709 link

Starred by 1 user

Issue metadata

Status: Verified
Owner:
Email to this user bounced
Closed: Aug 2014
Cc:
EstimatedDays: ----
NextAction: ----
OS: Chrome
Pri: 1
Type: Bug-Security



Sign in to add a comment

Security: Local Priv Esc - pppd malformed config file could lead to code execution in suid binary

Reported by leecam@chromium.org, Jul 1 2014

Issue description

We ship pppd with ChromeOS (I also checked its on 14.04 Ubuntu). Its a suid binary in /usr/sbin and can be run by the chronos user. 

I have confirmed the bug in 2.4.5 (what we ship) and I looked at the source for 2.4.6 (latest) and looks to be there too. 

getword() in options.c parses a user supplied config file. It loops round char by char, using getc() and appends it to a buffer on the stack |word|

	if (len < MAXWORDLEN-1)
	    word[len] = c;
	++len; 

As len is signed it will write up to MAXWORDLEN then stop writing, but it will still keep reading. When len reaches 0x80000000 the check will pass once again and we will have an arb write 2gig below the stack. Other config options allow us to spray this area. I've not taken it all the way to code execution but it crashes predictably on 32bit Arm and x64. 

pppd can take a config file from anywhere with the 'file' option or from /etc/pppd/peers/ with the 'call' option. We could disable the 'file' option and then config files would be limited to our read-only partition. 

Desktop Linux will need an upstream patch. 
 
Owner: leecam@chromium.org
Status: Assigned
It doesn't look like the option file feature can be disabled via ./configure. We should just disable that cmdline option, if we're not using it. Ben, do we need to read configuration options via a filename?

Lee, I'm gonna assign this to you, once Ben confirms how we're using pppd it should be straightforward to add a patch to the ppp ebuild to disable as much as we can of the vulnerable code:
https://cs.corp.google.com/#chromeos_public/src/third_party/chromiumos-overlay/net-dialup/ppp/ppp-2.4.5-r3.ebuild&l=39
vpn-manager does generate a pppd config file and refer that in xl2tpd config file (via 'pppoptfile'). xl2tpd will tell pppd to use that config file.
K, I'll report this upstream and get an ETA for a fix. I'll also prep an internal patch incase we cant sync with upstream pppd for some reason. 
Upstream author (Paul Mackerras) has got back to us and offered a new version within a week. 

I'm still reviewing the code and there may be more bugs, will be done by end of week and hopefully we can get all the fixes we need in one release. 

Ben do you see any reason why we couldn't bring in the new version 2.4.5 -> 2.4.7 (current is 2.4.6)? Then we can avoid local patches. 

We should also de-setuid it and see if everything else works.
Re #4: We have local pppd patches, which I can help port them over to 2.4.7.

Comment 7 by leecam@chromium.org, Jul 13 2014

Re #5:
Yep, sorry should of updated the bug when we proposed that offline...

Other Linux distros do have this non-setuid (Android is also non-setuid) but they will have to run it as root. 

There is this check in main()

   /*
     * Check that we are running as root.
     */
    if (geteuid() != 0) {
	option_error("must be root to run %s, since it is not setuid-root",
		     argv[0]);
	exit(EXIT_NOT_ROOT);
    } 

So we'd need a patch to try it. From what Ben says on our usage we probably need root anyhow. 

Re #6: Sorry Ben I should of said 'additional local patches'. Paul Mackerras has sent me his proposed patch and I LGTM'ed it. I'll let you know as soon as the new release is out and I'll bring it into into the tree. 
Yeah we can carry a local patch to remove that check and run pppd with Minijail and capabilities. Once we update to the latest version we'll remove setuid.

Thanks!

Comment 9 by parisa@chromium.org, Jul 17 2014

Cc: parisa@chromium.org timwillis@chromium.org
Labels: Security_Severity-High Security_Impact-Stable
Labels: CVE-2014-3158
Labels: M-37
Just note on exploitability....

I did a quick PoC on a 32bit Arm Chromebook. I just took it to heap control to make the case for a quick patch.  

I used a mem leak in the 'bundle' command to spray the heap and here is the mail I exchanged with the author 
-----------------
Hi Paul, 

Many thanks for getting back and offering a fix some promptly! 

I had quick look at exploiting it on a 32bit Arm Chromebook 11. The memory layout looks a bit like this on start up: 

b6d5f000-b6d66000 r-xp 00000000 fe:00 15690      /lib/libnss_files-2.15.so
b6d66000-b6d6d000 ---p 00007000 fe:00 15690      /lib/libnss_files-2.15.so
b6d6d000-b6d6e000 r--p 00006000 fe:00 15690      /lib/libnss_files-2.15.so
b6d6e000-b6d6f000 rw-p 00007000 fe:00 15690      /lib/libnss_files-2.15.so
b6d6f000-b6e48000 r-xp 00000000 fe:00 15704      /lib/libc-2.15.so
b6e48000-b6e50000 ---p 000d9000 fe:00 15704      /lib/libc-2.15.so
b6e50000-b6e52000 r--p 000d9000 fe:00 15704      /lib/libc-2.15.so
b6e52000-b6e53000 rw-p 000db000 fe:00 15704      /lib/libc-2.15.so
b6e53000-b6e56000 rw-p 00000000 00:00 0 
b6e56000-b6e58000 r-xp 00000000 fe:00 15686      /lib/libdl-2.15.so
b6e58000-b6e5f000 ---p 00002000 fe:00 15686      /lib/libdl-2.15.so
b6e5f000-b6e60000 r--p 00001000 fe:00 15686      /lib/libdl-2.15.so
b6e60000-b6e61000 rw-p 00002000 fe:00 15686      /lib/libdl-2.15.so
b6e61000-b6e69000 r-xp 00000000 fe:00 15723      /lib/libpam.so.0.83.1
b6e69000-b6e70000 ---p 00008000 fe:00 15723      /lib/libpam.so.0.83.1
b6e70000-b6e71000 r--p 00007000 fe:00 15723      /lib/libpam.so.0.83.1
b6e71000-b6e72000 rw-p 00008000 fe:00 15723      /lib/libpam.so.0.83.1
b6e72000-b6e78000 r-xp 00000000 fe:00 15691      /lib/libcrypt-2.15.so
b6e78000-b6e7f000 ---p 00006000 fe:00 15691      /lib/libcrypt-2.15.so
b6e7f000-b6e80000 r--p 00005000 fe:00 15691      /lib/libcrypt-2.15.so
b6e80000-b6e81000 rw-p 00006000 fe:00 15691      /lib/libcrypt-2.15.so
b6e81000-b6ea8000 rw-p 00000000 00:00 0 
b6eb3000-b6ecb000 r-xp 00000000 fe:00 15710      /lib/ld-2.15.so
b6ece000-b6ed2000 rw-p 00000000 00:00 0 
b6ed2000-b6ed3000 r--p 00017000 fe:00 15710      /lib/ld-2.15.so
b6ed3000-b6ed4000 rw-p 00018000 fe:00 15710      /lib/ld-2.15.so
b6ed4000-b6f0a000 r-xp 00000000 fe:00 9190       /usr/sbin/pppd
b6f12000-b6f13000 r--p 00036000 fe:00 9190       /usr/sbin/pppd
b6f13000-b6f16000 rw-p 00037000 fe:00 9190       /usr/sbin/pppd
b6f16000-b6f61000 rw-p 00000000 00:00 0 
b8719000-b873a000 rw-p 00000000 00:00 0          [heap]
be9a9000-be9ca000 rw-p 00000000 00:00 0          [stack]
ffff0000-ffff1000 r-xp 00000000 00:00 0          [vectors]

You can see with the ASLR the binary and the libs end up high in memory. The stack and heap are also just above the binaries. So when I trigger this bug I'm going to get a write located at a stack address minus 0x80000000. This is going to be around 0x3e0000000 in this example and as thats not mapped we will fault (as you point out). 
So I created a filesystem fifo and used that as the config file argument to pppd, then I can programmatically send data to pppd without creating massive files. I use this to spray the heap by sending the command 'bundle AAAA...AAAA' where there are 1024 A's. After doing this (2300x1024) times the memory layout looks like this...

2c15f000-b6d5f000 rw-p 00000000 00:00 0 
b6d5f000-b6d66000 r-xp 00000000 fe:00 15690      /lib/libnss_files-2.15.so
b6d66000-b6d6d000 ---p 00007000 fe:00 15690      /lib/libnss_files-2.15.so
b6d6d000-b6d6e000 r--p 00006000 fe:00 15690      /lib/libnss_files-2.15.so
b6d6e000-b6d6f000 rw-p 00007000 fe:00 15690      /lib/libnss_files-2.15.so
b6d6f000-b6e48000 r-xp 00000000 fe:00 15704      /lib/libc-2.15.so
b6e48000-b6e50000 ---p 000d9000 fe:00 15704      /lib/libc-2.15.so
b6e50000-b6e52000 r--p 000d9000 fe:00 15704      /lib/libc-2.15.so
b6e52000-b6e53000 rw-p 000db000 fe:00 15704      /lib/libc-2.15.so
b6e53000-b6e56000 rw-p 00000000 00:00 0 
b6e56000-b6e58000 r-xp 00000000 fe:00 15686      /lib/libdl-2.15.so
b6e58000-b6e5f000 ---p 00002000 fe:00 15686      /lib/libdl-2.15.so
b6e5f000-b6e60000 r--p 00001000 fe:00 15686      /lib/libdl-2.15.so
b6e60000-b6e61000 rw-p 00002000 fe:00 15686      /lib/libdl-2.15.so
b6e61000-b6e69000 r-xp 00000000 fe:00 15723      /lib/libpam.so.0.83.1
b6e69000-b6e70000 ---p 00008000 fe:00 15723      /lib/libpam.so.0.83.1
b6e70000-b6e71000 r--p 00007000 fe:00 15723      /lib/libpam.so.0.83.1
b6e71000-b6e72000 rw-p 00008000 fe:00 15723      /lib/libpam.so.0.83.1
b6e72000-b6e78000 r-xp 00000000 fe:00 15691      /lib/libcrypt-2.15.so
b6e78000-b6e7f000 ---p 00006000 fe:00 15691      /lib/libcrypt-2.15.so
b6e7f000-b6e80000 r--p 00005000 fe:00 15691      /lib/libcrypt-2.15.so
b6e80000-b6e81000 rw-p 00006000 fe:00 15691      /lib/libcrypt-2.15.so
b6e81000-b6ea8000 rw-p 00000000 00:00 0 
b6eb3000-b6ecb000 r-xp 00000000 fe:00 15710      /lib/ld-2.15.so
b6ece000-b6ed2000 rw-p 00000000 00:00 0 
b6ed2000-b6ed3000 r--p 00017000 fe:00 15710      /lib/ld-2.15.so
b6ed3000-b6ed4000 rw-p 00018000 fe:00 15710      /lib/ld-2.15.so
b6ed4000-b6f0a000 r-xp 00000000 fe:00 9190       /usr/sbin/pppd
b6f12000-b6f13000 r--p 00036000 fe:00 9190       /usr/sbin/pppd
b6f13000-b6f16000 rw-p 00037000 fe:00 9190       /usr/sbin/pppd
b6f16000-b6f61000 rw-p 00000000 00:00 0 
b8719000-be995000 rw-p 00000000 00:00 0          [heap]
be9a9000-be9ca000 rw-p 00000000 00:00 0          [stack]
ffff0000-ffff1000 r-xp 00000000 00:00 0          [vectors]

Now the region around 0x3e0000000 is mapped and I can now provide a command over 0x80000000 and write what I like down in that area. On Arm Linux malloc creates 'malloc chuck' meta data block every megabyte which I now control. I can tell when the 1meg blocks get allocated cuz I can time the mallocs and they take much longer as they need a syscall. I've not finished it yet but my goal would be to mess with the heap meta-data and the free-list so I force an allocation to happen in the global vars of pppd (0xb6f13000 in this example). I hope to get something non-zero in the 'privileged' variable so then i can do the plugin command and load my code.  

I'm not sure I'm going to have time to finish a full proof of concept but it looks controllable. 
Author has now fixed this. 
https://github.com/paulusmack/ppp/commit/7658e8257183f062dc01f87969c140707c7e52cb

Also fixed the mem leak I used to spray the heap
https://github.com/paulusmack/ppp/commit/b94b7fbbaa0589aa6ec5fdc733aeb9ff294d2656

An internal project is looking to update pppd in the ChromeOS tree to the latest stable (for non-security reasons). So looks like we can bring in these patches with that upgrade. Ben has offered to aid with testing.

Project Member

Comment 15 by bugdroid1@chromium.org, Aug 10 2014

Project: chromiumos/overlays/chromiumos-overlay
Branch : master
Author : Ben Chan <benchan@chromium.org>
Commit : 8582a3aac54dde89772053267339dea9f0457619

Code-Review  0 : Ben Chan, chrome-internal-fetch
Code-Review  +2: Mike Frysinger
Commit-Queue 0 : Mike Frysinger, chrome-internal-fetch
Commit-Queue +1: Ben Chan
Verified     0 : Mike Frysinger, chrome-internal-fetch
Verified     +1: Ben Chan
Change-Id      : I48d373a093306dfb038878f20bd16c5ed68056ed
Reviewed-at    : https://chromium-review.googlesource.com/211754

net-dialup/ppp: pull upstream fix for parsing options in config file

This CL pulls an upstream fix "commit
7658e8257183f062dc01f87969c140707c7e52cb (pppd: Eliminate potential
integer overflow in option parsing)".

BUG= chromium:390709 
TEST=Tested the following:
1. `emerge-$BOARD net-dialup/ppp`
2. Run the following tests:
   - network_VPNConnect.l2tpipsec_psk
   - network_VPNConnect.l2tpipsec_cert
3. Test 3G connectivity with a PPP-based dongle.

net-dialup/ppp/files/ppp-2.4.6-options-fix.patch
net-dialup/ppp/ppp-2.4.6-r5.ebuild
Status: Fixed
Thanks Ben!
Labels: VerifyIn-40
Project Member

Comment 18 by ClusterFuzz, Nov 16 2014

Labels: -Restrict-View-SecurityTeam
Bulk update: removing view restriction from closed bugs.
Status: Verified
Project Member

Comment 20 by sheriffbot@chromium.org, Oct 1 2016

This bug has been closed for more than 14 weeks. Removing security view restrictions.

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot
Project Member

Comment 21 by sheriffbot@chromium.org, Oct 1 2016

Labels: Restrict-View-SecurityNotify
Project Member

Comment 22 by sheriffbot@chromium.org, Oct 2 2016

Labels: -Restrict-View-SecurityNotify
This bug has been closed for more than 14 weeks. Removing security view restrictions.

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot
Labels: allpublic
Labels: CVE_description-submitted
Project Member

Comment 25 by sheriffbot@chromium.org, Jul 29

Labels: -Pri-2 Pri-1

Sign in to add a comment