$Id: LIDS-TPE-feature.txt,v 1.3 2004/03/12 05:58:08 purna Exp $ --------------------------------- LIDS Trusted Path Execution (TPE) --------------------------------- Yusuf Wilajati Purna (ywpurna@users.sourceforge.net) March 09, 2004 INTRODUCTION ============ A trusted path is known as one of classic protection mechanisms in a security model. It is in short a mechanism to make sure that a user can access the trusted software without being compromised by other processes or users, and to make sure that the software runs correctly as really intended. Some standards and papers ([1], [2]) give a more formal definition of the term. One concept trying to provide a trusted mechanism with the main purpose of preventing arbitrary users from executing arbitrary code is usually called Trusted Path Execution, or TPE for short. There has been a lot of security enhancements or patches for either Linux or *BSD kernels implementing this mechanism ([3], [4], [5], [6], and [7]). From these implementations, in general, TPE can be thought to be built based on the following 3 main components: - Trusted Path. ------------- This is a trusted path in the narrow meaning. Usually, a path is considered trusted if the parent directory is owned by 'root' and is neither group or world writeable. - Trusted ACL. ------------ This is a list of trusted users. That is, in addition to 'root', a user on the list is considered trusted. - Rule. ----- This is a policy or rule to decide if an executable can be run based on the trusted path and trusted ACL info/states. For example, [7] has the features as follows: a trusted path and a trusted ACL as are defined above, and the following rules to decide when an executable can be run: - Trusted user, trusted path -> the user can run the executable - Trusted user, untrusted path -> the user can run the executable - Untrusted user, trusted path -> the user can run the executable - Untrusted user, untrusted path -> the user cannot run the executable Thus, in this implementation, theoritically an executable cannot be run, only when the user is not trusted (i.e., it is not in the trusted ACL) and the executable is not in the trusted path. However, in practice, there are still some holes in this implementation. For example, since protection mechanisms from LD_PRELOAD/LD_LIBRARY_PATH (library) type attacks and '/lib/ld-linux.so.X ' type attacks are not implemented, an untrusted user does not need a lot of effort in order to run an untrusted executable (i.e., an executable that is on an untrusted path) by exploiting these types of attacks. Based on mostly the same general concepts of TPE above, I have tried to enhance the current LIDS so that in TPE mode LIDS will only execute binaries as well as libraries, and even load kernel modules as far as they are protected. APPROACH ======== To enhance LIDS with TPE, we can define the 3 components of general TPE as follows: - Trusted Path. -------------- It's not useful if we define the parent directory owned by root and neither group or world writeable as a trusted path in LIDS because one of LIDS motivations is to restrict root's privileges. Instead, we define that binaries/kernel modules/libraries/paths are considered trusted if they are protected with READONLY mode access by LIDS at the minimum. That is, the default rules for them are READONLY at the minimum. Examples: - lidsconf -A -o /sbin -j READONLY -> Executables under /sbin are trusted. - lidsconf -A -o /lib -j READONLY -> Libraries under /lib are trusted. - lidsconf -A -o /lib/modules -j READONLY -> Modules under /lib/modules are trusted. - lidsconf -A -o /var/workdir -j READONLY lidsconf -A -o /sbin/application_a -j READONLY lidsconf -A -s /sbin/application_a -o /var/workdir -j WRITE -> Although the protected application_a has WRITE access to /var/workdir, files under /var/workdir are considered trusted. - Trusted ACL. ------------ It's not useful either if we define a list of trusted users as a trusted ACL. LIDS focuses more on binaries/programs rather than users runnning the programs. There is already LIDS ACL. Here, we can define a LIDS ACL as the trusted ACL. - Rule. ----- We can define a simple rule as follows: Only trusted binaries are allowed to run, and only trusted libraries/kernel modules are allowed to load. Hey, wait! It seems that we already have a similar mechanism in LIDS. Yes, it's right. Currently, when we set CONFIG_LIDS_NO_EXEC_UP to Y when configuring the kernel, LIDS will refuse to execute unprotected programs before the kernel is sealed (lidsadm -I). Thus, the basic mechanism is already available in LIDS. Furthermore, if we take a broader view at the LIDS itself, LIDS is in fact a kind of TPE implementation in a bigger framework. IMPLEMENTATION ============== KERNEL SPACE ------------ In kernel space, a basic funtion to check if a path is protected or not is already available in LIDS. Thus the task is to create functions that include the basic function and decide where and when we must do the permission checking. The TPE enhancement is implemented in the following 3 functions: - lids_exec_tpe_permission(brpm) ------------------------------ This is the function to check if the binary is protected or not. - lids_mmap_tpe_permission(file, protection) ------------------------------------------ This function checks if the library is protected or not. - lids_module_tpe_permission(module) ---------------------------------- This one is used to check if the module is protected or not before loading the module. Places where these functions should be called are mostly derived from LSM hooks ([8]). For lids_exec_tpe_permission(brpm), we can place a hook to call the function in fs/exec.c:do_exec(). The basic algorithm is as follows: --------------------------------------------------------------------- lids_exec_tpe_permission(bprm) { int error = 0 if (!lids_check_base(bprm->file->dentry, LIDS_APPEND)) error = -EACCES; return error; } --------------------------------------------------------------------- Note that this is not the real code. Think of it as pseudo code. It simply checks if the dentry of the file is protected or not. If it is not protected, the function simply return an error with -EACCES as the error code. Since most of libraries are loaded by using mmap(), we can place a hook to call the function to check a library in mm/mmap.c:do_mmap_pgoff(). The following shows a basic algorithm of lids_mmap_tpe_permission(): --------------------------------------------------------------------- lids_mmap_tpe_permission(file, protection) { int error = 0; if (!file) return 0; if (!(protection & PROT_EXEC)) return 0; if (!lids_check_base(file->dentry, LIDS_APPEND)) error = -EPERM; return error; } --------------------------------------------------------------------- It only checks the file with PROT_EXEC as the memory protection attribute, that really exists on the file system. If this file is not protected the function simply returns an error with -EPERM as the error code. To check if a module is protected or not we can make use of symbols information in the module. We use the symbols information to derive the path of the module. A hook to call this function is then can be placed in kernel/module.c:sys_init_module(). The basic algoritm of the function is as follows: --------------------------------------------------------------------- lids_module_tpe_permission(module) { int error = 0; modpath = get_module_path(module); if (!lids_check_base(modpath->dentry, LIDS_APPEND)) error = -EPERM; return error; } --------------------------------------------------------------------- After getting the path info of the module from the symbols, as the other two previous functions, lids_module_tpe_permission() checks if the path is protected or not. It simply returns -EPERM if the path is not protected. Those are the 3 main functions composing the basic checking mechanism of LIDS TPE. This mechanism itself is introduced into LIDS as an option that can be controlled using a LIDS kernel configuration parameter. We use CONFIG_LIDS_TPE as the parameter. Setting CONFIG_LIDS_TPE to 'Y' when configuring the kernel for compilation enables the LIDS TPE feature in the kernel. USER SPACE ---------- Similar to ACL_DISCOVERY mode, the 'TPE mode' term is used to describe the state of LIDS during the operation. To easily control this mode a new flag is added into lidstools: the TPE flag. Its status can be used to check if the system in TPE mode or not. We can also use this flag to switch TPE mode to ON and OFF in the system as follows, respectively: # lidsadm -S -- +TPE /* This will switch on TPE mode */ # lidsadm -S -- -TPE /* This will switch off TPE mode */ We can also switch on the TPE mode in the same time as sealing the kernel: # lidsadm -I +TPE Turning on the ACL_DISCOVERY mode for a while, in the beginning, will help identify which libraries should be protected when running applications on TPE mode. WHAT LIDS TPE CAN DO AND CANNOT DO? =================================== With the above implementation, then, what LIDS TPE can really do? It can be simply explained as follows: - It prevents arbitrary users, including a user with root privilege, from executing arbitrary executables (unprotected binaries), including unprotected libraries. - It prevents arbitrary users, including a user with root privilege, from loading unprotected kernel modules. - It protects the system from LD_PRELOAD/LD_LIBRARY_PATH type attacks. - It protects the system from '/lib/ld-linux.so.X ' type attacks. (*) (*) Note that for Linux kernels before 2.4.25 and 2.6.0, this protection mechanism cannot be achieved by simply using 'mount' with the 'noexec' option. Now, however, we can achieve a protection mechanism from '/lib/ld-linux.so.X ' type attacks in kernels 2.4.25 and 2.6.0. Nevertheless, LIDS TPE is more flexible. However, no protection mechanism is perfect. And, LIDS TPE is not yet perfect. Currently, LIDS TPE cannot prevent untrusted scripts from being executed by trusted intepreters such as sh, perl, etc. Thus, untrusted scripts can still be run by passing them directly to the corresponding interpreters. It cannot prevent either arbitrary code execution caused by buffer overflows vulnerabilities. CAVEATS ======= Due to the rule specified in the approach, LIDS TPE can cause trouble for applications that create temporarily scripts/executables on unprotected directories (e.g., /tmp) and run them during execution. These kinds of applications won't run properly. LIDS TPE will be very annoying if you run LIDS on this mode in your development environment because you cannot just compile your programs and test the programs. LIDS TPE is not proper for development environment. SUMMARY ======= LIDS TPE can prevent arbitrary users, including a user with root privilege, from executing arbitrary executables/libraries, as well as from loading unprotected/untrusted kernel modules. Although LIDS TPE is not proper for development environment, it can be expected that it will have some places on production servers since it can raise the security bar on protecting the integrity of the servers. For kernel 2.4, integrating LIDS TPE with other security projects such as, Openwall [9] and PaX [10] projects for example, it can be expected that we can also prevent arbitrary code execution caused by buffer overflows vulnerabilities to some degree and new arbitrary code from being introduced into the task address space. Finally, please enjoy, give it a try, and report any bugs. :-) ACKNOWLEDGEMENT =============== The TPE mechanism presented here is part of a project I have done at Sony Corp. On behalf of LIDS team, I would like to thank Sony Corp. for contributing this work for the LIDS community. AVAILABILITY ============ LIDS TPE has been implemented in LIDS 1.2.0. To control this feature, you need to use at least, lidstools 0.5.4. Source code is freely available from http://www.lids.org. REFERENCES ========== 1. US DoD, "Trusted Computer System Evaluation Criteria (DOD 5200.28-std)", 1985. 2. Loscocco, Smalley, et al, NSA, "The Inevitability of Failure: The Flawed Assumption of Security in Modern Computing Environment", 1998. http://www.nsa.gov/selinux/papers/inevitability/ 3. route|daemon9 , "Trusted Path Execution Patch fo Linux 2.0.0+", 1998. https://www.phrack.com/phrack/52/P52-06 4. Krzysztof G. Baranowski , "Linux Trusted Patch Execution Redux", https://www.phrack.com/phrack/53/P53-08, 1998. 5. route|Mike Schiffman|daemon9 , "Trusted Path/ACL Execution Patches for OpenBSD 2.4-SNAP", 1998. https://www.phrack.com/phrack/54/P54-06 6. Brian , "TPE in Stephanie for OpenBSD 3.4", 2003. http://kaizo.org/mirrors/stephanie/ 7. Niki Rahimi "TPE LSM module for Linux 2.5.59 (2.6)", 2003. http://www-124.ibm.com/developer/opensource/linux/patches/?patch_id=770 8. LSM Developers/Community , "LSM Linux Security Modules". http://lsm.immunix.org/ 9. Solar Designer et al, "Openwall Project". http://www.openwall.com/ 10. PaX Team, "PaX Project". http://pax.grsecurity.net/ EOF