LevelBlue Completes Acquisition of Cybereason. Learn more

LevelBlue Completes Acquisition of Cybereason. Learn more

Services
Cyber Advisory
Managed Cloud Security
Data Security
Managed Detection & Response
Email Security
Managed Network Infrastructure Security
Exposure Management
Security Operations Platforms
Incident Readiness & Response
SpiderLabs Threat Intelligence
Solutions
BY TOPIC
Offensive Security
Solutions to maximize your security ROI
Operational Technology
End-to-end OT security
Microsoft Security
Unlock the full power of Microsoft Security
Securing the IoT Landscape
Test, monitor and secure network objects
Why LevelBlue
About Us
Awards and Accolades
LevelBlue SpiderLabs
LevelBlue Security Operations Platforms
Security Colony
Partners
Microsoft
Unlock the full power of Microsoft Security
Technology Alliance Partners
Key alliances who align and support our ecosystem of security offerings

CUPS Local Privilege Escalation And Sandbox Escapes

CVE-2018-4180, CVE-2018-4182, CVE-2018-4183, CVE-2018-6553, CVE-2018-4181: Multiple vulnerabilities in Apple's CUPS print system leading to local privilege escalation and sandbox escapes.

Aon’s Cyber Labs has discovered multiple vulnerabilities in Apple’s CUPS print system affecting macOS 10.13.4 and earlier and multiple Linux distributions. All information in this post has been shared with Apple and other affected vendors prior to publication as part of the coordinated disclosure process. All code is excerpted from Apple’s open source CUPS repository located at https://github.com/apple/cups.

The vulnerabilities allow for local privilege escalation to root (CVE-2018-4180), multiple sandbox escapes (CVE-2018-4182 and CVE-2018-4183), and unsandboxed root-level local file reads (CVE-2018-4181). A related AppArmor-specific sandbox escape (CVE-2018-6553) was also discovered affecting Linux distributions such as Debian and Ubuntu. When chained together, these vulnerabilities allow an unprivileged local attacker to escalate to unsandboxed root privileges on affected systems.

Affected Linux systems include those that allow non-root users to modify cupsd.conf such as Debian and Ubuntu. Redhat and related distributions are generally not vulnerable by default. Consult distribution-specific documentation and security advisories for more information.

The vulnerabilities were patched in macOS 10.13.5, and patches are currently available for Debian and Ubuntu systems. Aon would like to thank Apple, Debian, and Canonical for working to patch the vulnerabilities, and CERT for assisting in vendor coordination.

Credits:

  • CVE-2018-4180 – Dan Bastone
  • CVE-2018-4182 – Dan Bastone
  • CVE-2018-4183 – Dan Bastone and Eric Rafaloff
  • CVE-2018-6553 – Dan Bastone
  • CVE-2018-4181 – Eric Rafaloff and John Dunlap

Timeline:

  • 02/21/2018 – Initial disclosure to Apple
  • 02/26/2018 – Initial disclosure to Debian and Canonical (CVE-2018-6553)
  • 03/02/2018 – Issues confirmed by Apple
  • 05/04/2018 – Apple requests delay of public disclosure due to downstream vendor coordination with CERT
  • 06/01/2018 – Apple releases fixes in macOS 10.13.5
  • 06/05/2018 – Apple publishes patches on their public Github repository
  • 07/11/2018 – Public disclosure

Apple Security Advisory (updated 7/11/18):

https://support.apple.com/HT208849

Linux Vendor Advisories:

https://www.debian.org/security/2018/dsa-4243https://usn.ubuntu.com/3713-1/

Patches:

https://github.com/apple/cups/commit/d47f6aec436e0e9df6554436e391471097686ecc

This post describes the privilege escalation and sandbox escape vulnerabilities and their fixes. Exploit code is currently being withheld, and will be released at a later date. Details of the root-level local file read issue (CVE-2018-4181) will be released in a follow-up blog post.

 

Local privilege escalation to root due to insecure environment variable handling – CVE-2018-4180

Overview:

Affected versions of CUPS allow for the SetEnv and PassEnv directives to be specified in the cupsd.conf file, which is editable by non-root users using the cupsctl binary. This allows attacker-controlled environment variables to be passed to CUPS backends, some of which are run as root. By passing malicious values in environment variables to affected backends, it is possible to execute an attacker-supplied binary as root, subject to sandbox restrictions.

Details:

