A Taste of Computer Security

© Amit Singh. All Rights Reserved. Written in August 2004

Security in Solaris 10

The complexity of the "Security Problem", and of its attempted solutions may be appreciated by looking at what all could be listed under a loosely defined security umbrella. While Linux is a commonly chosen system for implementing research ideas — security-related and otherwise — Solaris 10 has a very impressive out-of-the-box security repertoire amongst general purpose operating systems. Using Solaris 10 as an example, we see in this section that the collection of security-related mechanisms in a modern operating system could amount to a dizzying array of technologies. Knowing what these are in a given system is the first step — an easy one. The next step is to understand them, but the hardest part is using these effectively.

Note that some mechanisms and features listed here also exist in Microsoft's recent systems (consider Microsoft Security Services in Windows Server 2003).

Login Administration

Solaris provides various tools for monitoring and controlling a user's ability to access the system. There is support for multiple password encryption algorithms, which may be implemented as 3rd party modules.

Resource Management

In Solaris, a task is a group of processes representing a component of some workload. A task is a manageable entity. Moreover, each workload (possibly consisting of several tasks) is tagged with a project identifier: a network-wide name for related work. Each logging in user must be assigned at least a default project.

Solaris provides flexible resource management through a number of control mechanisms:

Examples of available resource controls include CPU shares, total amount of locked memory allowed, limits on the sizes of the heap, the stack, and overall address space (summed over segment sizes), and limits on the number of various entities such as IPC objects, lightweight processes, file descriptors, etc.

# prctl $$ ... # cat /etc/project ... test-project:100::root::task.max-lwps=(privileged,2,deny) # newtask -p test-project /bin/zsh # id -p uid=0(root) gid=1(other) projid=100(test-project) # prctl -n task.max-lwps -i project test-project 3536: prctl -n task.max-lwps -i project test-project task.max-lwps 2 privileged deny 2147483647 system deny [max] # sleep 100 & [1] 3563 # sleep 100 & zsh: fork failed: resource temporarily unavailable

The resource capping daemon, rcapd, regulates physical memory consumption by processes running in projects that have resource caps defined. Per-project physical memory caps are supported.


Zones provide a virtual mapping from the application to the platform resources. They could be simply understood as "application containers": a software partitioning scheme so that operating system services may be virtualized to yield similar, but isolated execution environments for applications.

The software limit on the maximum number of Zones per-machine is 8192, although in real life it would depend upon available resources, and on "normal" systems, the allowable number would be far lesser.

Note that one zone, called the global zone, is always present, and represents the conventional (default) Solaris execution environment. The global zone is the only zone that is bootable from physical hardware. Additional zones are configured, installed, and removed only from within the global zone. However, each zone can be administered independently. Therefore, zones allow delegation of administration without compromising overall system security.

Non-global zones can be used in association with resource management for better control and more efficient resource utilization. Once a process is placed in a non-global zone, the process (or any of its descendents) will be confined to that zone. A non-global zone's privileges are always a subset of the global zone's.

An example of using zones follows.

Initially, you only have one zone: the global zone. The zonecfg command is used to create and configure a new zone.

# zoneadm list global # zonecfg -z test-zone test-zone: No such zone configured Use 'create' to begin configuring a new zone. zonecfg:test-zone> create zonecfg:test-zone> set zonepath=/zones/test-zone zonecfg:test-zone> set autoboot=false zonecfg:test-zone> add fs zonecfg:test-zone:fs> set dir=/shared/tmp zonecfg:test-zone:fs> set special=/tmp zonecfg:test-zone:fs> set type=lofs zonecfg:test-zone:fs> end zonecfg:test-zone> add net zonecfg:test-zone:net> set address= zonecfg:test-zone:net> set physical=iprb0 zonecfg:test-zone:net> end zonecfg:test-zone> add device zonecfg:test-zone:device> set match=/dev/fd0* zonecfg:test-zone:device> end zonecfg:test-zone> verify zonecfg:test-zone> commit zonecfg:test-zone> exit

The zone must be installed before it can be booted and used.

# zoneadm -z test-zone install Preparing to install zone <test-zone>. Creating list of files to copy from the global zone. Copying <2178> files to the zone. Initializing zone product registry. Determining zone package initialization order. Preparing to initializing <681> packages on the zone. Initialized <681> packages on zone. Zone <test-zone> is initialized. ...

Booting a zone is similar in many respects to booting a regular Solaris system. You can log in to a booted zone using the zlogin command.

# zoneadm -z test-zone boot # zoneadm list -v ID NAME STATUS PATH 0 global running / 1 test-zone running /zones/test-zone # zonename global # zlogin -C test-zone [Connected to 'test-zone' console] /* * The first time you do this, you must * set language, time zone, root password, etc. * Zone will reboot. */ test-zone console login: root Password: ******** Jul 5 18:49:55 test-zone login: ROOT LOGIN /dev/console Sun Microsystems Inc. SunOS 5.10 s10_58 May 2004

Now you can explore the isolation and virtualization aspects of zones. Note that a zone is not identical to a conventional Solaris environment. For example, a zone cannot be an NFS server; you cannot use the mknod system call inside a zone, and so on.

# zonename test-zone # ls /shared/tmp ... (files from global /tmp) # ls /proc 10640 10691 ... 10643 10730 ... 10666 10740 ... # ifconfig -a iprb0:1: flags=... inet netmask ff000000 lo0:1: flags=... inet netmask ff000000

Role-Based Access Control (RBAC)

RBAC is an alternative to the traditional all-or-nothing super-user model. RBAC is based on the principle that no user should have more privileges than are necessary for performing an operation (the principle of least privilege). Following are key aspects of RBAC:

Note that without the appropriate privilege, a process will not be able to perform a privileged operation (the kernel will ensure it). However, without an authorization, a user may not be able to run a privileged application (or perform certain operations within such an application).

