A few questions about mac_mls and mac_biba

Hello,

I'm new to FreeBSD (I've been currently experimenting with FreeBSD 9.0-RELEASE) and I've been playing with mac_mls and mac_biba a bit. I have some questions about using these MAC modules, to which I haven't found any answers:

1. I wanted to set up a few login classes with a range of compartments, but it never worked. Say, for example, I'd like to have a login class with default MAC label set to mls/5, with possible ranges from 2 to 10 and with possible compartments from 1+2+3 to 1+2+3+4. This is what I added to /etc/login.conf:
Code:
mlsclass:\
     :label=mls/5(2:1+2+3-10:1+2+3+4):
but it doesn't work. I also tried to escape the brackets and/or the colons in the label definition with a backslash, but with the same result. After login, the user with the security class mlsclass doesn't have a label mls/5(2:1+2+3-10:1+2+3+4) as I would expect, but mls/5(low-high) instead. Of course I run # cap_mkdb /etc/login.conf after a change of the class definition. Is there anything I do wrong or what I've understood wrong?

2. The compartments can only be determined by a number (1-256), or there is a way to use a text label for them instead of numbers?

3. Is there a simpler way to manage the labels for different login classes than manually editing /etc/login.conf?

4. One practical use of the aforementioned MAC modules is probably setting mandatory rules which files/directories can be accessed by the users in different login classes. What could be other uses for those modules in practice? :-) I thought of some, but then I told myself there would probably be better solutions than those modules (e. g. using mac_biba for a webserver within an insecure class running at biba/low with the served files labeled biba/low, but there would be other ways to secure the system from possible webserver vulnerabilities, such as jails?).

Thank you very much in advance for your answers!
 
