You don't always see what you want (... and how you configure it in Solaris)

Consider the following situation: You are tasked to update an application, to stop it, to start it, to change it’s configuration. You need access to the config files, to the binary. But the data processed by the application? You do not really need to see those parts. The application running with a the same user id needs to work with the data, the user id needs read and write privileges to the file. Ooviously. Hwever with the privilege to log in with the user id the application will run with you have access to the data as well. With Solaris 11.4 it doesn’t have to be that way, as we introduced File and Process labeling in this version. With this feature you can protect your files much better.

An example

I want to demonstrate it with a rather short example. Let’s assume we have an application importantapp running with the user id iappadm1 for “important app admin 1”. The location of the application is /export/importantapp.

root@server:~# zfs create rpool/export/importantapp
root@server:~# zfs set multilevel=on rpool/export/importantapp
root@server:~# useradd -m iappadm1
80 blocks
root@server:~# passwd iappadm1
New Password:
Re-enter new Password:
passwd: password successfully changed for iappadm1 


In my demonstration your application is a simple shell script.

root@server:~# cat /export/importantapp/binary
 #!/bin/bash
id >> /tmp/narf
date >> /tmp/narf
plabel >> /tmp/narf
ls -l /export/importantapp >> /tmp/narf


It just dumps the userid, the time of execution, the label imposed to our binary and what files are visible to the application Into a file. Now let’s create a file that poses as our datafile and a smaller file posing as our configfile.

root@server:~# mkfile 10k /export/importantapp/datafile
root@server:~# mkfile 1k /export/importantapp/configfile


We want to „run“ this with the user id iappadm1, so we have to change a number of things with the rights and ownership. To make life easier, we assign /export/importantapp as a home directory to the user iappadm1

root@server:~# chown -R iappadm1 /export/importantapp
root@server:~# usermod -d /export/importantapp iappadm1
root@server:~# touch /tmp/narf
root@server:~# chmod 666 /tmp/narf


Let’s check if everything is in place.

root@server:/export/importantapp# ls -l
total 26
-rwxr-xr-x   1 iappadm1 root         107 März  2 23:21 binary
-rw———   1 iappadm1 root        1024 März  2 22:49 configfile
-rw———   1 iappadm1 root       10240 März  2 22:49 datafile


Now assign labels to this files.

root@server:/export/importantapp# setlabel „Confidential - Restricted“ binary
root@server:/export/importantapp# setlabel "Confidential - Restricted" configfile
root@server:/export/importantapp# setlabel "Confidential - Highly Restricted" datafile


We assigned a “Confidential - Restricted” to the binary and the configfile, however we assigned a “Confidential - Highly Restricted” to the datafile. The next step is to assign a clearance to the user iappadm1

root@server:/export/importantapp# usermod -K clearance="Confidential - Restricted" iappadm1


We are essentially telling the system, that the user iappadm1 has the clearance „Confidential - Restricted“. As you may remember from this blog entry this means two things. The user can see documents with the Classification “Confidential” and lower and with the compartment „Restricted“. It can’t see files with the compartment Highly Restricted“. Before we start to test our configuration, let’s do some other checks if the labels found their way to the files.

root@server:/export/importantapp# getlabel binary
binary: Confidential - Restricted
root@server:/export/importantapp# getlabel datafile
datafile:       Confidential - Highly Restricted
root@server:/export/importantapp# getlabel configfile
configfile:     Confidential - Restricted


Okay, looks right. We now log into our system as iappadm1 and execute our binary.

MacBook-Pro:~ jmoekamp$ ssh iappadm1@10.0.10.2
Password:
Last login: Fri Mar  2 22:55:35 2018 from 10.0.10.1
Oracle Corporation      SunOS 5.11      11.4.Beta       January 2018

$ ./binary
$ cat /tmp/narf
[…]
uid=1114(iappadm1) gid=10(staff)
Freitag,  2. März 2018 um 23:39:54 Uhr UTC
Confidential - Restricted
total 5
-rwxr-xr-x   1 iappadm1 root         107 März  2 23:21 binary
-rw———   1 iappadm1 root        1024 März  2 22:49 configfile