Multiple vulnerable code paths exist for this issue, one of which is shown below. The environment variable is used to construct a filename on lines 804 and 807 that is executed on line 819.

cups/backend/dnssd.c:
800  /*
801   * Get the filename of the backend...
802   */
803
804   if ((cups_serverbin = getenv("CUPS_SERVERBIN")) == NULL)
805      cups_serverbin = CUPS_SERVERBIN;
806
807   snprintf(filename, sizeof(filename), "%s/backend/%s", cups_serverbin, scheme);
[…]
817   fprintf(stderr, "DEBUG: Executing backend \"%s\"...\n", filename);
818
819   execv(filename, argv);


Fix:

The issue was remediated by moving the SetEnv and PassEnv configuration directives from cupsd.conf to cups-files.conf, which is only editable by root. Additionally, sensitive environment variables that may have security implications have been restricted and can no longer be set using these directives. This effectively prevents all known exploit vectors.

Anticipate threats and protect your business with LevelBlue.

Explore Services

MacOS cups-exec sandbox bypass due to insecure error handling – CVE-2018-4182

Overview:

It is possible to cause cups-exec to execute backends without a sandbox profile by causing cupsdCreateProfile() to fail. An attacker that has obtained sandboxed root access can accomplish this by setting the CUPS temporary directory to immutable using chflags, which will prevent the profile from being written to disk.

Chaining this vulnerability with CVE-2018-4180 results in unsandboxed root code execution.

Details:

When /var/spool/cups/tmp is set to immutable, the following sequence will fail, resulting in DefaultProfile being set to NULL in cupsdStartServer(). This error is ignored, and execution continues.

DefaultProfile =                NULL
   cupsdCreateProfile()         ^
       cupsTempFile2()          |
          cupsTempFd()           |
             open("/var/spool/cups/tmp/...") = -1 [Operation not permitted]
When cupsdStartProcess() is later called to execute a backend, the NULL default profile is passed as an argument:

scheduler/client.c:
3819 if (cupsdStartProcess(command, argv, envp, infile, fds[1], CGIPipes[1],
3820 -1, -1, root, DefaultProfile, NULL, &pid) < 0)

When cupsdStartProcess() is later called to execute a backend, the NULL default profile is passed as an argument:

scheduler/client.c:
3819 if (cupsdStartProcess(command, argv, envp, infile, fds[1], CGIPipes[1],
3820        -1, -1, root, DefaultProfile, NULL, &pid) < 0)

The process is then executed unsandboxed, because the profile is NULL.

