2.1. Filesystem Protections

 < Day Day Up > 

Anyone familiar with Unix operating systems knows about standard Unix file permissions that have been around since the earliest days. They specify what one user, one group, and everybody else may do with a file, directory, or device. They identify only three possible actions: read, write, and execute. It's somewhat sad that after so many years, there are no more sophisticated means of controlling permissions that are standard across all Unices. A variety of proprietary controls have been developed over the years, but each is typically implemented in only one Unix. Most operating systems are still unique in what filesystem permissions they offer, and only the three read-write-execute bits are common to all.

2.1.1. Overview

FreeBSD and OpenBSD (along with NetBSD and Mac OS X) use some derivative of the BSD "Unix filesystem" (UFS). In addition to the standard Unix permissions that are common across all Unices, these BSD systems also implement special filesystem flags that can change the operating system's behavior with respect to certain files. The flags help a system administrator protect key files from misuse and corruption.

In recent years, FreeBSD has evolved UFS to Version 2 (UFS2), incorporating POSIX 1/e access control lists (ACLs) at about the same time. These more advanced discretionary access controls add further, fine-grained control over permissions. Different users can be given different sets of permissions without relying on traditional Unix groups.

The intended use of your system will determine where and when flags or ACLs make the most sense. If you're maintaining a server with many interactive users, ACLs probably make sense because of their flexible permission structure. If your system is more like a dedicated server, the flags will probably be all you need. Flags are one-size-fits-all by nature.

2.1.2. UFS Filesystem Flags

Flags are coarse-grained, but very carefully defined, controls on how a file can be modified, and how it should be handled in backups. Unlike traditional permissions or ACLs, flags enforce the same behavior for all users. If the immutable flag is set on a file, for example, no one can write to it not even root. The BSD kernel is responsible for enforcing these controls, and your ability to adjust varies, depending on your kernel securelevel (see "Kernel Security Level," later in this chapter). In particular, several flags cannot be unset once the kernel securelevel is raised above zero. If your system runs at a securelevel less than 1, the flags are of only moderate value. An attacker who can compromise the root account can unset these flags at will, but they will certainly impede automated attacks like rootkits. Although you can't turn them off whenever you want, you can set flags on an unflagged file at any time, regardless of the kernel's current securelevel.

2.1.2.1 Manipulating flags

Flags are set with the chflags(1) command. Naming a flag will set it, and prepending "no" to the flag's name will unset it. For example, to set the system immutable flag on /kernel, you run chflags schg /kernel. To unset it, you run chflags noschg /kernel. The nodump flag is an exception to this convention, since its primary function is to prevent files from being dumped (see "nodump flag," later in this chapter). It is turned on with nodump and turned off with dump. For example: chflags dump /var/db/foo.

Specifying 0 in place of a flag name will turn off all the flags on a file. It's an inelegant little shortcut, but it works. For example, chflags 0 foo will turn off all the flags on the file foo.


To view the active flags on a file, use the -o argument to the ls(1) command. Example 2-1 shows a /var/log directory with a variety of file flags highlighted. Note that this is a contrived example: logfiles with flags set this way could not effectively be rotated, deleted, or otherwise archived.

Example 2-1. Example output of ls -lo in a contrived /var/log
-rw-------  1 root  wheel  sappnd  1862 Sep 30 22:39 auth.log -rw-------  1 root  wheel  sappnd 38374 Sep 30 22:45 cron -rw-------  1 root  wheel  nodump  3157 Sep 30 03:06 dmesg.today -rw-r--r--  1 root  wheel  sappnd 28056 Sep 30 22:39 lastlog -rw-r--r--  1 root  wheel  -          0 Jun  4 21:57 lpd-errs -rw-r-----  1 root  wheel  sappnd  2160 Sep 30 03:06 maillog -rw-r--r--  1 root  wheel  sappnd 15547 Sep 30 22:47 messages -rw-r-----  1 root  mail   sappnd   628 Sep 30 03:06 sendmail.st -rw-r-----  1 root  mail   schg    3455 Sep 29 22:00 sendmail.st.0 -rw-r-----  1 root  mail   schg    5543 Jun  4 21:57 sendmail.st.1