# ppriv -l cpc_cpu dtrace_kernel dtrace_proc ... sys_suser_compat sys_time

Now, let us try to read a file that we do not have privileges to read. The -D option of ppriv will turn on privilege debugging.

$ ppriv -e -D cat /etc/shadow cat[1399]: missing privilege "file_dac_read" \ (euid = 100, syscall = 225) needed at ufs_iaccess+0xd2 cat: cannot open /etc/shadow

We could create a new role, say called "filerole", and assign ourselves to that role.

# roleadd -s /bin/pfksh -d /home/filerole \ -K defaultpriv=basic,file_dac_read filerole # passwd filerole # New Password: ******** # Re-enter new Password: ******** passwd: password successfully changed for filerole # mkdir /home/filerole # chown filerole:other /home/filerole # usermod amit -R filerole # su - amit $ su - filerole Password: ******** $ cat /etc/shadow

You can list the privileges that your current shell has as follows:

$ ppriv -v $$ ...

Device Management

Solaris provides two mechanisms for controlling device access:

Device Policy - access to a particular device needs a certain set of privileges. For example, in order to access a network device directly (for sending raw packets, say), you would need the net_rawaccess privilege. The getdevpolicy command can be used to inspect the system's device policy:

# getdevpolicy DEFAULT read_priv_set=none write_priv_set=none ip:* read_priv_set=net_rawaccess write_priv_set=net_rawaccess icmp:* read_priv_set=net_icmpaccess write_priv_set=net_icmpaccess ... spdsock:* read_priv_set=sys_net_config write_priv_set=sys_net_config

Device Allocation - use of a device requires authorization, and only one user may allocate a device at a time. The list_devices command can be used to list allocable devices:

# list_devices -l device: fd0 type: fd files: /dev/diskette ... device: sr0 type: sr files: /dev/sr0 ...

It is also possible to prevent a device from being used entirely.


Solaris supports auditing, that is, collection of data about system usage, at the kernel level. Solaris auditing can be configured to generate audit records for a wide variety of events.

Basic Audit Reporting Tool (BART)

Unrelated to the kernel-based auditing mentioned earlier, BART is a tool that can be used to determine what file-level changes have occurred on a system relative to a known baseline. Thus, BART is a file-tracking tool, and it operates at the filesystem level. It allows you to define which files to monitor, and you can use it to create a control manifest — a baseline, or a trusted data set — from a fully installed and configured system. For each file being monitored, the manifest includes information about the file's attributes, its MD5 checksum, etc.

# bart create -R /etc > /tmp/etc.ctrl.manifest # touch /etc/DUMMY # chmod 444 /etc/zshenv # bart create -R /etc > /tmp/etc.test.manifest # cd /tmp # bart compare etc.ctrl.manifest etc.test.manifest /DUMMY: delete /zshenv: mode control: 100444 test:100644 acl control:user::r--,group::r--,mask:r--,other:r-- \ test:user::rw-,group::r--,mask:r--,other:r--

Automated Security Enhancement Tool (ASET)

ASET is a security package that provides automated administration tools for controlling and monitoring system security. It runs various tasks that perform specific checks and adjustments based on the level at which ASET is run — one of low, medium, or high (access permissions of many files restricted). ASET tasks include:

In a typical usage scenario, ASET would be run periodically via a crontab entry.

Solaris Security Toolkit (JASS)

This toolkit, also known as the JumpStart Architecture and Security Scripts (JASS), helps in simplifying and automating the process of securing a Solaris system. This process includes minimizing (removal of unnecessary packages) and hardening (performing modifications aimed at improving system security). JASS includes a profiling tool, a reporting tool, and undo capability.

Access Control Lists (ACLs)

In additional to conventional Unix file permissions, Solaris supports access control lists for files and directories. Using ACLs, you can define default and specific permissions for the file or directory owner, group, others, and for specific users or groups.

The getfacl and setfacl commands can be used to view and set file ACLs, respectively.

Solaris Cryptographic Services

Solaris includes a central framework of cryptographic services for kernel-level and user-level consumers, such as Internet Key Exchange (IKE), Kerberos, IPsec, and end-users encrypting/decrypting data.

The framework includes user-level, kernel-level, and hardware plugins.

# cryptoadm list user-level providers: /usr/lib/security/$ISA/ /usr/lib/security/$ISA/ kernel software providers: des aes arcfour blowfish sha1 md5 rsa kernel hardware providers:

Solaris Authentication Services

Solaris includes support for various authentication services and secure communication mechanisms:

While PAM is widely used on many systems today, it was introduced on Solaris. PAM provides a uniform abstraction (through a library interface) for a number of authentication mechanisms. Thus, if an authentication mechanism changes, or a new one is introduced, services that use these mechanisms would not need to be modified.

Securing the PROM

On SPARC hardware, you can gain access to the OpenBoot PROM, even while the operating system is running (using the Stop-A keyboard sequence). This has obvious (and some non-obvious) security implications, such as:

Thus, the administrator must protect access to the PROM with a password, or must disable breaking into PROM entirely.

Preventing Stack Executability

You can set the noexec_user_stack system variable to 1 in /etc/system to mark the stack of every process in the system as non-executable. Attempts to execute "code" from the stack will result in a SIGSEGV (segmentation fault). Moreover, such attempts can be logged by setting noexec_user_stack_log to 1.

Note that this feature is available on SPARC and AMD64, but not IA-32, as the latter does not implement a per-page execute bit in hardware.

Automated Patching

Solaris includes support for downloading, verifying the signatures of, and installing patches automatically, possibly based on a specified criteria (for example, installations of those patches that would not require a system reboot).

<<< Sandboxing main Miscellaneous >>>