9.8 Creating a New Domain
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 TE file.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:Test the program.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 nmapWe find four sorts of files:The Nmap executable, /usr/bin/nmapNmap documentation files, which live in
/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/copyingl
/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_docl
/usr/share/doc/nmap-3.50/nmap_manpagel
/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
/usr/share/doc/nmapThe Nmap man page, /usr/share/man/man1/nmap.1.gzNmap 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 copyingl
-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_docl
-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_manpagel
-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:
#################################Our TE file currently does nothing more than define the types
#
# 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;
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:
# nmapWhen the filesystem is labeled, the FC file will cause the Nmap
/usr/bin/nmap -- system_u:object_r:nmap_exec_t
/usr/share/nmap.* system_u:object_r:nmap_t
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 loadThe output of the ls command verifies that the
#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/
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 -ZWhen we run the program as system administrator, it appears to work
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
fine. However, let's see what happens when we run
the program as a user other than the administrator:
#id -ZAs you might expect, the program fails. Indeed, we should hope that
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
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_socketResolve 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.1Inspecting the system log, we find the relevant AVC message:
Segmentation fault
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=fdThis 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_fileNow 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.1This message indicates that our domain is unable to access shared
nmap: error while loading shared libraries: libssl.so.4: cannot open shared object file: Permission denied
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.1This resembles the error we encountered in the preceding section,
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!
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_socketUnderstanding how to resolve these errors might be overwhelming, were
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
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)The first line invokes a macro that generates declarations
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 };
authorizing network access. The second and third lines authorize
specific network operationsnamely, 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.1At least Nmap now prints a different error message.
Starting nmap 3.50 ( http://www.insecure.org/nmap/ ) at 2004-06-01 14:36 PDT
socket trobles in massping : Operation not permitted
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=dirOur problems now seem to relate to accessing our home directory,
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
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:Search the directory.Get the attributes of, and read, the files contained in the directory.
So, to fix the problem accessing /proc, add:
allow nmap_t proc_t:dir search;However, it's not necessary to be prescient. If we
allow nmap_t proc_t:file { getattr read };
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.1It appears that our new domain lacks the ability to create sockets. A
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!
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.1Because we implemented our domain iteratively, it may be hard to
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
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:
#################################However, unless we're very lucky,
#
# 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;
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.