Table 2-1 lists the flags, who can set them, and a brief description of what they do. They are listed in relative order of usefulness, with the most useful flags first.

Table 2-1. UFS filesystem flags

Flag

Can be set by

Behavior

schg

Root only

System immutable. No part of it can change, not even metadata. Root cannot unset this flag unless the system is in single-user mode or the system is at securelevel 0 or less.

uchg

Owner or root

User immutable. Like the schg flag, above, but can be set and unset by root and the file's owner.

nodump

Owner or root

Skip dump. Tell the dump(8) program not to include a file when it backs up a filesystem.

sappnd

Root only

System append only.No one may truncate the file or write to it at any point other than its end. It can be read at any point, but only written at the end.

uappnd

Owner or root

User append only. Like the sappnd flag, above, but can be set and unset freely, both by root and the file's owner.

sunlnk

Root only

System unlink. No one, not even root, can unlink (delete) the file, regardless of the permissions on the parent directory or file.

uunlnk

Owner or root

User unlink. The owner cannot unlink (delete) the file, regardless of the Unix permissions on the parent directory or file.

opaque

Owner or root

Opaque directories. Set only on directories. Makes them opaque when directories are unionfs mounted on top of them, i.e., underlying filesystems will not "show through," just like a typical mount-over.

arch

Root only

Archive. The archive flag is not used.


2.1.2.2 System immutable flag (schg)

This flag is the workhorse of filesystem security. Despite the fact that its abbreviation, schg, is derived from "system change," it is universally referred to as the "immutable" flag. When the system immutable flag is set on a file, nothing can modify any part of it. Its metadata (modification times, permissions, owner, group, and so on) cannot be changed, nor can its contents. It cannot be renamed, unlinked (i.e., deleted), or moved, either. Nothing about it can change.

Directories can be made immutable also. They will be just as unalterable as a file, but this will have broader ramifications to the maintenance of the system. If your /usr/local/bin directory, for example, is immutable, then you won't be able to install any software in that directory while your system runs at a non-zero security level (see "Kernel Security Level," later in this chapter). The way around this limitation is to reboot into an insecure security level, unset the immutable flags, and then perform the installations. Once the installations are complete, you can run chflags to re-enable the immutable flags and then run sysctl(8) to increase the kernel security level to its normal level (see "Tweaking a Running Kernel: sysctl," later in this chapter).

2.1.2.3 User immutable flag (uchg)

The user immutable flag is a kinder, gentler immutable flag that is not affected by the kernel securelevel. Users can set and unset this on their own files and directories, just as root can. Unlike the system immutable flag, this one can be unset at any time. In order to be able to set this flag, you must be either the file's owner or root. A user with write access via Unix groups or ACLs, for example, still cannot set this flag.

This flag serves as a useful additional hurdle for an attacker and as a reminder to an administrator. The automatic tools favored by "script kiddies" will probably not account for the possibility that files are set immutable. Failures in their tools, then, give you an opportunity to spot their activities before they completely succeed, and it might even be enough to keep the unsophisticated script kiddies out entirely. When an administrator bumps into this flag, it helps to serve as a reminder that "the file you're changing is important. Be sure that you know what you're doing."

The one place all FreeBSD systems use this flag is on the kernel. It's added mainly as an extra security measure. It helps keep anyone, even root, from accidentally clobbering the /boot/kernel file. However, rather than inflict a system immutable file on an unsuspecting populace, the FreeBSD maintainers simply made it user immutable. It helps keep the novice administrator from doing something careless, but it doesn't prevent an experienced administrator from getting his job done.

2.1.2.4 Nodump flag (nodump)

Normally all files in a filesystem are backed up when the dump(8) program runs. The nodump flag tells the backup system not to include the given file in the dumps. Interestingly, it only affects incremental backups (dump level 1 and above) by default. To tell dump to honor the nodump flag, specify -h on the dump command line. If you want files to be omitted from backups entirely (i.e., not even included on full dumps), then you need to specify -h 0 on the command line.

