Info: Version 1.8.x is available.
Last modified: $Date: 2024-03-31 15:45:12 +0000 (Sun, 31 Mar 2024) $
By now in this series, I explained access control on files. Access control on files prevents accessing unnecessary programs and data files and plays basic role for improving security using secure OS. But access control on files alone is not sufficient. In this installment, I explain major access controls which TOMOYO Linux provides, mainly access control on networks.
By default, Linux provides iptables for doing packet filtering. TOMOYO Linux provides similar functionality, but TOMOYO Linux's access control on networks can perform packet filtering for per TOMOYO Linux's domain and per user ID basis, and easy to configure. You can use TOMOYO Linux's access control on networks even if iptables is too difficult for you to configure. (But note that there are functionalities which iptables can provide but TOMOYO Linux can't provide, for TOMOYO Linux is independent with iptables.)
Coverage of TOMOYO Linux's access control on networks is shown in Fig. 1.
♦ Fig. 1 Coverage of access control on networks
TCP protocol / UDP protocol / IP protocol IPv4 network address / IPv6 network address Port number (for TCP and UDP) / Protocol number (for IP) |
By using TOMOYO Linux's access control on networks, you can allow, for example, svn command which is executed by a user whose user ID is 500 and who logged in via /usr/sbin/sshd can communicate with port 80 on host 202.221.179.11 using TCP protocol. I explain steps to configure in following sections.
You can specify access control on networks for per a domain basis like access control on files. For this installment, I create 3 profiles for "a profile for learning mode for network only" "a profile for permissive mode for network only" "a profile for enforcing mode for network only".
As a preparation for access control on network, create profile 5 to 7. Append lines listed in Fig. 2 to the bottom of /etc/ccs/profile.conf .
♦ Fig. 2 Lines to be appended to /etc/ccs/profile.conf
5-COMMENT=Learning Mode (Network Only) 5-CONFIG::network={ mode=learning } 6-COMMENT=Permissive Mode (Network Only) 6-CONFIG::network={ mode=permissive } 7-COMMENT=Enforcing Mode (Network Only) 7-CONFIG::network={ mode=enforcing } |
Save the file and then reflect the changes by doing command in Fig. 3.
♦ Fig. 3 Reflect the changes
# /usr/sbin/ccs-loadpolicy p |
Target domains for applying access control on network are arbitrary. In this installment, I choose domains under currently operating shell sessions as target domains. You can see the domain which current process belongs to by doing "/bin/cat < /proc/ccs/self_domain". If the domain which currently operating shell sessions belong is specified using "keep_domain" keyword, delete the "keep_domain" keyword for this section using policy editor. (This is just for making it easier for you to understand. You don't need to delete "keep_domain" keyword when you apply on actual environment.) Note that the IP addresses and port numbers learned may differ depending on your environment.
Change a domain which current process belongs to and its descendent domains to learning mode by doing commands listed in Fig. 4. (You may specify actual domainname as string parameter instead of redirection.)
♦ Fig. 4 Change a domain which current process belongs to and its descendent domains to learning mode
# xargs -0 /usr/sbin/ccs-setprofile -r 5 < /proc/ccs/self_domain |
As an example command that uses networks, let's access http://www.osdn.jp/ using /usr/bin/curl command. (Fig. 5)
♦ Fig. 5 Execute /usr/bin/curl command
# curl http://www.osdn.jp/ > /dev/null |
If /usr/bin/curl command is not available, you can use other commands like /usr/bin/wget command or /usr/kerberos/bin/telnet command. Run the policy editor and browse permissions for the domain for /usr/bin/curl command. (Fig. 6)
♦ Fig. 6 Policy configuration for a domain for /usr/bin/curl command |
Lines starting with "allow_network" keyword are permissions for access control on networks. "allow_network UDP connect 192.168.1.2 53" allows communicating with port 53 (i.e. DNS service) on host 192.168.1.2 using UDP protocol. Also, "allow_network TCP connect 202.221.179.11 80" allows communicating with port 80 (i.e. HTTP service) on host 202.221.179.11 (this is IP address for www.osdn.jp as of this writing) using TCP protocol.
In this section, let's login to SSH service using /usr/bin/ssh command. (If you don't have SSH service, you can use other services like HTTP.) If "initialize_domain /usr/sbin/sshd" is specified in the exception policy (it should be specified by init_policy command which I executed in the first installment of this series), /usr/sbin/sshd runs in the "<kernel> /usr/sbin/sshd" domain. Thus, assign a profile for learning mode to the "<kernel> /usr/sbin/sshd" domain. (Fig. 7)
♦ Fig. 7 Assign a profile for learning mode to "<kernel> /usr/sbin/sshd" domain
# /usr/sbin/ccs-setprofile 5 '<kernel> /usr/sbin/sshd' |
Then, login to localhost using ssh command (Fig. 8) and run the policy editor and browse permissions for "<kernel> /usr/sbin/sshd" domain. (Fig. 9)
♦ Fig. 8 Login to localhost using ssh command
# ssh localhost |
♦ Fig. 9 Policy configuration for "<kernel> /usr/sbin/sshd" domain |
"allow_network TCP accept 0:0:0:0:0:ffff:7f00:1 34561" allows accepting TCP connections from port 34561 on host (IPv6 address) 0:0:0:0:0:ffff:7f00:1.
You can apply conditions to permissions for access control on networks as well as permissions for access control on files. For example, you can restrict remote server's IP addresses based on user ID by using process's user ID as conditions. (Fig. 10)
♦ Fig. 10 Restricting remote servers based on user ID
allow_network TCP connect 202.221.179.11 80 if task.uid=500 allow_network TCP connect 66.35.250.203 80 if task.uid=501 |
Regarding IP sockets, you specify protocol number instead of port number. I explain using ping command as an example. Execute command in Fig. 11 and then execute the policy editor and browse permissions for the domain for ping command. (Fig. 12)
♦ Fig. 11 Executing ping command
# ping -c 4 www.osdn.jp |
♦ Fig. 12 Policy configuration for the domain for ping command |
You can see a line "allow_network RAW connect 202.221.179.11 1". Fig. 12 shows that the domain which ping command is running is allowed to communicate with host 202.21.179.21 using IP sockets with protocol number 1 (i.e. ICOMP).
After you let TOMOYO Linux learn permissions, verify the permissions using permissive mode. Assign profile 6 to change to permissive mode. (Fig. 13)
♦ Fig. 13 Change to permissive mode by assigning profile 6
# xargs -0 /usr/sbin/ccs-setprofile -r 6 < /proc/ccs/self_domain |
You need to patternize IP address ranges for doing access control on networks as well as you patternized file's pathnames for doing access control on files. To patternize IP addresses, specify address ranges using "StartAddress-EndAddress" format like Fig. 14. No space is permitted around "-".
♦ Fig. 14 Specifying IPv4 address ranges
xxx.xxx.xxx.xxx-yyy.yyy.yyy.yyy |
You can specify IPv6 address as well as IPv4 address. But "::" and "." are not supported for IPv6 address. You need to specify IPv6 address using format like Fig. 15. Also, be sure to specify all possible IP addresses if target servers has multiple IP addresses (e.g. load balancing).
♦ Fig. 15 Specifying IPv6 address
xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx |
Generally, the port number which servers use for accepting connections from clients are fixed, but the port number which clients use for establishing connections with servers are not fixed. Therefore, you need to specify possible port number ranges which clients might use when giving permissions to server side programs. To patternize, specify port number ranges using "StartPort-Endport" format like Fig. 16. No space is permitted around "-". Three patterns listed in Fig. 17 are port number ranges frequently used.
♦ Fig. 16 Specifying port number ranges
xxxxx-yyyyy |
♦ Fig. 17 Frequently used port number ranges
1024-65535 32768-61000 600-1023 |
The first pattern is for port numbers which normal client programs choose when establishing connections with server programs, and you likely specify this range for server programs. The second pattern is for port numbers which are specified in /proc/sys/net/ipv4/ip_local_port_range . Normal client programs choose an unused port from this range when establishing connections with server programs, and you likely specify this range for client programs. Check /proc/sys/net/ipv4/ip_local_port_range when determining the second pattern.
The last pattern is for port numbers used by programs like portmap command which require privileged port numbers (port numbers smaller than 1024) for communication. The actual port numbers required by such programs may be different. The easy way for determining whether patternizing port numbers are necessary or not is to execute programs for several times. For example, permissions with contiguous port numbers like Fig. 18 will be appended by learning mode. Thus, guess required port number ranges from the result of learning mode.
♦ Fig. 18 Example of permissions with contiguous port numbers
allow_network TCP bind 127.0.0.1 610 allow_network TCP bind 127.0.0.1 611 allow_network TCP bind 127.0.0.1 612 allow_network TCP bind 127.0.0.1 613 |
If you find permissions in Fig. 18, you likely need permissions in Fig. 19.
♦ Fig. 19 Patternized permissions based on Fig. 18
allow_network TCP bind 127.0.0.1 600-1023 |
If you find permissions in Fig. 20, you likely need permissions in Fig. 21 or Fig. 22.
♦ Fig. 20 Example of permissions with contiguous port numbers
allow_network TCP accept 127.0.0.1 32780 allow_network TCP accept 127.0.0.1 32781 allow_network TCP accept 127.0.0.1 32782 allow_network TCP accept 127.0.0.1 32783 allow_network TCP accept 127.0.0.1 32784 |
♦ Fig. 21 Patternized permissions based on Fig. 20
allow_network TCP accept 127.0.0.1 1024-65535 |
♦ Fig. 22 Patternized permissions based on Fig. 20
allow_network TCP accept 127.0.0.1 32768-61000 |
When you became sure that you gave enough permission, let's enforce access control on networks. Assign profile 7 to change to enforcing mode. (Fig. 23)
♦ Fig. 23 Change to enforcing mode by assigning profile 7
# xargs -0 /usr/sbin/ccs-setprofile -r 7 < /proc/ccs/self_domain |
Note that profile 5 to 7 does not perform access control on files. By using ccs-queryd which I explained in the fourth installment of this series, you can interactively append missing permissions. I think you understood that you can break access control on networks provided by iptables by using TOMOYO Linux.
Linux kernel 2.2 and later supports POSIX capabilities. Capabilities realize secure OS's basic concept "least privileges" and are used for restricting use of various privileged operations for per a process basis. You can find list of capabilities which Linux supports in /usr/include/linux/capability.h . However, since CAP_SYS_ADMIN privilege is used for various purposes, we cannot expect fine grained restriction. Therefore, TOMOYO Linux defined and uses original capabilities. (Hereafter, capabilities refers to TOMOYO Linux's capabilities rather than POSIX's capabilities.)
While TOMOYO Linux uses original capabilities that are not compatible with POSIX capabilities, TOMOYO Linux's capabilities are not visible from userland applications. Thus, you don't need to modify userland programs. TOMOYO Linux 1.7.4 uses capabilities listed in Fig. 24.
♦ Fig. 24 Capabilities defined in TOMOYO Linux 1.7.4
|
In this section, I explain about privilege for doing mount operation (i.e. SYS_MOUNT ) as an example. Since TOMOYO Linux performs access control using pathnames, it is an absolutely important assumption that filesystems are mounted as the administrator intended. It is annoying thing if any processes running as "root" user can freely mount filesystems. Thus, by using capabilities, you can restrict domains which can do mount operations. Steps for doing access control on capabilities are the same with doing access control on networks. Firstly, specify capabilities you want to control in the profiles. Append lines listed in Fig. 25 to the bottom of /etc/ccs/profile.conf .
♦ Fig. 25 Lines to be appended to /etc/ccs/profile.conf
9-CONFIG::capability::SYS_MOUNT={ mode=learning } 10-CONFIG::capability::SYS_MOUNT={ mode=enforcing } |
Unlike files and networks, capabilities do not have operands. All necessary capabilities are given by simply using learning mode. Thus, a profile for permissive mode is omitted in Fig. 25. Save the file and then reflect the changes by doing command in Fig. 3.
For explanation, I firstly use a profile for enforcing mode. (Fig. 26)
♦ Fig. 26 Assign a profile for enforcing mode
# xargs -0 /usr/sbin/ccs-setprofile -r 10 < /proc/ccs/self_domain |
Then, mount tmpfs somewhere. (Fig. 27)
♦ Fig. 27 Mounting tmpfs
# mount -t tmpfs none /tmp/ mount: permission denied |
The mount operation was rejected. This is because the domain which mount command belongs to was not given a capability for doing mount operation. Next, assign a profile for learning mode. (Fig. 28)
♦ Fig. 28 Assign a profile for learning mode
# xargs -0 /usr/sbin/ccs-setprofile -r 9 < /proc/ccs/self_domain |
Again, mount tmpfs somewhere. (Fig. 29)
♦ Fig. 29 Mounting tmpfs
# mount -t tmpfs none /tmp/ |
This time, the mount operation succeeded. Run the policy editor and find the domain for mount command and browse permissions for that domain. (Fig. 30)
♦ Fig. 30 Permission "allow_capability SYS_MOUNT" was learned |
You can find that a permission "allow_capability SYS_MOUNT" was learned. Now, you can forbid mount operations from domains without SYS_MOUNT capability by assigning a profile for enforcing mode.
You might notice that it is not sufficient to restrict whether mount operation is permitted or not , for the process can do arbitrary mount operations if mount operation is permitted. In fact, that is true. TOMOYO Linux's access control on files includes ability to restrict the combination of mount device and mount point and filesystem type and mount flags. Thus, if you do operations listed in Fig. 29 with a profile for learning mode for access control on files, "allow_mount none /tmp/ tmpfs 0" will appear in Fig. 30.
TOMOYO Linux can do access control on signal numbers and signal targets. Steps for doing access control on signals are the same with doing access control on networks. Append lines listed in Fig. 31 to the bottom of /etc/ccs/profile.conf .
♦ Fig. 31 Lines to be appended to /etc/ccs/profile.conf
11-CONFIG::ipc::signal={ mode=learning } 12-CONFIG::ipc::signal={ mode=enforcing } |
Save the file and then reflect the changes by doing command in Fig. 3.
I assume below operations are done from "<kernel> /usr/sbin/sshd /bin/bash" domain (i.e. login shell executed by /usr/sbin/sshd ). Make sure that "keep_domain <kernel> /usr/sbin/sshd /bin/bash" is not specified in the exception policy. Firstly, execute /bin/sleep command. (Fig. 32)
♦ Fig. 32 Execute /bin/sleep
# sleep 100 |
At this state, open another window and login to the system. For explanation, I firstly use a profile for enforcing mode. (Fig. 33)
♦ Fig. 33 Assign a profile for enforcing mode
# xargs -0 /usr/sbin/ccs-setprofile -r 12 < /proc/ccs/self_domain |
Then, get the process ID of running /bin/sleep command and send a signal to that process ID. (Fig. 34. Use external /bin/kill command rather than shell's built-in kill command.)
♦ Fig. 34 Send signal to process ID of /bin/sleep command
# pidof sleep 4649 # /bin/kill -15 4649 kill 4649: Operation not permitted |
The kill operation was rejected. This is because the domain which /bin/kill command belongs to was not given permission for sending signals. Next, assign a profile for learning mode (Fig. 35) and resend the signal. (Fig. 36)
♦ Fig. 35 Assign a profile for learning mode
# xargs -0 /usr/sbin/ccs-setprofile -r 11 < /proc/ccs/self_domain |
♦ Fig. 36 Send signal to process ID of /bin/sleep command again
# /bin/kill -15 4649 |
This time, signal operation succeeded. Run the policy editor and find the domain for kill command and browse permissions for that domain. (Fig. 37)
♦ Fig. 37 Permissions given to the domain for kill command |
You can find a permission "allow_signal 15 <kernel> /usr/sbin/sshd /bin/bash /bin/sleep" was learned. This permission allows sending signal 15 (i.e. SIGTERM) to "<kernel> /usr/sbin/sshd /bin/bash /bin/sleep" domain and its descendent domains. Since TOMOYO Linux's domains forms hierarchal structure starting with "<kernel>", "allow_signal 15 <kernel>" will allow sending signal 15 to any processes. Also, as exceptions, sending signals to the same domain (e.g. threads in current process) is always permitted, and sending signal 0 is always permitted.
In this installment, I explained mainly access control on networks. I think you understood that you can restrict domains that can use networks and apply powerful and flexible access controls using TOMOYO Linux. In the next installment, I explain steps for restricting login sessions. Don't miss it!
Go back to the sixth installment. Proceed to the eighth installment.