Labeled Sandboxes

One of the reasons why I was that silent here the last year even when Solaris 11.4 was introduced was the situation, that my colleague Detlef Drewanz and I created a large presentation about Solaris 11.4. 170 slides packed with new features (I think I have now enough new features in examples to warrant a new version of the presentation). A presentation that found a lot of reuse. In this presentation I needed something to demonstrate sandboxes and file/process labeling in one go. The presentation already was 3-4 hours long and consolidating some demonstration would be really useful not to break through the 5 hours limit.

Then i remembered a comment of Glenn Faden, who talked about this feature on an engineering conference (in 2014 i think) in Santa Clara and made an important statement. I don’t remember his exact words, but it was along the lines that it didn’t suffice to have security feature, they must be simple to use, because otherwise nobody would use them and no security would be won.

So the example should be fast to set up, unproblematic to set up in order to prevent non-working demonstrations and should show the feature, and it must show the simplicity to use it. This is what I came up with (yes, I know, there are other ways to do this, however i think it’s really simple this way.

I won’t explain sandboxes or file labeling. I leave this to the documentation, or a later blog entry. Just think of sandboxes of a way to jail in applications in their own set of privileges without the need for zones and process/file labeling as an access control mechanism on top of the discretionary access control (you know, rwxrwxrwx ). Yeah, vastly oversimplified, but that should suffice for now.

Demonstration of the feature

Let’s assume you have a directory with a lot of company information. You want to keep all information at one place. However you want to give access to this data via a webserver and not all web server should show all the contents. Perhaps you want to ensure that based on the port number the servers show different content.

We still have some preparations do to. In order to work with file labeling we have to enable the ZFS filesystem to work with labels. This is really simple. As soon as the filesystem has set the property multilevel to on, you can use labels.

root@solaris:~# zfs create rpool/export/importantapp
root@solaris:~# zfs set multilevel=on rpool/export/importantapp

By configuring this, labeling will be used in the filesystem. Keep in mind that the whole file and process labeling stuff is configured per default in a way, that stays totally out of the way. So when you activate this, nothing visible to you or the processes will change.

Before you ask, the label is part of the metadata of the filesystem. You can see them with zdb:

root@solaris:~# zdb –ddddddd rpool/export/importantapp 
Object  lvl   iblk   dblk  dsize  lsize   %full  type
         9    1    16K  20.0K  20.0K  20.0K  100.00  ZFS plain file
                                        189   bonus  System attributes
        dnode maxblkid: 0
        path    /businessplan.pdf
        uid     102
        gid     0
        atime   Tue Aug 14 20:45:17 2018
        mtime   Tue Aug 14 20:45:17 2018
        ctime   Tue Aug 14 20:50:30 2018
        crtime  Tue Aug 14 20:45:17 2018
        gen     21538
        mode    0100600
        size    20480
        parent  4
        links   1
        pflags  0x40800000204
        mac_label       <strong>0x0002-08-e0</strong>

We have now to do some additional preparations. Creating a user, creating some files.

root@solaris:~# useradd -m pyws
80 blocks
root@solaris:/export/importantapp# mkfile 20k businessplan.pdf
root@solaris:/export/importantapp# mkfile 20k constructionblueprints.pdf
root@solaris:/export/importantapp# mkfile 20k bus_schedule.pdf
root@solaris:/export/importantapp# chown -R pyws /export/importantapp

And now the labeling part begins. Technically you are setting two things here. You set a compartment and a classification. Classification is rather simple to explain. You know the classic hierarchy perhaps from the military, the one that pinnacles usually in Top Secret. It defines on what level you are trusted. As the word hierarchy implies it means as well, if you have a clearance of “Top Secret” in means that you can see all objects that are classified at the level “Top Secret or Lower”. In Solaris it’s represented by an integer. If the integer of your clearance is higher or equal to the one in the label, you are allowed to access the data from the perspective of the classification.

There are some default classifications. Let’s check them

root@batou:/# labelcfg
labelcfg:label_encodings.default> info classification
classification=Confidential -

The second part is the compartment. It defines which areaof information the trust applies to. Just you are trusted to see the top secret HR data doesn’t mean that you are trusted to see the top secret engineering data and vice versa. Just because the chef trusts you the secret recipe for his soup, doesn’t mean that he trusts you with the list of the ingredients of the sausages. Compartments allow you do express such kind of information. It’s represented in Solaris with a bitmap. If the the same bit in the label and the clearance is set, you are allowed to access from the compartment point of view.

labelcfg:label_encodings.default> info compartment
compartment=Highly Restricted
	minclass=Confidential -
	minclass=Confidential -
	minclass=Confidential -

I used the word clearance before: What is this ? The clearance is the the combination of classification and compartment a user holds and only when the clearance is matches the classification (equal or better) and the compartment (the compartment in the label and the clearance have to match , subcompartments make this more complex, but just forget this now. Matching means that the same bit in the clearance and the label has to be set.)

This mechanism sits on top of the normal access control. When you don’t have read privileges on a file, you can’t read it, even when you have the matching clearance. It doesn’t override that setting. However it allows you to do a fine grain access control for separate processes even when they are running under the same user id.

In this example for the sake of simplicity I will just use the default set of label/clearances and use just one classification and three compartments.

root@solaris:/export/importantapp# setlabel "Confidential - Internal" bus_schedule.pdf
root@solaris:/export/importantapp# setlabel "Confidential - Restricted" constructionblueprints.pdf
root@solaris:/export/importantapp# setlabel "Confidential - Highly Restricted" businessplan.pdf

Now I set the attributes of the user pyws I configured it so the user has the clearance “Confidential - Highly Restricted”:

root@solaris:/export/importantapp# usermod -K clearance="Confidential - Highly Restricted" pyws

I’m changing now into this new user in order to do the core part of the demonstration.

root@solaris:/export/importantapp# su - pyws
Oracle Corporation      SunOS 5.11      Solaris_11/11.4/ON/  June 2018

As setting up three separate instances of Apache in SMF takes a bit of time, I will use the SimpleHTTPServer in Python (which explains why the username is pyws). It simply presents contents the directory you are in when starting it.

pyws@solaris:/export/importantapp$ sandbox -l "Confidential - Internal" nohup python -m SimpleHTTPServer 8000 \&amp;
pyws@solaris:/export/importantapp$ sandbox -l "Confidential - Restricted" nohup python -m SimpleHTTPServer 8001 \&amp;
Sending output to nohup.out
pyws@solaris:/export/importantapp$ sandbox -l "Confidential - Highly Restricted" nohup python -m SimpleHTTPServer 8002 \&amp;
Sending output to nohup.out

And here the sandboxing kicks in. I start each of the processes in a different sandbox. I start the first webserver in a sandbox with the clearance “Confidential - Internal” that listens on port 8000, the second webserver is started in a sandbox with the clearance “Confidential - Restricted” bound to port 8001 and the last one is started on port 8002 running with a clearance of “Confidential - Highly Restricted”.
Now start your favorite browser and try it out. At first connect to port 8000. You will see just one file.

Try it again with port 8001, you will see a different set of files.

Only when you connect to the third webserver on port 8002 you will see all the files.

I left the directory with it’s standard label of ADMIN_LOW. As this is dominated by all clearance, all webserver processes can see the nohup.out file.

Despite all processes are running on the same user id and all files are owned by the same user and group, we can start processes that just see a subset of them. And now think of this in terms of application, where some subprocesses of it see all files and some just see a subset despite running unter the same userid. That’s the nice thing about this idea.

Do you want to learn more? - Application Sandboxing in Oracle Solaris 11.4 - Labeling Files for Data Loss Protection - Labeling Processes for Data Loss Protection