Unfortunately, the nodump flag is binary, which makes it hard to have any mixture of behaviors. That is, it's hard to have some files completely omitted from backups while others are omitted only from the incrementals. If you really wanted to, though, you could make this work with some clever automated scripts.

Note that if you use Amanda (see ports/misc/amanda-server) or a similar software system to automate your backups, it may be a bit tricky to get the -h argument onto the command line.


Why would you use such a flag? One set of executives at a major educational institution has their email mailboxes explicitly omitted from the backup schedule. In their case, they are concerned about legal liability. Anything that exists on disk or backup tape can be the subject of a subpoena. These executives want email to be truly deleted if they delete it.

Database files are another example of files that might benefit from the nodump flag. They tend to be very large and always changing. They are not very useful to back up with dump, however, unless the database server is in a quiescent state while dump runs. The files are not usually in a consistent state if the database is actively reading and writing to them. Database files are often among the largest individual files on a system, and they have always been modified recently, so they always get included in incremental backups. This increases the time backups take to run, but they will not actually be very useful for restoration. To back up databases, you have to use a database replication scheme that is aware of the actual needs of backing up databases. Once that is in place, the nodump flag can be set on the database files to keep the dump program from doing a lot of needless work.

You can also set the nodump flag on directories that contain temporary data that is not worth preserving. For example, /tmp probably has nothing of long-term value in it. You probably don't need to back up /var/run, either. Then again, depending on your system, you might not save much time or tape space by omitting these directories.

2.1.2.5 System append-only flag (sappnd)

The append-only flag prevents files from being modified, much like the immutable flag, with one exception: data can be appended at the end of the file. The archetypal use of the append-only flag is for logfiles on secured servers or perhaps for root's .history file to help catch unwary hackers (see "Candidates for append-only," later in this chapter).

Note that when a file is marked append-only or immutable, it cannot be removed either. The only difference between immutable and append-only is the ability to append to the file. The flags are the same in all other respects.


2.1.2.6 User append-only flag (uappnd)

The user append-only flag performs exactly as the system append-only flag described above. The only difference is that this flag can be unset by both the owner and root at any time, regardless of the kernel securelevel. The fact that the flag can be unset does not make it useless for security purposes. It helps keep programs from clobbering logfiles or datafiles even when the Unix file permissions would allow it. It also allows non-root users to make use of this kernel feature for their own software. If you do not have non-root interactive users, you may not see a lot of use of this flag on your system.

2.1.2.7 System no unlink flag (sunlnk)

This flag is a little weaker than the schg flag. It simply prevents the deletion of a file. It is arguably most useful in its "user" version, uunlnk. It does not prevent truncation of the file or modification of its contents, its permissions, or any other aspect. It merely prevents the file from being removed.

Like other "system" flags, it can only be set by root, and it cannot be unset when the kernel security level is greater than 0. This flag exists only in FreeBSD.

2.1.2.8 User no unlink flag (uunlnk)

This flag allows a user to indicate that a file may not be deleted, regardless of the actual Unix permissions on its parent directory. Normally, if a user has permissions (through user, group, or ACLs) on the parent directory, she can delete any file in the directory even files she does not own. That's because, in Unix filesystems such as UFS, the permission for deleting a file is a function of modifying the directory, not the file itself. However, with this flag, the permission to unlink a file can be controlled by the file itself. A user can prevent his file from being deleted, even when the Unix permissions would otherwise permit it.

This flag can be set and unset freely by the file's owner and by root, regardless of the current kernel security level. This flag exists only in FreeBSD.

2.1.2.9 Opaque flag (opaque)

Opaque flags are used on directories or files that are involved in unionfs mounts (see mount_unionfs(8) on FreeBSD or mount_union(8) on OpenBSD). Union mounts allow one directory or filesystem to be mounted over the top of another directory while retaining visibility into the underlying directory. Thus, when you look in the top-level directory, you see the union of the two directories (hence the name). A file that exists in one place but not the other (XOR) will be visible. If there are files or directories of the same name in both places, the "uppermost" one is the one that is accessible.

