From N-day exploit to Kerberos EoP in Linux environments

Introduction

In one of its operations, the Red Team achieved command execution in a perimeter web page as a non-privileged user. This article describes the analysis and exploiting of a vulnerability (CVE-2018-1685) that could allow an attacker to read arbitrary files, but of which no public details are known. Finally, we’ll present a method to turn this type of vulnerability (arbitrary file read) into a full system compromise (command execution), when playing around with Active Directory joined Linux machines (via Kerberos).

Privilege escalation

The compromised machine is a recently updated Red Hat server, thus privilege escalation via kernel exploit is discarded. After the typical routine checks, some root-owned executables with the SUID bit set are detected:

 /home/db2test/sqllib/adm:
 total 5.3M
 drwxr-sr-x.  2 db2test db2test  112 Oct  8 10:29 .
 drwxrwsr-t. 19 db2test db2test 4.0K Oct  8 10:32 ..
 -r-sr-xr-x.  1 db2test db2test 152K Oct  8 10:29 db2audit
 -r-sr-xr-x.  1 root    db2test  19K Oct  8 10:29 db2cacpy
 -r-xr-xr-x.  1 db2test db2test 195K Oct  8 10:29 db2cap
 -r-sr-x---.  1 root    db2test  32K Oct  8 10:29 db2iclean
 -r-sr-x---.  1 root    db2test  87K Oct  8 10:29 db2licm
 -r-xr-xr-x.  1 db2test db2test 120K Oct  8 10:29 db2set
 -r-sr-sr-x.  1 db2test db2test 4.7M Oct  8 10:29 db2trc  

The “db2test” user seems to be related to a DB2 testing installation, an IBM’s database management system. After a quick Google search, we find a security bulletin about one of these executables (db2cacpy), published by the vendor:

CVE-2018-1685 description
CVE-2018-1685 description
Workarounds and Mitigations
Workarounds and Mitigations

Although they don’t reveal technical details about the vulnerability, we can highlight two interesting hints:

  • It could allow a local user to read any file on the system.
  • In the “Workarounds” section, they note that deleting this binary will remove the ability to add ports into /etc/services when adding new databases for the “Configuration Assistant”.

With this information in hand, the Red Team proceeds to spot the vulnerability.

CVE-2018-1685: the vulnerability hunt

Firstly, we download the executable in order to analyze it locally. We need also to download about 10 DB2 libraries, to make the tool work.

After an initial static analysis, we can break down its behavior. The binary receives 2 command-line arguments, on which it performs a check for each of them, before the program continues.

First check

It checks, in a somewhat obfuscated way, if the first argument matches with a key which is stored in cleartext on the “.rodata” segment.

First check disassembly
First check disassembly

Second check

In this case, it checks whether the second argument starts with the string /tmp/services., probably because another DB2 component generates files following this pattern.

Second check disassembly
Second check disassembly

Vulnerability

If these two checks are met, the tool copies the specified file (second parameter) to /etc/services, overwriting it. A possible pseudocode, simplified, could be the following:

func main(argc, argv[]) {
   init_db2()

   if (argc is 3)
   {
      if (argv[1] equals HARDCODED_KEY) {
         if (argv[2] startsWith "/tmp/services.") {
            copy_file(argv[2], "/etc/services")
         }
      }
   }
}

How to take advantage of this to read arbitrary files? Through path traversal. If we create a directory called “services.” (or one which starts like that) in /tmp, we could trigger the copy of /tmp/services./../../etc/shadow, fulfilling the second check.

You can find a working exploit in this repository, which also takes care of restoring the original /etc/services file after exploitation. Note that the key (first check) might vary depending on the DB2 version or setup (we cannot test that).

Reading /etc/shadow
Reading /etc/shadow

From arbitrary read to command execution as root

Since it’s an AD-joined Linux server via Kerberos, we first check if there are valid TGTs (ccache files) in /tmp (to reuse them), but all of them are expired. Therefore, we look for a path which doesn’t require user interaction: the keytab file.

The keytab contains the computer account’s keys (by default /etc/krb5.keytab in Red Hat). You can use the computer account’s keys to forge tickets for its services (TGS).

To extract the keys from the keytab, we use a script together with our DB2 exploit.

Keys extraction from keytab
Keys extraction from keytab

Then, using the ticketer.py tool from impacket we craft a TGS for the SSH service of the server (“host” SPN) in the name of a domain user who has admin privileges on the machine.

Crafting a TGS in the name of a server admin
Crafting a TGS in the name of a server admin

Finally, we can use the resulting ticket to connect via SSH, authenticating using Kerberos.

Command execution as "root"
Command execution as “root”

Conclusion

In this article, we’ve seen how an attacker can exploit a well-known vulnerability, for which there is no exploit or public details. That’s why it’s important to stress the relevance of applying every security patch as soon as possible and not only when an exploit comes out (an example of this was the publication of Zerologon, where many companies didn’t see its gravity until some exploits were released on GitHub, months later).