Nobody has any idea about my questions? :-( At least I'd be very glad to find answers for questions 1 and 4...
 
Little help.

I'm looking for more tutorials about MAC but there is nothing! There is such less documentation about MAC that I'm so angry. This is the one of strongest site of freebsd FreeBSD and so less information about. I have been looking by all the time and found nothing. I have found only something from 2004 maybe it can help you.

Code:
CONTENTS
=====================================

1. Introduction
2. Simple policies
3. Advanced policies
4. Full example
5. Notes
6. Link of the day
7. Last words

=====================================



1. Introduction
===============

	I've written this tutorial because FreeBSD's handbook 
	([url]http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/index.html[/url]) didn't offer enough 
	information on how to correctly/safely install/configure/use MAC on a workstation. Please 
	refer to the man pages and handbook for detailed explanation on how everything works.

	MAC (mandatory access control) is used to introduce system security modules in order to fortify 
	the default lack of security policies in most unices. This paper discusses the 
	instalation/configuration and basic use of the following policies: 

	mac_seeotheruids, mac_bsdextended, mac_ifoff, mac_portacl, mac_test, mac_none, mac_stub
	mac_partition, mac_mls, mac_biba, mac_lomac

	Compile your kernel with the new policies by adding the following line in the kernel conf. file:
		options MAC


2. Simple policies
==================

	These policies work without the use of the labelling feature:

	A. mac_seeotheruids (man mac_seeotheruids)

			$ ps ax |wc -l
			90
			# kldload mac_seeotheruids
			# sysctl security.mac.seeotheruids.enabled=1
			^^^ this is the default behaviour (use sysctl.conf to make permanent changes)
			$ ps ax | wc -l
			30

		You can exempt a groupd ID from the policy:
	
			$ id -G
			2000
			$ ps ax | wc -l
			30
			# sysctl security.mac.seeotheruids.specificgid_enabled=1
			# sysctl security.mac.seeotheruids.specificgid=2000
			$ id -G
			2000
			$ ps ax | wc -l
			90

		Or even let users see their primary groups processes: (remember to set seeotheruids.specificgid_enabled to 0)

			# sysctl security.mac.seeotheruids.primarygroup_enabled=1
			$ id -G
			2000
			# ps ax | wc -l
			35
			(my 30 processes + 5 others owned by the same group)

	B. mac_bsdextended

		Ever used ipfw ? This is fsfw (file system firewall).

			# kldload mac_bsdextended
			# ugidfw list
			0 slots, 0 rules

			# cat rc.mac_bsdextended
				#!/bin/sh
				i=0
				while [ ${i} -le 4 ]
				do     
				ugidfw remove ${i}
				i=`expr ${i} + 1`
				done
				ugidfw set 0 subject uid new object uid root mode rsx
				ugidfw set 1 subject uid new object gid wheel mode rsx
				# yes, /bin/ls works now
				ugidfw set 2 subject uid new object uid bugghy mode n
				ugidfw set 3 subject uid new object gid bugghy mode n
				# owned by bugghy == private :)
				ugidfw set 4 subject uid new object gid nobody mode n
				# new can't "locate | grep /home/bugghy" anymore <-- BIG security risk
				# you can deny other groups (from /etc/group) or users (/etc/passwd)

			$ id -u -nr
			bugghy
			$ echo sex > /tmp/bug; chmod a+rwx /tmp/bug; ls -l /tmp/bug
			-rwxrwxrwx    1 bugghy   wheel           4 Apr  5 20:05 bug*
	
			$ id -u -nr
			new
			$ ls -l /home
			ls: bugghy: Permission denied
			total 4
			drwxr-xr-x  2 new    new    512 Mar 28 15:09 new
			$ ls /tmp/bug
			ls: /tmp/bug: Permission denied

	C. mac_ifoff

			# kldload mac_ifoff
			$ ping -c 1 127.0.0.1
			PING 127.0.0.1 (127.0.0.1): 56 data bytes
			64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.203 ms

			--- 127.0.0.1 ping statistics ---
			1 packets transmitted, 1 packets received, 0% packet loss
			round-trip min/avg/max/stddev = 0.203/0.203/0.203/0.000 ms
			# sysctl security.mac.ifoff.lo_enabled=0
			$ ping -c 1 127.0.0.1
			PING 127.0.0.1 (127.0.0.1): 56 data bytes

			--- 127.0.0.1 ping statistics ---
			1 packets transmitted, 0 packets received, 100% packet loss

			# sysctl security.mac.ifoff.other_enabled=1
			^^^ we enable external interface (which is disabled by default)
			You can write a script that runs aide (with a proper config file) and if it finds modified
			files in the protected directories it won't allow external network traffic.
			# sysctl security.mac.ifoff.bpfrecv_enabled=1
			^^^ allows Berkeley Packet Filter traffic (man 4 bpf)

	D. mac_portacl
		To enable mac policies on sockets "sysctl security.mac.enforce_socket=1": (default value)

			# kldload mac_portacl

			# sysctl net.inet.ip.portrange.reservedlow=0
			sysctl net.inet.ip.portrange.reservedlow: 0 -> 0
			# sysctl net.inet.ip.portrange.reservedhigh=1000
			sysctl net.inet.ip.portrange.reservedhigh: 1023 -> 1000
			# sysctl security.mac.portacl.port_high=1010
			security.mac.portacl.port_high: 1000 -> 1010
	
			# sysctl security.mac.portacl.suser_exempt=0
			^^^ rules apply for root too
	
			$ id -u
			2000
			$ nc -l -p 1000
			Can't grab 0.0.0.0:1000 with bind : Operation not permitted
			^^^ the ip.portrange.reservedhigh limit works
			$ nc -l -p 1010
			Can't grab 0.0.0.0:1010 with bind : Operation not permitted
			^^^ the mac.portacl.port_high limit works too
	
			# sysctl security.mac.portacl.rules=uid:2000:tcp:1000,uid:2000:tcp:1010
			^^^ we enforce 2 rules (the first tries to bypass ip.portrange.reservedhigh
			and the 2nd tries to bypass mac.portacl.port_high)
	
			$ nc -l -p 1000
			Can't grab 0.0.0.0:1000 with bind : Permission denied
			^^^ mac.portacl allows port 1000 binding while ip.portrange.reservedhigh doesn't
			$ nc -l -p 1010
			^^^ works due to our firewall rule
	
			NOTE: A basic security policy would be:
			# cat rc.mac_portacl
				#!/bin/sh
				rules="uid:2000:tcp:79,uid:2000:tcp:80"
				# allow uid 2000 to bind to port 79 and 80
	
				sysctl net.inet.ip.portrange.reservedlow=0
				sysctl net.inet.ip.portrange.reservedhigh=50
				# first 50 ports are accessible only by root
				sysctl security.mac.portacl.port_high=1023
				# our policy works for 50 -> 1023
				sysctl security.mac.portacl.suser_exempt=1
				# root doesn't need the policy
				sysctl security.mac.portacl.rules=$rules

	E. mac_test

		Tests the mac framework, finds corrupt labels amongst other things.

			# kldload mac_test
			# sysctl security.mac.test
			security.mac.test.enabled: 1
			security.mac.test.slot: 2
			security.mac.test.init_count_bpfdesc: 0
			security.mac.test.init_count_cred: 1920
			security.mac.test.init_count_devfsdirent: 0
			security.mac.test.init_count_ifnet: 0
			...
			(big output)


	F. mac_none

		No effect.

			# kldload mac_none

	G. mac_stub

		Sample policy that does nothing (man 4 mac_stub)

			# kldload mac_stub
(...)

More you will see under link: -> http://lists.freebsd.org/pipermail/trustedbsd-discuss/2004-April/000547.html

I can't paste more because of restrictions. Let me know if it helps you.
 
Hi bryn1u,

thank you for your effort to help me. I know the text you posted, and I strongly agree with you that there's a serious lack in documentation and howtos relating to the MAC framework in TrustedBSD. That's why I asked the questions above :). I hope I will be able to answer them at least partially (the sooner the better).
 
