OpenBSD PF Developer Interview, Part 2
Pages: 1, 2, 3, 4
Federico: What type of bpf security extensions have been
introduced?
CEA: bpf is a device designed to capture
packets from an interface. It has a filter language for selecting a subset of
packets to be read, used mainly for performance reasons. bpf also
contains some functionality for injecting packets into the network.
Programs use bpf by opening one of the
/dev/bpfX devices, and obtaining a file descriptor. The
access to the devices is restricted to root by default (through file
permissions). The problem happens when a program wishes to drop privileges, or
use privilege separation, after obtaining a bpf descriptor.
Even with dropped privileges, a program can change the filters, and the
interface and, thus sniff any interface on the host. Furthermore, if
the descriptor was opened with write access (some daemons require this, and
libpcap does this by default) it is possible to inject packets to
any of the available interfaces.
This had to be solved before any bpf-using program can be safely privilege separated. Two security mechanisms were introduced:
write filtering allows setting
bpffilters for write operationslocking prevents "dangerous" changes to the descriptor such as modifying the read/write filters, and changing the interface. Obviously the descriptor cannot be unlocked once it is locked.
If the descriptor is properly configured and locked before dropping
privileges, an exploit will not be able to further compromise the system
through the bpf descriptor.
Federico: I've read this thread
on the misc@ mailing list and I'm wondering what are the advantages of
tcpdump privilege separation?
CEA: Network data is untrusted, and parsing them into a
readable form is difficult and error-prone, especially for complex or obscure
protocols, thus tcpdump (and most other sniffers) are complex and
potentially dangerous pieces of code. A look at recently discovered
vulnerabilities in such programs should give an idea. Even saved binary files
may not be safe, and could act as time bombs. Privilege separation is used in
these programs to isolate the dangerous packet parsing code into an
unprivileged chroot jail.
At this point running tcpdump as root in OpenBSD is much more
safer than running it unprivileged, since being root allows it to properly
privsep. Hopefully this will be improved to cover unprivileged use, possibly
using setuid after we resolve some signal issues. Yes, there is an irony here,
making a program setuid root to make it safer :)
Federico: Can, could you provide a short history of pflogd?
CEA: The logging mechanism in pf is ingenious. Saving the
raw packet dumps loses minimum information, (usually) uses less space than
ASCII logs, and allows the logs to be analyzed using a variety of tools,
including passive OS fingerprinting recently added to our tcpdump,
and all the other cool analyzers/sniffers available.
The first version of pflogd is imported into the three about 2
months after the pflog interface. It had a basic functionality:
dump the logs to a file in binary tcpdump format, make sure the
existing file has the correct header before appending, handle SIGALRM for
flushing logs, and SIGHUP for re-opening the log files for working correctly
with log rotation.
At the last hackathon, right after OpenBSD 3.3 is released I have added
support for the new pflog format. pflogd supports
both, but refuses to overwrite an old file and outputs a 'Move away' warning to
the syslog.
After OpenBSD 3.4 is released, the bpf extensions was ready,
so pflogd was privilege separated. The privileged parent handled
the bpf descriptor stuff and opening/positioning of log files,
while the child running chrooted under _pflogd user is used for
logging.
Later, (January 2004) it was noticed that the pflogd files may
become corrupted if the partition gets full, or after an unclean shutdown. In
this case some or all of the appended logs would become unreadable.
pflogd now scans the complete log file, and detects corruption,
and gives the "Move away" warning, refusing to append until the log is moved or
rotated away.
Future: I have a (half forgotten) diff that handles the infamous "move away" part by renaming the existing log if a problem is detected. I have also not yet abandoned my plans for having ASCII pflogs. tcpdump is
safe, and more powerful than anything I could put into pflogd, but
lacks the rotation functionality.
Federico: Can, could you provide a short history of the PF logs format?
CEA: The pf logs contain a header and the logged packet itself. In the initial version, the header length was fixed, and very simple. It contained "interface, direction, action, a rule number" and a sub reason (why passed or dropped). This old format contained an unofficial link type (an identifier that determines the interface type and header format) and having a fixed length with no empty fields, it was not extendable.
After 3.3, we have improved the format to contain anchor and ruleset names
and a header length field which will allow the format to be extended later as
required. We have also changed the link type to the official id obtained from
the libpcap/tcpdump maintainers.
Federico: The PF log format has changed over time. Do other operating systems
or common software such as ethereal and the standard
tcpdump support this format?
CEA: I have contributed patches to ethereal,
and snort also supports the format. The standard tcpdump includes
support to the new format since tcpdump_3_8rel2 (although they
dropped backward compatibility to the old format).