When a directory is marked opaque with the opaque flag, it only shows files that actually exist in its level. That is, it makes the union mount act like a regular mount; files in the corresponding directory of a lower layer will be invisible.

The unionfs filesystem is not complete under FreeBSD. It does not fully work and it is dangerous to use. Do not use this feature until you check the documentation and see that it is supported and functional.


2.1.2.10 Archived flag (arch)

This flag has no official or default function. The dump program (you'd think dump would care) and all other programs ignore it. The fact that standard programs ignore it doesn't prohibit you from making use of it. It's like another bit that you can set and add your own meaning to.

2.1.3. Common Uses of Flags

It's probably obvious by the preceding discussion and by the functionality implemented in the flags that they were designed with specific tasks in mind. There are a few standard uses of flags that are worth mentioning.

2.1.3.1 Candidates for system immutable

There are many files that are commonly set system immutable. Your SSH configuration files in /etc/ssh are good candidates. If your SSH key is ever compromised, all your communications (which might include root passwords or other privileged passwords) can be compromised. Unless you suffer a major compromise or perform a significant upgrade to SSH itself, the SSH keys should remain the same for the life of the system. Likewise, root's .ssh/authorized_keys file (if it is used) or administrators' .ssh/authorized_keys files could be made immutable. This will stop an attacker from inserting her own authorized key or removing your access to the system by removing your key.

A workstation will probably have fewer files immutable than a core infrastructure server. The exception to this is if you establish a network filesystem infrastructure where software installations are all on a networked disk. In that case, the workstations can be locked down more tightly because the changes that users request probably take place on that networked fileserver, rather than at their desktops. Depending on how tightly you lock down the workstations, you may or may not choose to apply some of the following suggestions, which are more appropriate for core servers.

Lock down and make immutable all the directories that contain software binaries and libraries. These include:

/bin

/sbin

/usr/bin

/usr/sbin

/usr/lib

/usr/libexec

/usr/libdata

/usr/X11R6/bin

/usr/X11R6/lib

/usr/local/bin

/usr/local/sbin

/usr/local/lib

/usr/local/libexec

/usr/local/libdata

 


You probably will not have all of those directories, unless you are working on a user-oriented workstation. A system whose sole purpose is a VPN concentrator, for example, would probably not have the X11R6 directories.

There's an important difference between chflags -R schg /bin/* and chflags -R schg /bin. The former does not set the immutable flag on the directory itself. This allows an attacker to insert files in the directories. A malicious program named mroe in /bin is a devious, subtle attack if the administrator is prone to misspelling.


It's sometimes also useful to create "blocker" files that are immutable to prevent file-creation exploits from creating holes. Imagine a file-creation exploit that creates a ~root/.rhosts file containing +. Your rsh/rlogin daemons (that for some crazy reason you didn't disable yet) will now permit root logins from any system with no password (see rhosts(5) for more information). If you create the file, make it empty, and then make it immutable, you protect yourself from an attack like this. There is an equivalent ~root/.shosts file that is used by ssh; it could also be blocked this way.

Sidestepping Immutability

An aggressive administrator might mark all of the files in /etc immutable, make the /etc directory itself immutable, and enforce the flags by running in securelevel 2 (see "Kernel Security Level," later in this chapter). It turns out that, without rebooting, an attacker who achieves root access can still slip past these protections with a little bit of diligence. The following attack will allow you to take over an OpenBSD system that has been locked down this way. FreeBSD 4.x is similarly vulnerable, but FreeBSD 5.x is not.

  1. Make a copy of /etc (or whatever important directory you want to own). Be sure to use a tool or options that do not duplicate flag settings. Something straightforward like cp -pr is bad, but tar should work.

  2. Modify the files in your /etc copy to suit your needs.

  3. Mount an MFS filesystem over the existing /etc. For example:

    sudo mount_mfs -s 8192 /dev/wd0a /etc

  4. Copy your modified files into your clean-slate MFS /etc.

  5. Send HUP signals to any daemons whose configurations you replaced.

The daemons will reread their configuration files from your new version of the /etc directory, and they will follow your new configuration. This just goes to show that even options that seem pretty rigid, like filesystem flags, can sometimes be circumvented.