As you see, when we execute it on the shell, the script has run with iappadm1, the process had the clearance Confidential - Restricted. The great part is a missing part. You don’t see the datafile. Despite based all of thre relevant files are owned by iappadm1:root The user can log in, can change the binary, can change the config file but it can’t see the datafile.

Now lets make an SMF service for our binary. It will be only a transient service. The service is automatically enabled.

root@server:/export/importantapp# svcbundle -I -s service-name=testing/labeledsvc -s start-method=/export/importantapp/binary
Waiting for testing/labeledsvc to reach online state.
It is safe to interrupt.
root@server:/export/importantapp# cat /tmp/narf
[…]
id=0(root) gid=0(root)
Friday, March  2, 2018 at 11:21:51 PM UTC
ADMIN_HIGH
total 26
-rwxr-xr-x   1 iappadm1 root         107 Mar  2 23:21 binary
-rw———   1 iappadm1 root        1024 Mar  2 22:49 configfile
-rw———   1 iappadm1 root       10240 Mar  2 22:49 datafile


Tada … when the binary is started as a SMF services, it sees the datafile. Okay, it’s running as root. Root has the clearance ADMIN_HIGH per default (and don’t dare to change that). Of course it’s able to see all files. Okay, let’s change that: The SMF will now start our binary with the user id iappadm1:

root@server:/export/importantapp# svccfg -s testing/labeledsvc
sac:/testing/labeledsvc> setprop start/user = astring: iappadm1
svc:/testing/labeledsvc> refresh
svc:/testing/labeledsvc> exit
root@server:/export/importantapp# svcadm restart testing/labeledsvc
root@server:/export/importantapp# cat /tmp/narf
[…]
uid=1114(iappadm1) gid=10(staff)
Friday, March  2, 2018 at 11:27:07 PM UTC
ADMIN_HIGH
total 26
-rwxr-xr-x   1 iappadm1 root         107 Mar  2 23:21 binary
-rw———   1 iappadm1 root        1024 Mar  2 22:49 configfile
-rw———   1 iappadm1 root       10240 Mar  2 22:49 datafile


Hey, it runs with the user id iappadm1 and you see all three files. But wait a moment. Of course it sees al the files. It still runs with the clearance ADMIN_HIGH. Why? We configured the user explicitly with a different clerance. What did happen? Well. SMF ist starting every SMF service with a default clearance and this default clearance is ADMIN_HIGH. ADMIN_HIGH dominates everything you may use as a label on your files. This default is part of the fact, that the default configuration of labeling doesn’t change the default behaviour of your system. Binary compatibility at work. So we have to change that as well for our service.

root@server:/export/importantapp# atohexlabel „Confidential - Highly Restricted“
0x0002-08-e0
root@server:/export/important-app# svccfg -s testing/labeledsvc
svc:/testing/labeledsvc> setprop start/clearance = astring: 0x0002-08-e0
svc:/testing/labeledsvc> refresh
svc:/testing/labeledsvc> exit
root@server:/export/importantapp# svcadm restart testing/labeledsvc
root@server:/export/importantapp# cat /tmp/narf
[…]
uid=1114(iappadm1) gid=10(staff)
Saturday, March  3, 2018 at 01:46:42 AM UTC
Confidential - Highly Restricted
total 26
-rwxr-xr-x   1 iappadm1 root         107 Mar  2 23:21 binary
-rw———   1 iappadm1 root        1024 Mar  2 22:49 configfile
-rw———   1 iappadm1 root       10240 Mar  2 22:49 datafile


We have to convert our label at first to an internal representation of it. Then we put this internal representation into the SMF property start/clearance. Now restart the service. User iappadm1? Check! Sees all three files? Check! And it runs with the clearance Confidential Restricted.

Real life

Obviously this simple example has an important shortfall … you could simply change the binary so it gives you the datafile. So you could make the binary highly restricted as well thus a interactive user just could modify the configuration of the system. However this example was more about an easy example using labels with SMF and users than to have an real life ready to use example.

Conclusion

With the use of labels it’s really easy to isolate data even better than compared to conventional mechanisms. It’s even possible to isolate an interactive user from the application, even when both are using the same user id.