Tuesday, September 15, 2009

Episode #60: Proper Attribution

Hal starts off:

Back in Episode #54 we got a chance to look at the normal permissions and ownerships in the Unix file system. But we didn't have room to talk about extended file attributes, and that's a shame. So I thought I'd jot down a few quick pointers on this subject.

The Linux ext file systems support a variety of additional file attributes over and above the standard read/write/execute permissions on the file. Probably the most well-known attribute is the "immutable" bit that makes a file impossible to delete or modify:

# touch myfile
# chattr +i myfile
# lsattr myfile
----i-------------- myfile
# touch myfile
touch: cannot touch `myfile': Permission denied
# rm myfile
rm: cannot remove `myfile': Operation not permitted
# ln myfile foo
ln: creating hard link `foo' => `myfile': Operation not permitted
# chattr -i myfile
# rm myfile
As you can see in the above example, you use the chattr command to set and unset extended attributes on a file, and lsattr to list the attributes that are currently set. Once you set immutable on a file (and you must be root to do this), you cannot modify, remove, or even make a hard link to the immutable file. Once root unsets the immutable bit, the file can be modified or removed as normal. It's not uncommon to see rootkit installation scripts setting the immutable bit on the trojan binaries they install, just to make them more difficult for novice system administrators to remove.

But there are many other extended attributes that you can set on a file. For example, the append-only ("a") attribute means that you can add data to a file but not remove data that's already been written to the file. The synchronous updates attribute ("S") means that data that's written to the file should be flushed to disk immediately rather than being buffered for efficiency-- it's like mounting a file system with the "sync" option, but you can apply it to individual files. There's also a dir sync attribute ("D") that does the same thing for directories, though it's really unclear to me why this is a separate attribute from "S". The data journalling attribute ("j") is equivalent to the behavior of mounting your ext3 file systems with the "data=journal" option, but can be applied to individual files.

As you can see in the output of lsattr in the example, however, there are lots of other possible extended attribute fields. Many of these apply to functionality that's not currently implemented in the mainstream Linux kernels, like "c" for compressed files, "u" for "undeletable" files (meaning the file contents are saved when the file is deleted so you can "undo" deletes), "s" for secure delete (overwrite the data blocks with zero before deallocating them), and "t" for tail-merging the final fragments of files to save disk space. Then there are attributes like the "no dump" attribute ("d") which means the file shouldn't be backed up when you use the dump command to back up your file systems: "d" isn't that useful because hardly anybody uses the dump command anymore. There are also a bunch of attributes (E, H, I, X, Z) which can be seen with lsattr but not set with chattr.