FreeBSD 5.x is not vulnerable because mount fails in any securelevel greater than 1.


2.1.3.2 Candidates for append-only

Remember that append-only is the same as immutable, except that the file can be appended. Your immediate intuition would be to set this flag on logfiles. If you did that, though, the files could not be rotated on an automated schedule. Append-only logfiles cannot be renamed, deleted, or moved just like immutable files. Being able to rename, move, or delete a logfile is tantamount to editing it. So, in general, you probably will not be setting your basic logfiles, like /var/log/maillog, to be append-only.

There are a few places where append-only files make sense. If you have specially designed your logging infrastructure so that you have a very large logging disk, and you want to be sure that your log is safe, the append-only flag can help. You could only rotate the logs at boot time, so that might motivate you to reboot on a somewhat regular schedule.

2.1.3.3 Finding files with flags

The find(1) command understands flags if you give it the -flags argument. For instance, this command finds all files that have the uunlnk flag set in user paco's home directory: find /home/paco -flags +uunlnk -print. Here's how you might do something interesting with find's flag awareness.

Remember how we said you could use clever scripting with the nodump flag to get some files included only in full backups, while others excluded entirely? You could use the arch flag (which has no defined purpose right now) to indicate the files that should be included in the full backups. Set the nodump flag on files that should never be dumped at all, and set both the nodump and the arch flag on files that should be included only in full backups. Always run dump with the -h 0 argument so all files with the nodump flag set will be excluded. On nights that you run full backups, run a find command like this before you run dump: find / -flags +arch -exec chflags dump '{}' \;. That finds all files that have the arch flag set, and turns off their nodump flag. After dump does its work, you can run a similar command to reverse these effects: find / -flags +arch -exec chflags nodump '{}' \;. Whenever you want to remove a file from your incrementals, you merely set the arch flag on it, and this scheme handles the rest.

2.1.4. POSIX Access Control Lists (FreeBSD Only)

Access control lists (ACLs) extend the well-known Unix file permissions to control, at a fine-grained level, the kind of access individual users or groups can have on particular files. They are new extensions to the Unix filesystem (UFS) and UFS Version 2 (UFS2). Both ACLs and UFS2 are only available under FreeBSD. The permissions governed by ACLs are still the traditional read, write, and execute permissions of Unix filesystems, but they can now be specified for arbitrary lists of users and groups. You're no longer constrained to set permissions for three populations: the owner, one group, and everybody else.

ACLs can be a boon for administrators who manage multiuser systems because users can manage the ACLs on their own files just like the administrator can. With ACLs, a system administrator doesn't have to know what federations of users are forming from week to week and then create Unix groups for them. Individual users can give and revoke access to whomever they choose, whenever they choose.

2.1.4.1 Enabling ACLs

Before anyone can use ACLs on any filesystem, you must make sure your kernel has the UFS_ACL option enabled. The generic FreeBSD kernel does, so unless you took it out when you built a custom kernel, you don't need to do anything special. This one option is sufficient whether you are using ACLs under UFS or UFS2 filesystems. The only time you have to worry about UFS filesystems, though, is if you are using an older FreeBSD system. UFS2 has been the standard filesystem since FreeBSD 5.1.

Once you have the kernel support built in, there are two ways to enable ACLs: using the /etc/fstab file or tagging the superblock directly.

2.1.4.1.1 ACLs in /etc/fstab

There is an acls option to mount that can be specified in /etc/fstab as shown in Example 2-2.

Example 2-2. Example /etc/fstab file with ACLs for /home
# Device    Mount   FStype  Options                         Dump Pass# /dev/da0s1b none    swap    sw                              0    0 /dev/da0s1a /       ufs     rw,userquota,groupquota         1    1 /dev/da0s1f /usr    ufs     rw,userquota,groupquota         2    2 /dev/da0s1e /home   ufs     rw,userquota,groupquota,acls    3    3 /dev/da1s1e /var    ufs     rw,userquota,groupquota         2    2 /dev/acd0c  /cdrom  cd9660  ro,noauto                       0    0

As you can see, the /home partition in this case has ACLs enabled.