I think the default compartments (corresponding to "5") need to at least contain the low end ("1+2+3") but no more than the high end ("1+2+3+4"). In other words, with "a:A(b:B-c:C)" you need b<=a<=c and B subset A subset C. For example, you could try "mls/5:1+2+3(2:1+2+3-10:1+2+3+4)".
Kevin Barry
 
Hi Kevin,

You're right with the dominance of the A, B, C subsets, but I'm still afraid it doesn't work as expected. In the example I posted earlier, I made the mistake that the default security level wasn't higher or equal to the low security level. So I tried to set MLS label for the login class of my user to mls/1:1(1:1-2:1+2), which should be OK AFAIK. But still it doesn't work as it should:

Code:
$ getpmac
mls/1(low-high)

It seems like I don't get something important, or the classes are somewhat broken in the MAC framework. I also noticed one think that kind of breaks the information flow in MLS - a user can manipulate the security label within the range of his security levels in both ways - he can upgrade the label to a higher level (which in fact could be OK), but he also can downgrade it, which could cause information leak. Is there any way to disable it, or it's a bug, or it's just a feature of the MLS implementation in the FreeBSD Mac framework?
 
What method are you using to switch to that user, e.g. console login, ssh, su, sudo, etc.? The first two set the MAC label for the user, but the last two don't by default.

Kevin Barry
 
In this case it was just a console login. Btw, what's your opinion on the upgrade/downgrade possibility of the files' level within the user's security levels range?
 
jirka said:
Btw, what's your opinion on the upgrade/downgrade possibility of the files' level within the user's security levels range?
Without this you'd never be able to use multilabel because you can't create a file in a directory that has a different MAC label. The MAC label of the directory effectively places a bound on the MAC labels of the contained files (notwithstanding the almighty process labels mls/equal and biba/equal.) For mac_mls this is a lower boundary and for mac_biba this is an upper boundary. Take the following two examples.
  1. My home directory is mls/low and I can't $ setpmac mls/1 touch test. I can, however, $ touch test && setpmac mls/1 setfmac mls/1 test. In this case, I can create "test" because I'm in mls/low and so is the directory, and I can change the MAC label because I can go to mls/1 and still access the directory.
  2. On the other hand, if I was in an mls/1 directory operating at mls/1(low-1) I couldn't do $ touch test && setpmac mls/low setfmac mls/low test because as soon as I go to mls/low I can no longer access the current directory. You could easily write a program in C that buffers from an mls/1 file, changes to mls/low, and writes to an mls/low file, which would circumvent any attempt to prevent downgrading files, except that the file being written to would have to be in a location both readable and writable by that process (which can further be restricted by mac_biba.)