So in general, "i" is useful for files you want to be careful not to delete, and "a" and possibly "S" are useful for important log files, but a lot of the other extended attributes are currently waiting for further developments in the Linux kernel. Now let's see what Ed's got going for himself in Windows land (and look for an update from a loyal reader after Ed's Windows madness).

Ed finishes it up:

In Windows, the file and directory attributes we can play with include Hidden (H), System (S), Read-only (R), and Archive (A). H, S, and R are pretty straightforward, and function as their name implies. The Archive attribute is used to mark files that have changed since the last backup (the xcopy and robocopy commands both have a /a option to make them copy only files with the Archive attribute set).

You can see which of these attributes are set for files within a given directory using the well-named attrib command. The closest thing we have to the Linux immutable attribute used by Hal above is the Read-Only attribute, so let's start by focusing on that one, mimicking what Hal does (always a dangerous plan).

C:\> type nul >> myfile

Note that we don't have a "touch" command on Windows, so I'm simply appending the contents of the nul file handle (which contains nothing) into myfile. That'll create the file if it doesn't exist, kinda like touch. However, it will not alter the last modified or accessed time, unlike touch. Still, it'll work for what we want to do here.

C:\> attrib +r myfile
C:\> attrib myfile
A R C:\tmp\myfile

Here, we've set the read-only attribute on myfile using the +r option, and then listed its attributes. Note that it had the Archive attribute set by default. We could specify a whole list of attributes to add or subtract in a single attrib command, such as +s -a +h and so on. Note that you cannot add and remove the same attribute (e.g., +r -r is forbidden).

Now, let's try to see how this attribute is similar to what Hal showed earlier for the immutable stuff:

C:\> type nul >> myfile
Access is denied.

C:\> del myfile
C:\tmp\myfile
Access is denied.

C:\> attrib -r myfile

C:\> del myfile

To remove all attributes, you could run:

C:\> attrib -h -s -r -a [filename]

Beyond attrib, we can also use the dir command to list files with certain attributes, using the /a option. For example, to list all hidden files, we could run:

C:\> dir /b /ah
boot.ini
Config.Msi
IO.SYS
MSDOS.SYS
NTDETECT.COM
ntldr
pagefile.sys
RECYCLER
System Volume Information

I used the /b option here to display the bare form of output so that I omit some clutter.

If you want to see non-hidden files, you could run:

C:\> dir /a-h

You can bundle multiple attributes together as well in dir using a slightly different syntax from the attrib command. With dir, you just smush together all the attributes you want to see, and indicate the ones you don't want with a minus sign in front of them. For example, if you want to see read-only files that are not hidden but that are also system files, you could run:

C:\> dir /ar-hs

A lot of people get thrown off by the fact that, by default, the dir command omits hidden and system files from its output. Consider:

C:\> type nul > myfile
C:\> type nul > myfile2
C:\> type nul > myfile3
C:\> attrib +h myfile
C:\> attrib +s myfile2
C:\> attrib +r myfile3

C:\> attrib
A H C:\tmp\myfile
A S C:\tmp\myfile2
A R C:\tmp\myfile3

C:\> dir /b
myfile3

This issue comes up rather often when playing the Capture the Flag game in my SANS 560 class on network penetration testing. Attendees need to grab GnuPG keys from target accounts, with the keys acting as the flags in the game. Rather often, folks get command shell on a target box, change into the appropriate directory for the GnuPG keys, and run the dir command. They see... NOTHING. Inevitably, a hand goes up and I hear "Someone deleted the keys!". I respond, "You know, GnuPG keys have the hidden attribute set...." The hand goes down, and the happy attendee snags the keys.

You see, the dir command with the /a option lets us specify a set of attributes we want or don't want. If you want to see all files regardless of their attributes, use dir with the /a option, but don't include any specific attributes in your list after the /a. That way, you'll see everything:

C:\> dir /b /a
myfile
myfile2
myfile3

With this functionality, some people think of the /a option of dir as meaning "all" or "anything", but it really is more accurate to think of it as "attributes" followed a blank list of attributes. In my own head, when I type "dir /a", I think of it as "Show me a directory listing with attributes of anything."

There's one last thing about attributes I'd like to cover. It's really annoying that the Windows file explorer doesn't show system files by default. This is a travesty. Darnit, I need to see those files, and hiding them from me is just plain annoying. I can accept hiding hidden files, because, well, they are hidden. But system files? Who thought of that? It makes Windows into its own rootkit as far as I'm concerned. Because of this, one of the first things I do with any Windows box I plan on using for a while is to tweak this setting. You can change it in the Explorer GUI itself by going to Tools-->Folder Options-->View. Then, deselect "Hide protected operating system files (Recommended)". Recommended? I guess Microsoft is trying to protect its operating system files from clueless users. Still, this is just plain annoying. Oh, and while you are there, you may as well deselect "Hide extensions for known file types", which is yet another rootkit-like feature that confounds some users when they are looking for files with specific extensions. And, finally, you may want to just go whole hog (is that kosher?) and select "Show hidden files and folders." There, now you have a Windows machine that is almost usable!


Hal's got an update from a loyal reader:

The fact that anybody with root privileges can undo your file attribute settings, makes "chattr +i" somewhat less useful from an absolute security perspective. Loyal reader Joshua Gimer took me to school regarding the Linux kernel capability bounding feature:

If you wanted to make a file immutable so that not even root could modify it you could perform the following after making your attribute changes:

lcap CAP_LINUX_IMMUTABLE


This setting could be changed back by anyone that has super-user privileges running the same command again. You could make it so that the kernel capability bounding set cannot be modified (not even by root) by issuing the following:

lcap CAP_SYS_RAWIO
lcap CAP_SYS_MODULE


This would require a system reboot to reintroduce these capabilities. You could then add these commands to /etc/rc.local, if you wanted them to persist through a reboot.


If you're interested in messing around with the lcap program, you can find the source code at
http://caspian.dotconf.net/menu/Software/Misc/lcap-0.0.6.tar.bz2


I had actually not been aware of this functionality before Joshua's message, so I went off and did a little research on my own. Turns out there's been a major change to this functionality as of Linux kernel 2.6.25. The upshot is that the global /proc/sys/kernel/cap-bound interface that the lcap program uses has been removed and kernel capabilities are now set on a per-thread basis. However, you can set capability bounding sets on executables in the file system. So if you want to globally remove a capability, the suggested method appears to be to set a capability bound on the init executable (using the setcap command) and have that be inherited by every other process on the system when you next reboot the machine. I have personally not tried this myself.

More info in the capabilities(7) manual page: http://manpages.ubuntu.com/manpages/jaunty/man7/capabilities.7.html