In general, it's unwise to create overly large domains, especially domains that include unrelated programs. The traceroute_t domain considered in the preceding sections is perhaps such an overweight domain, since it relates to both the traceroute and Nmap programs. These programs perform a few somewhat similar operations, but they're not closely related . Because they're part of a single domain, a vulnerability in either program could enable an intruder to gain control of the entire domain. Let's presume that we prefer to avoid that fate and see what's required to create a domain specific to the Nmap program. To do so, we'll follow a procedure that also works in most similar cases: -
Determine what files are related to the domain. -
Determine the security contexts of these files. -
Decide what security contexts are appropriate for the new domain. -
-
Create a basic FC file that specifies proper labels for files related to the domain. -
If necessary, delete conflicting specifications from other FC files. -
Load the revised policy and label the domains. -
Repeat the following steps as needed: -
-
Tweak the TE or FC files as needed. 9.8.1 Determine What Files Are Related to the Domain As the procedure directs, let's start by finding out what files are related to Nmap: # rpm -ql nmap /usr/bin/nmap /usr/share/doc/nmap-3.50 /usr/share/doc/nmap-3.50/COPYING /usr/share/doc/nmap-3.50/README /usr/share/doc/nmap-3.50/copying.html /usr/share/doc/nmap-3.50/nmap-fingerprinting-article.txt /usr/share/doc/nmap-3.50/nmap.deprecated.txt /usr/share/doc/nmap-3.50/nmap.usage.txt /usr/share/doc/nmap-3.50/nmap_doc.html /usr/share/doc/nmap-3.50/nmap_manpage.html /usr/share/man/man1/nmap.1.gz /usr/share/nmap /usr/share/nmap/nmap-os-fingerprints /usr/share/nmap/nmap-protocols /usr/share/nmap/nmap-rpc /usr/share/nmap/nmap-service-probes /usr/share/nmap/nmap-services We find four sorts of files: -
The Nmap executable, /usr/bin/nmap -
Nmap documentation files, which live in /usr/share/doc/nmap -
The Nmap man page, /usr/share/man/man1/nmap.1.gz -
Nmap data files, which live in /usr/share/nmap 9.8.2 Determine the Security Contexts of the Files Next, let's see what security contexts are currently assigned: # ls -Z /usr/bin/nmap -rwxr-xr-x+ root root system_u:object_r:traceroute_exec_t /usr/bin/nmap # ls -Z /usr/share/doc/nmap-3.50/ -rw-r--r--+ root root system_u:object_r:usr_t COPYING -rw-r--r-- root root system_u:object_r:usr_t copying.html -rw-r--r-- root root system_u:object_r:usr_t nmap.deprecated.txt -rw-r--r-- root root system_u:object_r:usr_t nmap_doc.html -rw-r--r-- root root system_u:object_r:usr_t nmap-fingerprinting- article.txt -rw-r--r-- root root system_u:object_r:usr_t nmap_manpage.html -rw-r--r-- root root system_u:object_r:usr_t nmap.usage.txt -rw-r--r-- root root system_u:object_r:usr_t README # ls -Z /usr/share/man/man1/nmap.1.gz -rw-r--r--+ root root system_u:object_r:man_t /usr/share/man/man1/nmap.1.gz # ls -Z /usr/share/nmap/ -rw-r--r-- root root system_u:object_r:traceroute_t nmap-os-fingerprints -rw-r--r-- root root system_u:object_r:traceroute_t nmap-protocols -rw-r--r--+ root root system_u:object_r:traceroute_t nmap-rpc -rw-r--r-- root root system_u:object_r:traceroute_t nmap-service-probes -rw-r--r-- root root system_u:object_r:traceroute_t nmap-services 9.8.3 Decide on Appropriate Security Contexts for the New Domain Files having the usr_t and man_t types are readable by ordinary users, but writable only by privileged users. So it appears that the documentation files and the man page have reasonable security contexts. Let's establish new contexts for the executable and data files. We'll use nmap_t as the type of the data files and nmap_exec_t as the type of the executable. 9.8.4 Create a Basic TE File To assign the proper security contexts, let's first create a simple TE file, domains/program/nmap.te : ################################# # # Rules for the nmap_t domain. # # nmap_t is the domain for the nmap program. # nmap_exec_t is the type of the corresponding program. # type nmap_t, domain; type nmap_exec_t, file_type, sysadmfile, exec_type; Our TE file currently does nothing more than define the types we'll use to properly label the files related to the domain. We'll add additional declarations later. In particular, we'll add a declaration that allows processes executing nmap_exec_t programs to transition to the nmap_t domain. We'll also add declarations that specify the operations processes in the nmap_t domain are authorized to perform and the operations that other domains can perform on nmap_t objects. Like the nmap_t domain, most domains have at least two associated types: one associated with the domain itself and one used as an entry point to the domain. Many domains have additional types used to restrict permissions further. 9.8.5 Create a Basic FC File Next, let's create the FC file, file_contexts/program/nmap.fc : # nmap /usr/bin/nmap -- system_u:object_r:nmap_exec_t /usr/share/nmap.* system_u:object_r:nmap_t When the filesystem is labeled, the FC file will cause the Nmap program and its associated documentation files to be assigned the specified contexts. 9.8.6 Delete Conflicting Specifications from Other FC Files Conflicting FC specifications could result in incorrectly labeled files. To avoid conflicts, let's remove the following extraneous lines from the traceroute.fc file: /usr/bin/nmap -- system_u:object_r:traceroute_exec_t /usr/share/nmap.* system_u:object_r:traceroute_t 9.8.7 Load the Revised Policy and Label the Domains Now, let's install our new policy and relabel the related files: # make load # setfiles file_contexts/file_contexts /usr/bin/nmap # setfiles file_contexts/file_contexts /usr/share/nmap # ls -dZ /usr/bin/nmap /usr/share/nmap/ -rwxr-xr-x+ root root system_u:object_r:nmap_exec_t /usr/bin/nmap drwxr-xr-x root root system_u:object_r:nmap_t /usr/share/nmap/ The output of the ls command verifies that the security contexts were correctly revised. 9.8.8 Test and Revise the TE and FC Files as Needed Now, let's try executing the Nmap command and see what sorts of errors arise: # id -Z root:sysadm_r:sysadm_t # nmap -sT 127.0.0.1 Starting nmap 3.50 ( http://www.insecure.org/nmap/ ) at 2004-06-01 13:49 PDT Interesting ports on bill-a31 (127.0.0.1): (The 1658 ports scanned but not shown below are in state: closed) PORT STATE SERVICE 22/tcp open ssh Nmap run completed -- 1 IP address (1 host up) scanned in 0.510 seconds When we run the program as system administrator, it appears to work fine. However, let's see what happens when we run the program as a user other than the administrator: # id -Z root:staff_r:staff_t # nmap -sT 127.0.0.1 Starting nmap 3.50 ( http://www.insecure.org/nmap/ ) at 2004-06-01 13:50 PDT Unable to find nmap-services! Resorting to /etc/services socket trobles in massping : Permission denied As you might expect, the program fails. Indeed, we should hope that it does so, because otherwise SELinux would not be properly enforcing its policies. Let's discover what's necessary to coax our new nmap_t domain into working for a nonadministrative user. First, let's examine the system log for relevant AVC messages. We find a message similar to the one we found in the situation described in the preceding section: avc: denied { create } for pid=9533 exe=/usr/bin/nmap scontext=root:staff_r:staff_t tcontext=root:staff_r:staff_t tclass=rawip_socket Resolve the problem as we did earlier, by authorizing users in the staff_r role to access the domain. role staff_r types nmap_t; Also authorize an automatic type transition to nmap_t when the Nmap executable is loaded: domain_auto_trans(staff_t, nmap_exec_t, nmap_t) Again, load the revised policy and test the program. This time, it segfaults: # nmap -sT 127.0.0.1 Segmentation fault Inspecting the system log, we find the relevant AVC message: avc: denied { use } for pid=9607 exe=/usr/bin/nmap path=/dev/pts/1 dev= ino=3 scontext=root:staff_r:nmap_t tcontext=root:system_r:sshd_t tclass=fd This message indicates that the program was unable to access the pseudoterminal device, /dev/pts/1 . Recall that before moving Nmap to its own domain, it executed from the traceroute_t domain without problems. So the traceroute_t domain probably contains a declaration that authorizes access to the pseudoterminal. By studying the TE file for the traceroute_t domain, we discover the declaration needed in our new domain: allow traceroute_t privfd:fd use; Add the declaration, load the revised policy, and try again. The program appears to suffer from the same problem. But inspecting the system log turns up a new AVC message: avc: denied { read write } for pid=9661 exe=/usr/bin/nmap path=/dev/pts/1 dev= ino=3 scontext=root:staff_r:nmap_t tcontext=root:object_r:staff_devpts_t tclass=chr_file Now that Nmap can use the file descriptor, it needs read and write access to the related device file. Again consulting the TE file for traceroute_t , we discover and add a declaration authorizing read and write access to the terminal: allow nmap_t { ttyfile ptyfile }:chr_file rw_file_perms; This time, after loading the new policy, we obtain an unfamiliar error: # nmap -sT 127.0.0.1 nmap: error while loading shared libraries: libssl.so.4: cannot open shared object file: Permission denied This message indicates that our domain is unable to access shared libraries. Let's add a macro invocation that authorizes such access: uses_shlib(nmap_t) After loading the new policy, we obtain a somewhat familiar error: # nmap -sT 127.0.0.1 Starting nmap 3.50 ( http://www.insecure.org/nmap/ ) at 2004-06-01 21:21 UTC Unable to find nmap-services! Resorting to /etc/services Unable to open /etc/services for reading service information QUITTING! This resembles the error we encountered in the preceding section, when Nmap was unable to read /usr/share/nmap/nmap-services . However, now Nmap also seems unable to read /etc/services . Inspecting the system log uncovers related log entries: avc: denied { create } for pid=9821 exe=/usr/bin/nmap scontext=root:staff_r:nmap_t tcontext=root:staff_r:nmap_t tclass=unix_stream_socket avc: denied { read } for pid=9821 exe=/usr/bin/nmap name=localtime dev=dm-0 ino=32810 scontext=root:staff_r:nmap_t tcontext=system_u:object_r:locale_t tclass=file avc: denied { create } for pid=9821 exe=/usr/bin/nmap scontext=root:staff_r:nmap_t tcontext=root:staff_r:nmap_t tclass=unix_stream_socket avc: denied { read } for pid=9821 exe=/usr/bin/nmap name=nsswitch.conf dev=dm-0 ino=32811 scontext=root:staff_r:nmap_t tcontext=system_u:object_r:etc_t tclass=file avc: denied { read } for pid=9821 exe=/usr/bin/nmap name=passwd dev=dm-0 ino=34492 scontext=root:staff_r:nmap_t tcontext=system_u:object_r:etc_t tclass=file avc: denied { search } for pid=9821 exe=/usr/bin/nmap name=nmap dev=dm-4 ino=100533 scontext=root:staff_r:nmap_t tcontext=system_u:object_r:nmap_t tclass=dir avc: denied { search } for pid=9821 exe=/usr/bin/nmap name=root dev=dm-0 ino=262145 scontext=root:staff_r:nmap_t tcontext=root:object_r:staff_home_dir_t tclass=dir avc: denied { read } for pid=9821 exe=/usr/bin/nmap name=services dev=dm-0 ino=32797 scontext=root:staff_r:nmap_t tcontext=system_u:object_r:etc_t tclass=file Understanding how to resolve these errors might be overwhelming, were it not for our strategy of studying the domain traceroute_t . After some consideration, we settle on the following additional lines: can_network(nmap_t) allow nmap_t self:{ rawip_socket netlink_socket } create_socket_perms; allow nmap_t self:unix_stream_socket create_socket_perms; read_locale(nmap_t) allow nmap_t etc_t:file { getattr read }; allow nmap_t nmap_t:dir { search }; allow nmap_t nmap_t:file { getattr read }; The first line invokes a macro that generates declarations authorizing network access. The second and third lines authorize specific network operations ”namely, creating raw and stream sockets. The fourth line authorizes reading locale information, such as localtime . The fifth line authorizes access to etc_t files, such as nsswitch.conf . Finally, the sixth and seventh lines authorize access to nmap_t directories and files. Unfortunately, after loading the new policy, we discover that our work is not yet done: # nmap -sT 127.0.0.1 Starting nmap 3.50 ( http://www.insecure.org/nmap/ ) at 2004-06-01 14:36 PDT socket trobles in massping : Operation not permitted At least Nmap now prints a different error message. That's some indication of progress. Studying the system log turns up the following AVC messages: avc: denied { search } for pid=9972 exe=/usr/bin/nmap name=root dev=dm-0 ino=262145 scontext=root:staff_r:nmap_t tcontext=root:object_r:staff_home_dir_t tclass=dir avc: denied { search } for pid=9972 exe=/usr/bin/nmap name=root dev=dm-0 ino=262145 scontext=root:staff_r:nmap_t tcontext=root:object_r:staff_home_dir_t tclass=dir avc: denied { search } for pid=9972 exe=/usr/bin/nmap dev= ino=1 scontext=root:staff_r:nmap_t tcontext=system_u:object_r:proc_t tclass=dir avc: denied { net_raw } for pid=9972 exe=/usr/bin/nmap capability=13 scontext=root:staff_r:nmap_t tcontext=root:staff_r:nmap_t tclass=capability Our problems now seem to relate to accessing our home directory, which has type staff_home_dir_t ; accessing /proc ; and using special capabilities. Address the home directory problem by adding allow nmap_t staff_home_dir_t:dir {search }; To access the files within a directory, a process must be able to: So, to fix the problem accessing /proc , add: allow nmap_t proc_t:dir search; allow nmap_t proc_t:file { getattr read }; However, it's not necessary to be prescient. If we failed to authorize the getattr and read operations, Nmap would fail with an AVC message that would prompt us to authorize them. Finally, to authorize use of special capabilities, add: allow nmap_t nmap_t:capability { net_raw }; After compiling and loading the revised policy and testing Nmap, we find a new error message: # nmap -sT 127.0.0.1 Starting nmap 3.50 ( http://www.insecure.org/nmap/ ) at 2004-06-01 14:47 PDT pcap_open_live: socket: Permission denied There are several possible reasons for this, depending on your operating system: LINUX: If you are getting Socket type not supported, try modprobe af_packet or recompile your kernel with SOCK_PACKET enabled. *BSD: If you are getting device not configured, you need to recompile your kernel with Berkeley Packet Filter support. If you are getting No such file or directory, try creating the device (eg cd /dev; MAKEDEV <device>; or use mknod). SOLARIS: If you are trying to scan localhost and getting '/dev/lo0: No such file or directory', complain to Sun. I don't think Solaris can support advanced localhost scans. You can probably use "-P0 -sT localhost" though. QUITTING! It appears that our new domain lacks the ability to create sockets. A glance at the log confirms this hypothesis. Add a declaration authorizing the creation of sockets: allow nmap_t self:packet_socket create_socket_perms; After compiling and loading the policy, we find that Nmap now works correctly: # nmap -sT 127.0.0.1 Starting nmap 3.50 ( http://www.insecure.org/nmap/ ) at 2004-06-01 14:49 PDT Interesting ports on bill-a31 (127.0.0.1): (The 1658 ports scanned but not shown below are in state: closed) PORT STATE SERVICE 22/tcp open ssh Nmap run completed -- 1 IP address (1 host up) scanned in 0.473 seconds Because we implemented our domain iteratively, it may be hard to grasp the big picture. So that you can review the result of our effort, here's the complete TE file for the nmap_t domain: ################################# # # Rules for the nmap_t domain. # # nmap_t is the domain for the nmap program. # nmap_exec_t is the type of the corresponding program. # type nmap_t, domain; type nmap_exec_t, file_type, sysadmfile, exec_type; role staff_r types nmap_t; domain_auto_trans(staff_t, nmap_exec_t, nmap_t) allow nmap_t privfd:fd use; allow nmap_t { ttyfile ptyfile }:chr_file rw_file_perms; uses_shlib(nmap_t) can_network(nmap_t) allow nmap_t self:{ rawip_socket netlink_socket } create_socket_perms; allow nmap_t self:unix_stream_socket create_socket_perms; read_locale(nmap_t) allow nmap_t etc_t:file { getattr read }; allow nmap_t nmap_t:dir { search }; allow nmap_t nmap_t:file { getattr read }; allow nmap_t staff_home_dir_t:dir {search }; allow nmap_t proc_t:dir search; allow nmap_t proc_t:file { getattr read }; allow nmap_t nmap_t:capability { net_raw }; allow nmap_t self:packet_socket create_socket_perms; However, unless we're very lucky, we're not yet done. It's likely that additional testing will disclose other permissions that must be added to the TE file. You can now see why many SELinux policies work less than perfectly . Like almost all computer software, they're generally developed using a write-test-revise process that doesn't differ much from cut-and-try. Unusual inputs or circumstances can reveal the need for permissions that haven't been anticipated or provided. |