Blogs & Stories

SpiderLabs Blog

Attracting more than a half-million annual readers, this is the security community's go-to destination for technical breakdowns of the latest threats, critical vulnerability disclosures and cutting-edge research.

CVE-2018-2892 - Kernel Level Privilege Escalation in Oracle Solaris

Trustwave recently discovered a locally exploitable issue in all current versions of Oracle Solaris 10/11 as detailed in the recently posted Trustwave advisory. The issue is present in the kernel and is locally exploitable as an unprivileged user provided the local system has the Sun StorageTek Availability Suite (AVS) configured.

The Vulnerability

The vulnerability has an interesting history dating back to 2007 when the underlying issue was originally discovered and exploited. The original issue was disclosed on stage at CanSec 2009 ( https://cansecwest.com/slides.html). The root cause of the issue is a combination of an arbitrary memory dereference through a lack of bounds checking on a user-controlled array index combined with an unbounded user-controllable length in the call to copyin(). The combined result is an arbitrary memory write and overflow in the call to copyin(). The vulnerability itself is present in the ioctl handler for the '/dev/sdbc' device, the vulnerable code path passes through the following code with a 'cmd' value of 'SDBC_TEST_INIT ':

922 static int 923 sdbcioctl(dev_t dev, int cmd, void *arg, int mode, cred_t *crp, int *rvp) 924 {
953 switch (cmd) {
966 case SDBC_TEST_INIT: 967 rc = _sd_test_init(&args); 968 break;

The code passes through the call to _sd_testing_init(&args) to the function definition given below:

613 int 614 _sd_test_init(void *args) 615 { 616 register struct a { 617 caddr_t addr; 618 long ar; 619 long len; 620 long tsize; 621 long flag; 622 } *uap = (struct a *)args; 623 624 if (copyin(uap->addr, devarray[uap->ar]1, uap->len2)) { 625 return (EFAULT); 626 } 627 dev_tsize[uap->ar]3 = (uap->tsize < 48) ? 48 : uap->tsize; 628 dev_flag[uap->ar]4 = uap->flag; 629 return (0); 630 }

There are at least 4 different vulnerabilities in this small code fragment! We summarise these below:

  1. arbitrary memory dereference resulting in an arbitrary destination pointer being passed to copyin(),
  2. arbitrary user-controlled length in the call to copyin() resulting in an unbounded memory write,
  3. arbitrary memory dereference and thus a user controllable write,
  4. arbitrary memory dereference and thus a user controllable write.

However, the history of this particular vulnerability does not end there, sometime between 2009 and 2017 Oracle/Sun attempted to fix the issue by adding a bounds check on the value of uap->ar. The following disassembly illustrates the bounds checking Oracle/Sun applied:

Screen Shot 2018-07-17 at 08.24.03


As can be seen, the value of uap->ar should not be greater or equal to 128. However, we can also observer than Oracle/Sun did not modify the underlying type os uap->ar which is a signed long and as such a signedness issue exists since the value of uap->ar is not checked for a value < 0. As such an attacker could specify a value with the top most bit set (and thus negative) and pass the bounds check thereby dereferencing arbitrary memory once again. The remainder of the patch was to the limit the uap->len parameter to a signed value less than 256 (but also potentially negative).


Exploitation of the issue is almost identical to the exploit developed back in 2007 for the original issue with the exception of a change in architecture between OpenSolaris running on x86 (32-bit) and the newer Oracle Solaris 11 running on x86-64 taking into account that the user-supplied index uap->ar must now be a negative value.


Final Thoughts

In case you were wondering why there would be such an obviously exploitable issue in a common configuration of Oracle Solaris, well the following might provide some hints:

93 #define SDBC_TEST_INIT _SDBC_(5) /* TESTING - tdaemon parameters */ 94 /* 95 * char * device_name; 96 * int index; 97 * int len; 98 * int track_size; 99 * int flags; 100 */

The code in question may well be for testing purposes.

This vulnerability has been issued CVE-2018-2892.
Oracle has patched this vulnerability as a part of their July CPU patch cycle: http://www.oracle.com/technetwork/security-advisory/cpujul2018-4258247.html