2.1.4.1.2 ACLs in the superblock

Tagging the superblock is actually the preferred way to enable ACLs on the filesystem. It can only be done, however, using the tunefs(8) command; and tunefs can only do its job on an unmounted filesystem. If you want to do this, you will have to take your system down to single-user mode, or umount the idle filesystem, in order to run it. For example, to enable ACLs on the /home filesystem, you would umount it, and run tunefs -a /home. The superblock tag is the best way to enable ACLs because it cannot easily be removed from the filesystem. A typo in /etc/fstab or filesystem changes could inadvertently cause the acls flag to be omitted at mount time. However, the ACL flag in the superblock will never be overlooked by mount.

2.1.4.2 Managing ACLs

The setfacl(1) and getfacl(1) commands allow you to manipulate the ACLs on files. Entries in the ACL can either be replaced wholesale or can accumulate. Each time setfacl is run, it can append a new access specifier to the access control list, replace an existing entry on the list, or replace the entire list with a new list specified on the command line.

As an example, let's assume we have a file book.pdf, and we want three users (paco, yanek, and bruce) to have read and write access to it. Let us also suppose that the Unix group editors should have read access to this file, and no one else should have any access. In traditional Unix, we could not actually enforce such permissions there is no way to give three users write permission while giving a Unix group read-only permission. With ACLs enabled, Example 2-3 shows the series of commands that will establish exactly that permissions structure on book.pdf.

Example 2-3. Setting ACLs with setfacl(1)
% setfacl -b book.pdf             # Erase any existing ACLs % setfacl -m u:paco:rw book.pdf   # Add Paco's access %  # Now do Bruce and Yanek in one (contrived) command % setfacl -m u:bruce:rw -m u:yanek:rw book.pdf % setfacl -m g:editors:r book.pdf # Give the Unix group editors read access % setfacl -m o:: book.pdf         # Nobody else gets any permission at all

The specifier for the ACL entry is three elements delimited by colons: a letter, a user or group, and then the access to grant that user or group. The letters u, g, and o are very similar to chmod(1) and indicate what you'd expect: user, group, and other, respectively. Naturally there is only one "other" entry. There can be an arbitrary number of user or group permission entries. The specifier in between the colons is either the name of a user, the name of a group, or nothing. In the case of a user or group entry, omitting the user or group name implies that the ACL entry applies to the file's current owner or group. For symmetry, the "other" ACL entry has two colons, but nothing can go between them. After the second colon come the permissions specified with r, w, and x, again just like with chmod.

To see the ACL for a file, use the getfacl command as shown in Example 2-4. It shows the access control list for the book.pdf file we established in Example 2-3.

Example 2-4. Viewing the ACL of book.pdf using getfacl
% ls -l book.pdf -rw-rw-r--+ 1 www  www  0 Nov 23 04:12 book.pdf % getfacl book.pdf #file:book.pdf #owner:1001 #group:100 user::rw- user:paco:rw- user:yanek:rw- user:bruce:rw- group::r-- mask::rw- other::---

ACLs are subtle in a few ways. The only hint you have that a file has an associated ACL is a + after its Unix permissions in the output of ls -l as shown in Example 2-4. They also invisibly supercede the standard Unix file permissions. The output of ls -l might show a file readable by the editors group, and user gnat might be a member of editors, but if there is a specific ACL entry that denies user gnat read privileges on the file, he will be denied. Only the output of the getfacl command will explain why.

Both ACLs and flags can be confusing if they are used on an NFS file server. The NFS protocol has no means of transmitting ACL information from the server to the client. So the client will be denied permission because the ACL or the flags deny the action, but the client will have an incomplete picture of why it happened. Commands like getfacl and ls -lo will appear to work, but they will not actually show the true ACLs or flags. Commands like setfacl and chflags will fail on NFS mounted filesystems.


     < Day Day Up > 


    Mastering FreeBSD and OpenBSD Security
    Practical Guide to Software Quality Management (Artech House Computing Library)
    ISBN: 596006268
    EAN: 2147483647
    Year: 2003
    Pages: 142
    Authors: John W. Horch

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net