In this case it's a compromise to let users change file labels, because otherwise you'd need an all-powerful mls/equal user to go around and maintain all of the places where a file's label needs to differ from that of the containing directory. I think the idea is that your level of trust of the user dictates his/her label range. If you don't trust a user to not "inappropriately declassify" files then that person should not be able to access the higher and lower levels within the same process. Compartmentalization is inherently inconvenient, but small compromises need to exist so that larger compromises don't become common practice. It's the same philosophy that inspires tools like sudo, without which you'd have to decide between handing out the root password and tightly controlling all sysadmin yourself. If you absolutely cannot tolerate a particular file being downgraded then you need to prevent all processes from having access to both level "x" and "x-1" at the same time.
jirka said:
So I tried to set MLS label for the login class of my user to mls/1:1(1:1-2:1+2), which should be OK AFAIK.
You should try this without the compartments to see if you get mls/1(1-2) when you log in.


On a related topic, I think a very powerful use of mac_mls and mac_biba is to hide processes. For example, you can run a process at mls/high and set the MAC label for all login classes to something lower, so even someone with root access won't be able to detect or terminate that process. This, of course, requires that you limit the MAC label of sshd; otherwise, someone could just edit /etc/login.conf and log in again.

Kevin Barry
 
ta0kira said:
Without this you'd never be able to use multilabel
To be honest, I don't know what exactly the multilabel option means - does that mean that I can have an object (file, directory, ...) with a range of security levels, or multiple labels per file (for example, mls/1 and biba/equal), or even something else?

I agree that in most cases there's a tradeoff between security and usability... But still, not having known that mac_mls works this way, I would expect for example that a user would be able to create a new file on any level in his range, or maybe upgrade a level of an existing file if he's the owner, but that he won't be able to downgrade it (or at least that there would be an option to force this behavior). Yes, I know that the theory and real use are two different things.

You should try this without the compartments to see if you get mls/1(1-2) when you log in.

When I try to set up a security level range without compartments, I get exactly what I expected. For example, I set mls/1(1-2) and get
Code:
$ getpmac
mls/1(1-2)
but when I add compartments, it looks like this (for mls/1:1(1:1-2:1)):
Code:
$ getpmac
mls/1(low-high)
, just in the same way I mentioned earlier.
 
jirka said:
To be honest, I don't know what exactly the multilabel option means - does that mean that I can have an object (file, directory, ...) with a range of security levels, or multiple labels per file (for example, mls/1 and biba/equal), or even something else?
It means that every file has its own respective MAC label, vs. every file on the filesystem sharing a global MAC label.
jirka said:
I agree that in most cases there's a tradeoff between security and usability... But still, not having known that mac_mls works this way, I would expect for example that a user would be able to create a new file on any level in his range, or maybe upgrade a level of an existing file if he's the owner, but that he won't be able to downgrade it (or at least that there would be an option to force this behavior). Yes, I know that the theory and real use are two different things.
In many cases sensitive information becomes less sensitive over time. It's also more costly to protect sensitive data, so organizations often downgrade sensitivity whenever possible. This obviously isn't universal, since some information is sensitive for a very long time (e.g. medical and legal information.)
jirka said:
When I try to set up a security level range without compartments, I get exactly what I expected. For example, I set mls/1(1-2) and get
Code:
$ getpmac
mls/1(1-2)
but when I add compartments, it looks like this (for mls/1:1(1:1-2:1)):
Code:
$ getpmac
mls/1(low-high)
, just in the same way I mentioned earlier.
I think the problem is that ":" is a delimiter for login.conf, so cap_mkdb stops parsing the label with mls/1. You should try escaping the ":" with "\", i.e. mls/1\:1(1\:1-2\:1).

Kevin Barry
 
ta0kira said:
It means that every file has its own respective MAC label, vs. every file on the filesystem sharing a global MAC label.
Thank you, now it's clear to me.

You should try escaping the ":" with "\", i.e. mls/1\:1(1\:1-2\:1).
Unfortunately this doesn't work either. I also tried to put the whole label between single or double quotes, without success.
 
Sorry, just found this in the login.conf manpage:
Code:
     Note that since a colon (`:') is used to separate capability entries, a
     `[B][U]\c[/U][/B]' escape sequence must be used to embed a literal colon in the value
     or name of a capability.
Kevin Barry
 
Back
Top