scheduler/process.c:
455 int               /* O - Process ID or 0 */
456 cupsdStartProcess(
457      const char    *command,       /* I - Full path to command */
458      char          *argv[],        /* I - Command-line arguments */
459      char          *envp[],        /* I - Environment */
460      int           infd,           /* I - Standard input file descriptor */
461      int           outfd,          /* I - Standard output file descriptor */
462      int           errfd,          /* I - Standard error file descriptor */
463      int           backfd,         /* I - Backchannel file descriptor */
464      int           sidefd,         /* I - Sidechannel file descriptor */
465      int            root,          /* I - Run as root? */
466      void           *profile,      /* I - Security profile to use */
467      cupsd_job_t    *job,          /* I - Job associated with process */
468      int            *pid)          /* O - Process ID */
469 {
[...]
545 /*
546 * Use helper program when we have a sandbox profile...
547 */
548
549 #if !USE_POSIX_SPAWN
550   if (profile)
551 #endif /* !USE_POSIX_SPAWN */
552   {
553     snprintf(cups_exec, sizeof(cups_exec), "%s/daemon/cups-exec", ServerBin);
554     snprintf(user_str, sizeof(user_str), "%d", user);
555     snprintf(group_str, sizeof(group_str), "%d", Group);
556     snprintf(nice_str, sizeof(nice_str), "%d", FilterNice);
557
558     real_argv[0] = cups_exec;
559     real_argv[1] = (char *)"-g";
560     real_argv[2] = group_str;
561     real_argv[3] = (char *)"-n";
562     real_argv[4] = nice_str;
563     real_argv[5] = (char *)"-u";
564     real_argv[6] = user_str;
565     real_argv[7] = profile ? profile : "none";
566     real_argv[8] = (char *)command;

The following debug output shows execution of exploits for CVE-2018-4180 and CVE-2018-4182.

CUPS_SERVERBIN is set to the attacker-controlled directory by the exploit:

d [18/Feb/2018:21:50:21 -0500] cupsdSetEnv: CUPS_SERVERBIN=/tmp/exploit
[...]
D [18/Feb/2018:21:50:21 -0500] [Job 69] envp[1]="CUPS_SERVERBIN=/tmp/exploit"

dnssd is executed as root with a valid sandbox profile:

cupsdStartProcess(command="/usr/libexec/cups/backend/dnssd", argv=0x7ffee67eac30, envp=0x7ffee67ece90, infd=-1, outfd=-1, errfd=15, backfd=17, sidefd=19, root=1, profile=0x7f9339d1acb0, job=0x7f9339e203d0(69), pid=0x7f9339e20538) = 2463

dnssd then executes its sub-backend from the attacker-controlled CUPS_SERVERBIN containing the exploit payload. On this initial execution, the write to /exploit.txt will fail, and the payload will set the CUPS temp directory to immutable.

D [18/Feb/2018:21:50:21 -0500] [Job 69] Executing backend \"/tmp/exploit/backend/dnssd\"...
D [18/Feb/2018:21:50:21 -0500] [Job 69] /tmp/exploit/backend/dnssd: line 2: /exploit.txt: Operation not permitted

The payload then triggers the exploit again:

D [18/Feb/2018:21:50:21 -0500] [Job 70] envp[1]="CUPS_SERVERBIN=/tmp/exploit"

This time, the sandbox profile is prevented from being written:

d [18/Feb/2018:21:50:21 -0500] cupsdCreateProfile(job_id=70, allow_networking=0) = NULL
E [18/Feb/2018:21:50:21 -0500] Unable to create security profile: Operation not permitted
d [18/Feb/2018:21:50:21 -0500] cupsdCreateProfile(job_id=70, allow_networking=1) = NULL
E [18/Feb/2018:21:50:21 -0500] Unable to create security profile: Operation not permitted

This causes cupsdStartProcess to be called with a NULL profile argument, executing dnssd as root outside the sandbox:

d [18/Feb/2018:21:50:21 -0500] cupsdStartProcess(command="/usr/libexec/cups/backend/dnssd", argv=0x7ffee67fa7a0, envp=0x7ffee67fca00, infd=-1, outfd=-1, errfd=14, backfd=16, sidefd=18, root=1, profile=0x0, job=0x7f9339f12480(70), pid=0x7f9339f125e8) = 2469

Finally, the sub-backend executes outside the sandbox, writes to /exploit.txt, and exits successfully:

D [18/Feb/2018:21:50:21 -0500] [Job 70] Executing backend \"/tmp/exploit/backend/dnssd\"...
D [18/Feb/2018:21:50:21 -0500] [Job 70] PID 2469 (/usr/libexec/cups/backend/dnssd) exited with no errors.


Fix:

The issue was remediated through the addition of error-handling code and sanity checks that prevent backends from executing outside of a sandbox profile.

 

MacOS cups-exec sandbox bypass due to profile misconfiguration – CVE-2018-4183

Overview:

The sandbox profile dynamically generated by cupsdCreateProfile() unintentionally allows write access to /etc/cups. This can be used by an attacker that has obtained sandboxed root access to alter /etc/cups/cups-files.conf, leading to unsandboxed root code execution.

Details:

The issue is caused by the fact that both ServerRoot and StateDir are set to /etc/cups. The sandbox profile first denies write access to ServerRoot, but subsequently allows write access to StateDir. This is shown in cupsdCreateProfile() below.

cups/scheduler/process.c:
142   cupsFilePrintf(fp,
143                  "(deny file-write*\n"
144                  " (regex"
145        " #\"^%s$\"" /* ServerRoot */
146        " #\"^%s/\"" /* ServerRoot/... */
147        " #\"^/private/etc$\""
148        " #\"^/private/etc/\""
[...]
194    cupsFilePrintf(fp,
195                    "(allow file-write* file-read-data file-read-metadata\n"
196                    " (regex"
197        " #\"^%s$\"" /* TempDir */
198        " #\"^%s/\"" /* TempDir/... */
199        " #\"^%s$\"" /* CacheDir */
200        " #\"^%s/\"" /* CacheDir/... */
201        " #\"^%s$\"" /* StateDir */
202        " #\"^%s/\"" /* StateDir/... */
203        "))\n",
204        temp, temp, cache, cache, state, state);

This results in the following conflicting sandbox profile directives, ultimately allowing write access to /etc/cups:

(deny file-write*
  (regex #"^/private/etc/cups$" #"^/private/etc/cups/" #"^/private/etc$" #"^/private/etc/" #"^/usr/local/etc$" #"^/usr/local/etc/" #"^/Library$" #"^/Library/" #"^/System$" #"^/System/"))

(allow file-write* file-read-data file-read-metadata
  (regex #"^/private/var/spool/cups/tmp$" #"^/private/var/spool/cups/tmp/" #"^/private/var/spool/cups/cache$" #"^/private/var/spool/cups/cache/" #"^/private/etc/cups$" #"^/private/etc/cups/"))


Fix:

The sandbox profile was corrected to disallow writes to /etc/cups by removing the StateDir entries.

 

Apparmor cupsd sandbox bypass due to use of hard links – CVE-2018-6553

Overview:

It is possible to bypass the AppArmor cupsd sandbox by invoking the dnssd backend using an alternate name that has been hard linked to dnssd. Both Debian and Ubuntu use AppArmor and shipped the mdns backend in this manner, in contrast to macOS and other systems that use symbolic links. Invoking the mdns backend causes the AppArmor profile to treat the backend as 3rd party, removing sandbox restrictions.

Details:

The cups backend directory and an excerpt of the cups .deb post-installation script shows the use of hard links.

ls -l /usr/lib/cups/backend/{dnssd,mdns}
-rwxr--r-- 3 root root 18424 Aug 22 17:26 /usr/lib/cups/backend/dnssd
-rwxr--r-- 3 root root 18424 Aug 22 17:26 /usr/lib/cups/backend/mdns
$ stat /usr/lib/cups/backend/{dnssd,mdns}
  File: '/usr/lib/cups/backend/dnssd'
  Size: 18424 Blocks: 40 IO Block: 4096 regular file
Device: 801h/2049d Inode: 12615 Links: 3
Access: (0744/-rwxr--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2018-02-18 13:08:11.761022386 -0800
Modify: 2017-08-22 17:26:53.000000000 -0700
Change: 2018-02-14 11:32:56.356309575 -0800
 Birth: -
 File: '/usr/lib/cups/backend/mdns'
 Size: 18424 Blocks: 40 IO Block: 4096 regular file
Device: 801h/2049d Inode: 12615 Links: 3
Access: (0744/-rwxr--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2018-02-18 13:08:11.761022386 -0800
Modify: 2017-08-22 17:26:53.000000000 -0700
Change: 2018-02-14 11:32:56.356309575 -0800
 Birth: -

DEBIAN/postinst: (from cups_2.2.1-8_amd64.deb)
71      if [ "$module" = "dnssd" ]; then
72        ln /usr/lib/cups/backend/dnssd /usr/lib/cups/backend/mdns
73      fi

The AppArmor sandbox profile explicitly whitelists known backends, but neglects to include mdns. Because mdns is hard linked to dnssd, it matches the rule on line 95. If symbolic links were used instead, line 81 would match and the backend would be sandboxed as intended.

/etc/apparmor.d/usr.sbin.cupsd:
79 # backends which come with CUPS can be confined
80 /usr/lib/cups/backend/bluetooth ixr,
81 /usr/lib/cups/backend/dnssd ixr,
82 /usr/lib/cups/backend/http ixr,
83 /usr/lib/cups/backend/ipp ixr,
84 /usr/lib/cups/backend/lpd ixr,
85 /usr/lib/cups/backend/parallel ixr,
86 /usr/lib/cups/backend/serial ixr,
87 /usr/lib/cups/backend/snmp ixr,
88 /usr/lib/cups/backend/socket ixr,
89 /usr/lib/cups/backend/usb ixr,
90 # we treat cups-pdf specially, since it needs to write into /home
91 # and thus needs extra paranoia
92 /usr/lib/cups/backend/cups-pdf Px,
93 # third party backends get no restrictions as they often need high
94 # privileges and this is beyond our control
95 /usr/lib/cups/backend/* Cx -> third_party,


Fix:

The AppArmor profile was updated to explicitly sandbox the mdns backend.

ABOUT LEVELBLUE

LevelBlue is a globally recognized cybersecurity leader that reduces cyber risk and fortifies organizations against disruptive and damaging cyber threats. Our comprehensive offensive and defensive cybersecurity portfolio detects what others cannot, responds with greater speed and effectiveness, optimizes client investment, and improves security resilience. Learn more about us.

Latest Intelligence

Discover how our specialists can tailor a security program to fit the needs of
your organization.

Request a Demo