In this lab we we take quick tour of some of Oracle Solaris security features that can help you to protect your applications and your system. We will look at the following technologies:
For lab exercises 3 and 4, apache 2.2 is required.
To install apache 2.2 on Solaris 11;
Expected duration: 20 minutes
The goal of this exercise is to gain a basic understanding of the RBAC/privileges framework in Solaris.
Thanks Joerg Moellenkamp and his post on Less known Solaris features: RBAC and Privileges - Part 1: Introduction for the following introduction.
And then there was root. And root was almighty. And that wasn't a good thing. root was able to control the world without any control. And root needed control. It was only a short chant between the mere mortals and root. Everybody with the knowledge of the magic chant was able to speak through root.
But root wasn't alone. root had servants called daemons. Some of one them needed divine powers to do their daily job. But root was an undividable being. So the servants had to work with the powers of root. But the servants were not as perfect as root: Some of the servants started to do everything mere mortals said to them if they only said more than a certain amount of prayers at once.
The old model of rights in a Unix systems is based on a duality. There is the superuser and the normal user. The normal users have a restricted set of rights in the system, the superuser has an unrestricted set of rights. To modify the system, a normal user has to login as root directly or assume the rights of root (by su -). But such a user has unrestricted access to the system. Often this isn't desirable. Why should you enable an operator to modify a system, when all he or she has do to on the system is create some users from time to time. You've trained them to do useradd or passwd. What do you do when they get too curious? They need root privileges to create a user or change a password. You need some mechanisms to limit this operator.
But it gets more problematic. Programs have to modify the system to work. A web server is a good example. You expect it to use port 80, ports beneath port number 1024 are privileged ports. You need special rights to modify the structures of the system to listen to port 80. A normal user doesn't have these rights. So the web server has to be started as root. The children of this process drop the rights of root by running with a normal user. But there is this single instance of the program with all the rights of the user. This process has much more rights than needed, a possible attack vector for malicious users.
There is a concept in security known as least privilege. You give someone only least amount of privileges, only enough to do the tasks they are assigned. An example of the real world - you won't give the janitor the master key for all the rooms on the campus, when all he has to do is work in Building C. The other way around - there are some trusted people who have access to all rooms in case of an emergency.
You have the same concept in computer security. Everyone should have only the least amount of privileges in the system to do their job. The concept of the superuser doesn't match to this, it's an all or nothing model. You are an ordinary user with basic privileges or you are a user with unrestricted rights. There is nothing in between. This doesn't follow the least privileges model.
The example with the key for the janitors is a good example. Let's imagine a large campus. You have janitors responsible for the plumbing (let's call them Lenny and Carl), for the park (let's call him Homer), for the security system (let's call her Marge and Lenny helps from time to time).
These roles have different sets of privileges: For example the plumbing janitors have access to all the rooms of the heating system. The janitor for the park has only access to the garage with the lawnmower.
When they start to work in their job, they assume a role. From the privilege perspective it's not important who is the person, but what role the person has assumed. Lenny punches the clock and assumes the role of the plumbing janitor for the next 8 hours. And while he is doing its job he uses the privileges inherent to the role. But he also has to do tasks in his office or in his workshop. It's his own room, so he doesn't need the special privileges.
Role Based Access Control is quite similar. You login to the system, and then you start to work. You read your emails (no special privileges needed), you find an email "Create user xy45345. Your Boss". Okay, now you need special privileges. You assume the role of a User Administrator and create the user. Job done, you donÂ´t need the privileges anymore. You leave the role and write the "Job done" mail to your boss with your normal user's privileges.
Role Based Access Control is all about this: Defining roles, giving them privileges and assigning users to this roles.
I've used the word quite often in this introduction so far. What is a privilege? A privilege is the right to do something. For example, having the keys for the control panel of the heating system.
Unix users are nothing different. Every user has privileges in a Unix system. A normal user has the privilege to open, close, read, write and delete files when he is allowed to do this (Because he created it, because he belongs to the same group as the creater of the file or the creator gave everybody the right to do it). This looks normal to you, but it's privilege based on the login credentials you gave to system. You don't have the privilege to read all files on the system or to use a port number 1024.
Every thing done in the system is based on these privileges. Solaris has separated the tasks into many privilege sets. At the moment, there are 70 different privileges in the system. The difference between the normal user is that the users have only a basic set, while root has all.
In Solaris the model has changed, privileges and users aren't connected with each other. You can give any user the power of the traditional â€œroot userâ€, and restrict the privileges of the root user. Solaris is configured to look as a traditional super user model due to our binary compatibility guarantee that mandates that the standard configuration of the system resembles the superuser model. There are application out there, which assume that only the root user or the UID 0 as unrestricted rights and exit when they are started with a different user.
The only thing that is special with UID 0 in Solaris is that it's the owner of the system configuration files, and thus has the capability to change system configurations.
Both features have their root in the Trusted Solaris product. Trusted Solaris was a version of Solaris to ensure the highest security standards. Today, these mechanisms are part of the normal Solaris in conjunction with the Trusted Extensions. So RBAC is a really old feature - it has been in Solaris since Solaris 8 (published in 2000). Privileges found their way into the generic Solaris with the first availability of Solaris 10 in February 2005.
Open a terminal window by right clicking any point in the background of the desktop, and select Open +T+erminal in the pop-up menu.
Lets look at what roles are assigned to our Oracle user. In a terminal, do as follows:
As you can see here you should be assigned the role root, it allows us to assume the root role. In Solaris 11 root is not a user but rather a role. So you have to login to the system as a normal user and then assume the root role with the su command.
In a terminal window type as follows:
As you can see here root is defined as a role with authorizations, the effect of this is similar to the old almighty root user. This is put in place for backwards compatibility.
And as your user is assigned the root role, you can try this by assuming the root role:
Lets add a new user, Joe Doe to our system:
As you can see here we are not allowed to use the useradd command. We will have to use su to execute useradd with "root" privileges, and assign missing rights to our account. The su command will prompt you for the root password.
As you can see, we now have the right to manage users. To take advantage of this right, we will invoke a profile shell, e.g. pfbash, and create the new user, jdoe.
To change the user's password we have to have User Security profile assigned, but it is not advised to assign it to a regular user because it allows the user to change passwords of other users, including more powerful ones. User Management profile is safe, because you can only delegate what you already have. Therefore, let's change the password of the new user using root role:
Note: -g oinstall option is submitted to the useradd command. It is necessary to add it because oracle user is in oinstall group by default in this lab setup. Default group in Oracle Solaris 11 is staff. Therefore, if you do not explicitly require to add the user to oinstall group with -g oinstall, useradd will try to add the new user to staff group. You are not allowed to do it as user oracle, because a user with "User Management" profile is allowed to add a new user just to a group which he/she already belongs to.
Role Authentication procedure has changed in Solaris 11. Running earlier Solaris version, including Oracle Solaris 11 Express, user had to know role password in order to assume the role. Oracle Solaris 11 includes the ability to specify whether to use the role password or user password when a user wants to assume a given role. Administrators can specify either 'user' or 'role' for the 'roleauth' keyword. If roleauth is not specified, 'role' is implied. Any newly created roles will be 'user' by default.
As you can see here jdoe doesn't have any roles assigned to him and he can't use su to assume the root role. We'll get back to him later. Now let's move on to a closer look at privileges in Exercise 2.
Expected duration: 20 minutes
The goal of this exercise is to understand Solaris privileges and how to use them
What are Privileges? Privileges are rights to do an operation in the kernel. These rights are enforced by the kernel. Whenever you do something within the kernel the access is controlled by privileges.
contract_event, contract_identity, contract_observer, cpc_cpu, dtrace_kernel, dtrace_proc, dtrace_user, file_chown, file_chown_self, file_dac_execute, file_dac_read, file_dac_search, file_dac_write, file_downgrade_sl, file_flag_set, file_link_any, file_owner, file_setid, file_upgrade_sl, graphics_access, graphics_map, ipc_dac_read, ipc_dac_write, ipc_owner, net_access, net_bindmlp, net_icmpaccess, net_mac_aware, net_mac_implicit, net_observability, net_privaddr, net_rawaccess, proc_audit, proc_chroot, proc_clock_highres, proc_exec, proc_fork, proc_info, proc_lock_memory, proc_owner, proc_priocntl, proc_session, proc_setid, proc_taskid, proc_zone, sys_acct, sys_admin, sys_audit, sys_config, sys_devices, sys_ipc_config, sys_linkdir, sys_mount, sys_iptun_config, sys_dl_config, sys_ip_config, sys_net_config, sys_nfs, sys_ppp_config, sys_res_config, sys_resource, sys_smb, sys_suser_compat, sys_time, sys_trans_label, virt_manage, win_colormap, win_config, win_dac_read, win_dac_write, win_devices, win_dga, win_downgrade_sl, win_fontpath, win_mac_read, win_mac_write, win_selection, win_upgrade_sl, xvm_control
Legend: blue - basic privilege
On conventional Unix systems you have a root user and they have all privileges. And you have a normal user, who has only a limited set of privileges. Sometimes you need the rights of an admin to do some tasks. You donÂ´t even need to administer the system.
You can use traceroute and ping because both tools are setuid tools. setuid allows a process to run with a specific userid and all the privileges that comes with that user. In the case of setuid to root the process would have root's privileges. A setuid program in Solaris can be privilege-aware and hence only retain the privileges needed for the operation.
You need a special privilege to ping - the privilege to use access ICMP. On conventional systems this right is reserved for the root user. Thus the ping program has to be executed with the rights of root. The problem: At the time of the execution of the program, the program has all the rights of the user. Not only to access ICMP, but the program is capable of doing everything on the system, such as deleting files in /etc. This may not a problem with ping or traceroute but think about larger programs. An exploit in a setuid program can lead to the escalation of the user's privileges.
Let's have a look at the privileges of an ordinary user. There is a tool to get the privileges of any given process in the system, it's called ppriv. $$ is a shortcut for the actual process id (in this case the process id of the shell):
What does "basic" mean, we can add -v to the ppriv flag to expand the aliases:
Every process in the system has four sets of privileges that determine if a process is enabled to use a privilege or not. The theory of privileges is quite complex. I would suggest to read the chapter How Privileges Are Implemented" in the Developers Guide to Oracle Solaris Security to learn how each set controls or is controlled other privilege sets.
At this time, I want only to explain the meaning of the first letter:
You can think about the privilege sets as keyrings. The effective privilege set are the keys the janitor has on its keyring. The permitted privilege set are the keys the janitor is allowed to put on its keyring. The janitor can decide to remove some of the keys. Perhaps he thinks: I work only in room 232 today, I donÂ´t need all the other keys. I'll leave them in my office. When he looses his keyring he lost only the control of this single room, not about the complete campus.
The inheritable privilege set is not a really a keyring. The janitor thinks about his new assistant: "Good worker, but I will not give him my key for the room with the expensive tools." The limited privilege set is the overarching order from the boss of janitor to his team leaders: "You are allowed to give your assistant the keys for normal rooms, but not for the rooms with all this blinking boxes from Oracle".
At the moment the most interesting set is the E:. This is the effective set of privileges. This is the set of privilege effectively available to process. Compared to the full list of privileges mentioned above the set is much smaller. But this matches your experience when you use a Unix system.
Lets see how it looks when we assume the root role:
This role has much more privileges. The effective set is much broader. When we assume the root role we assume all privileges in the system. NOTE: This is strictly to provide backwards compatibility and is not the recommended usage going forward.
Lets add some privileges to our jdoe user, let's assume that he is a software developer that needs access to DTrace to debug some applications.
First lets try to use DTrace as jdoe:
As we can see here jdoe is missing some privileges to be allowed to use DTrace. There are have 3 privileges needed for DTrace: dtrace_kernel, dtrace_proc, dtrace_user, depending on what the user needs to use DTrace for. We can add these privileges to the user in three different ways
Lets see how how to add dtrace privileges directly to the user (run first command as root, then exit root shell and continue as oracle user):
You will need to add basic to the set of privileges you assign to the user, without that he would not be able to do the most basic things such as create files, spawn new processes etc.
As you can see, jdoe now has the three needed privileges to use the dtrace command, lets give it a try:
OK, so that worked, just for the fun of it lets try to create a role that does the same.
First lets remove the dtrace privileges from jdoe:
Then lets create our role (using root shell, i.e. as a root user), lets call the role "bugger", and assign it to jdoe
OK, lets try and see if jdoe now can use DTrace
Now you should have a basic understanding about privileges and how you can assign them to users, however wouldn't it be nice if we could do the same to processes? We will look at that in exercise 3.
Expected duration: 10 minutes
We have looked at how you can add privileges to a user, now we'll look at how privileges interact with processes, we will look at both processes that are privilege aware and processes that are non-privilege aware.
The idea of managing the privileges is not limited to users and their shells. In any given system you find dozens of programs running as daemons.
These daemons interact in several ways with the privileges. The best way is "privilege-aware programming". Let's assume you code a daemon for your system. For example: You know that your daemon will never do an exec() call. So you can safely drop this privilege. The process modifies the permitted privilege set. The process can remove a privilege but not add it. Even when someone is able to access your process, the attacker can't make an exec() call. The process doesn't even have the privilege to do such a call. And the attacker can't add the privilege again. Several processes and programs in Solaris are already privilege aware. For example the kernel-level cryptographic framework daemon. Let's look at the privileges of the daemon.
In order to observe or manage privileges, a process must itself already have those privileges. Therefore we will assume the root role for the following exercise.
This daemon doesn't have even the basic privileges of a regular user. It has the only the bare minimum of privileges to do it's job.
But the world isn't perfect. Not every process is privilege aware. Thus you have to limit the privileges by other mechanisms. The Service Management Facility comes to help. The following example is copied from Glenn Brunette's Blueprint Limiting Service Privileges in the Solaris 10 Operating System.
Let's take the Apache Webserver as an example. The apache web server is not privilege aware. We start the daemon via the Service Management Framework (SMF).
OK, now we look at the processes of the Apache daemons.
Six daemons running as webservd, and one running as root.
As expected for a root process, this process has the complete set of privileges of a root user. Now lets look at one of its children:
Much better ... only basic privileges.
OK, There is a reason for this configuration. On Unix systems, you have two groups of ports. Privileged ones from 1-1023 and unprivileged ones from 1024 up. You can only bind to a privileged port with the privilege to do it. A normal user doesnÂ´t have this privilege, but root has it. And thus there has to be one process running as root. Do you remember the list of privileges for the apache process running at root. The process has all privileges but needs only one of them, that isn't part of the basic privilege set.
Expected duration: 10 minutes
We have now looked at both privilege aware and non-privilege aware processes, now lets look at how we can use SMF to let a user with a limited set of privileges manage a non-privilege aware process and give it the required privileges without using setuid to root.
In order to observe or manage privileges, a process must itself already have those privileges. Therefore we will assume the root role for the following exercise.
It doesn't to be this way. With Solaris you can give any user or process the privilege to use a privileged port. You don't need the root process anymore.
Let's configure it this way. At first we have to deactivate the running apache from exercise 3:
We will not be explaining the Service Management Facility here, but you can set certain properties in SMF to control the startup of a service:
Line 2 to 4 are the most interesting ones. Without any changes, the Apache daemon starts as root and forks away processes with the webservd user. But we want to get rid of the root user for this configuration. Thus we start the daemon directly with the webservd user, the same goes for the group id.
Now it gets interesting. Without this line (line 4), the kernel would deny Apache to bind to port 80. webservd is a regular user without the privilege to use a privileged port. The property start/privileges sets the privileges to start the service. At first, we give the service basic privileges. Then we add the privilege to use a privileged port. The service would start up now.
But wait, we can do more. A webserver shouldn't do any hardlinks. And it doesn't send signals outside it's session. And it doesn't look at processes other than those to which it can send signals. We donÂ´t need these privileges. proc_session, proc_info and file_link_any are part of the basic privilege set. We remove them, by adding a ! in front of the privilege:
OK, we have notified SMF of the configuration changes.
Until now, the apache daemon used the root privileges. Thus the ownership of files and directories were unproblematic. The daemon was able to read and write in any directory or file in the system. As we drop its privilege set by using a regular user, we have to modify the ownership of some files and move some files:
While the service no longer runs as root, there is a trade-off. In the "root" configuration, logs were owned by root and could not be modified by "webservd". In the new model, the web server has fewer privileges but the logs are now owned and writable by "webservd". This is not good or bad, just a tradeoff.
We need some configuration changes, too. We have to move the LockFile and the PidFile. There wasn't one of the two configuration directives specified earlier, thus we're simply appending them to the end of the configuration file:
OK, everything is in place. LetÂ´s give it a try.
Now we check for the running httpd processes:
You notice the difference ? There is no httpd running as root. All processes run with the userid webservd. Mission accomplished.
LetÂ´s check the privileges of the processes. At first the one, who ran as root before:
Only the least privileges to do the job, no root privileges. And even the other processes are more secure now. Before we changed the configuration of the webserver, it had the basic privileges of a regular user. Now we limited even this set.
But we still need to be a privileged user to start apache. Wouldn't it be nice if I could delegate management of â€œservicesâ€ to unprivileged users. I can use authorizations to do that, and authorizations is integrated with SMF. There are two authorizations we will need to add to our user to give hi the right to manage the apach22 service. We need a authorization to manage our service as well as a authorization to change the state of our service:
Both are needed to change the state of a service, as the state of the service is kept as a property for the service.
First we need to add our authorizations to /etc/security/auth_attr
In most SMF manifests one authorization is used for both action_authorization and value_authorization, as they are commonly used together.
Now we can exit the root role since we are finished manipulating privileges. Lets add those authorizations to our old friend jdoe.
Lets see if jdoe can start and stop apache now
See that worked fine, so by using SMF we've been able to take a service such as apache, removed it's need to start as root by giving it the privileges it needed and nothing more. We also removed some privileges that apache doesn't need, but a hacker would need to take control of your system.
Add to that we added the right to manage the apache service via SMF to an unprivileged user by giving him the correct authorizations that allows a user to manage that particular service and nothing else, as you can see here.
Congratulations! You have successfully completed - Protect Your Applications with Oracle Solaris Security.*
For additional information about the technologies used in this lab, please see the following links:
Restricting Service Administration in the Solaris 10 OS
Limiting Service Privileges in the Solaris 10 OS
Privilege Debugging in the Solaris 10 Operating System
Privilege Bracketing in the Solaris 10 Operating System
Thank you for participating!