Introduction
In this post we talk a little about sandbox. People that work and study software exploitation know the sandbox concept. This kind of feature when properly implemented on a system makes hard to exploit some kind of vulnerabilities, especially that involving memory corruption. In wikipedia we have a good reference about this:
“In computer security, a sandbox is a security mechanism for separating running programs. It is often used to execute untested code, or untrusted programs from unverified third parties, suppliers, untrusted users and untrusted websites. A sandbox typically provides a tightly controlled set of resources for guest programs to run in, such as scratch space on disk and memory. Network access, the ability to inspect the host system or read from input devices are usually disallowed or heavily restricted.”
The sandbox is a security mechanism that separates running processes. Basically we have a process with least privileges (target) and another process with greater privileges (broker). If the process with least privileges need execute some operation that is not allowed, a request is sent to the process with greater privileges that checks whether the operation has permissions to be executed and run with return to target (process with least privilege). Sandbox normally is used to protect the application and can also be used to provide a restricted environment for execute and test some malicious binaries, one example of this is Cuckoo Sandbox that used for malware analysis.
In this post we talk about Capsicum[1], is that a kind of sandbox developed by the University of Cambridge that support several common commands of the system such as tcpdump[2], hastd, dhclient, kdump and sshd as mentioned in the website[3]. The Capsicum is a new kind of sandbox but we have support for use in the FreeBSD and Linux[4]. The first experimental version was made only for FreeBSD[5] and available since version 9.0. This sandbox add two new features to the system, called capability mode and capabilities.
Here we introduced a rapid explanation about two modes. Capability mode is the feature that enable for the developers isolate processes allowing only that some system calls execute some tasks reducing the permissions of the process. Capabilities enables a more refined control over the files and devices. This post has more focus on the capability mode.
Building the kernel with Capsicum
In the FreeBSD 10.0, the capsicum has enabled by default but in FreeBSD 9.0 is necessary to enable manually and rebuild the kernel for using this feature.
Basically, edit your GENERIC kernel file at /usr/src/sys/amd64/conf/GENERIC and add this option:
options CAPABILITY_MODE
In the next step we need rebuild the kernel, we have many possible ways to execute this task but we recommended to use the options avaliable at [6].
After Capsicum is activated in the kernel, we have a new sysctl option and two new syscalls cap_getmode() and cap_enter() to interact with this.
Ok, we have Capsicum enabled and we have a code written to demonstrate this operation. The code below is a simple example that we use to confirm if Capsicum is working. If the syscall execve() fails, it shows the Capsicum is working properly and deny the syscall execution.
File: example01.c --- 1 #include 2 #include 3 #include 4 #include 5 #include <sys/capability.h> 6 7 int main(void){ 8 9 bool sandbox_status; 10 11 char *const command[] = {"/bin/sh", NULL }; 12 13 cap_enter(); 14 15 sandbox_status = cap_sandboxed(); 16 if(sandbox_status == true){ 17 fprintf(stdout,"Sandbox enabledn"); 18 } 19 else{ 20 fprintf(stdout,"Capsicum disabledn"); 21 } 22 23 if(execve("/bin/sh",command,NULL) == -1){ 24 perror("execve"); 25 exit(EXIT_FAILURE); 26 } 27 28 return 0; 29 } ---
A closer look at Capsicum
In the output from example01 we can see that the execve() syscall execution has failed and the error message has returned that syscall is not allowed to be executed on capability mode. The syscalls are the main ways of communication with the kernel and limit some permissions reduces the exploitation vectors of an possible attacker.
File: /usr/src/sys/kern/sys_capability.c --- 90 /* 91 * System call to enter capability mode for the process. 92 */ 93 int 94 sys_cap_enter(struct thread *td, struct cap_enter_args *uap) 95 { 96 struct ucred *newcred, *oldcred; 97 struct proc *p; 98 99 if (IN_CAPABILITY_MODE(td)) 100 return (0); 101 102 newcred = crget(); 103 p = td->td_proc; 104 PROC_LOCK(p); 105 oldcred = p->p_ucred; 106 crcopy(newcred, oldcred); 107 newcred->cr_flags |= CRED_FLAG_CAPMODE; 108 p->p_ucred = newcred; 109 PROC_UNLOCK(p); 110 crfree(oldcred); 111 return (0); 112 } ---
File: /usr/src/sys/sys/capability.h --- 343 #define IN_CAPABILITY_MODE(td)((td->td_ucred->cr_flags & CRED_FLAG_CAPMODE) != 0) ---
File: /usr/src/sys/sys/ucred.h --- 49 struct ucred { 50 u_int cr_ref; /* reference count */ 51 #define cr_startcopy cr_uid 52 uid_t cr_uid; /* effective user id */ 53 uid_t cr_ruid; /* real user id */ 54 uid_t cr_svuid; /* saved user id */ 55 int cr_ngroups; /* number of groups */ 56 gid_t cr_rgid; /* real group id */ 57 gid_t cr_svgid; /* saved group id */ 58 struct uidinfo *cr_uidinfo; /* per euid resource consumption */ 59 struct uidinfo *cr_ruidinfo; /* per ruid resource consumption */ 60 struct prison *cr_prison; /* jail(2) */ 61 struct loginclass *cr_loginclass; /* login class */ 62 u_int cr_flags; /* credential flags */ 63 void *cr_pspare2[2]; /* general use 2 */ 64 #define cr_endcopy cr_label 65 struct label *cr_label; /* MAC label */ 66 struct auditinfo_addr cr_audit; /* Audit properties. */ 67 gid_t *cr_groups; /* groups */ 68 int cr_agroups; /* Available groups */ 69 gid_t cr_smallgroups[XU_NGROUPS]; /* storage for small groups */ 70 }; ---
The cap_getmode() syscall and function cap_sandboxed() is used to check if the capability mode is enabled in the running process. The cap_sandboxed() is a function that calls cap_getmode() syscall. This function was designed to help developers because cap_getmode() is always executed successfully and here we don’t need check your return value and the cap_sandboxed() returns true or false respectively.
File: /usr/src/sys/kern/sys_capability.c --- 114 /* 115 * System call to query whether the process is in capability mode. 116 */ 117 int 118 sys_cap_getmode(struct thread *td, struct cap_getmode_args *uap) 119 { 120 u_int i; ... 122 i = IN_CAPABILITY_MODE(td) ? 1 : 0; 123 return (copyout(&i, uap->modep, sizeof(i))); 124 } ---
We have a file called capabilities.conf at directory /usr/src/sys/kern/ which contain all syscalls enabled to be executed by a process with the capability mode. Another way to know what syscalls are allowed is to look at the file /usr/src/sys/kern/init_sysent.c that contains the syscalls definitions. The syscalls containing the SYF_CAPENABLED parameter are enabled for execution. The check is made by the function syscallenter(). This function is responsible for managing all syscalls executed by the kernel, running after the interrupt handler.
File: /usr/src/sys/kern/subr_syscall.c --- 55 static inline int 56 syscallenter(struct thread *td, struct syscall_args *sa) 57 { ... 106 #ifdef CAPABILITY_MODE 107 /* 108 * In capability mode, we only allow access to system calls 109 * flagged with SYF_CAPENABLED. 110 */ 111 if (IN_CAPABILITY_MODE(td) && 112 !(sa->callp->sy_flags & SYF_CAPENABLED)) { 113 error = ECAPMODE; 114 goto retval; 115 } 116 #endif ... 165 } ---
At the moment of this post, on 64-bit systems, Capsicum does not have support for 32-bit binaries. FreeBSD has a layer (compat32) that allows 32-bit binaries runs on FreeBSD 64-bit systems.
Example of using Capsicum on a 32-bits process
Example of using Capsicum on a 64-bits process
Conclusion
The use of sandbox drastically reduces the ways that an attacker has to run code after exploiting a vulnerability. With Capsicum, if the FreeBSD kernel is exploited for escalation privileges to root, like the two previous posts that I have written[7][8], a new step is necessary to disable Capsicum and being able to do something useful. If the sandbox is not disabled, the attacker don’t have a successful attack because he don’t have permissions to execute some syscalls.
Nowadays, many popular software use this kind of technology, for example, Adobe Reader X, Flash Player and Google Chrome. The use of this kind of technology also result in more attention to kernel vulnerabilities because they may help in circumventing the restrictions imposed by the sandbox. For example, Google Chrome at pwn2own 2013 edition[9], a researcher needs escape the sandbox to execute arbitrary code. Another example is the famous malware Duqu that contains an exploit for a vulnerability in the Windows kernel that when explored give full access to the machine, escaping from Microsoft Word sandbox.
Although there are ways to circumvent the sandbox in some situations, but this a kind of technology that is highly recommended to use for protect your application.
References
[1] – https://www.cl.cam.ac.uk/research/security/capsicum/
[2] – https://lists.freebsd.org/pipermail/svn-src-head/2013-July/049317
[3] – https://www.cl.cam.ac.uk/research/security/capsicum/freebsd
[4] – https://www.cl.cam.ac.uk/research/security/capsicum/linux
[5] – https://www.freebsd.org/releases/9.0 R/announce
[6] – https://www.freebsd.org/doc/handbook/kernelconfig-building
[7] – https://blog.andersonc0d3.io/entendendo-e-explorando-o-cve-2012-4576
[8] – https://blog.andersonc0d3.io/uma-analise-do-cve-2012-0217
[9] – https://labs.mwrinfosecurity.com/blog/2013/09/06/mwr-labs-pwn2own-2013-write-up—kernel-exploit/