Making the programs in a distribution more resistant to exploits—a
process known as hardening—is a fairly common way to reduce the
attack surface for the distribution. Many distributions have made
an effort in this area, with some adding in an overall security architecture, like
AppArmor for SUSE or SELinux for Red Hat and Fedora distributions.
Debian is currently looking at enabling some hardening features,
potentially throughout a large swath of packages that it distributes. The
features being considered and the concerns raised provide an interesting
look at the tradeoffs.
A posting to
debian-devel-announce regarding hardening features for Lenny started
the conversation. Those packages that are most susceptible—network services, packages that parse files from
untrusted sources, or those that have been the subject of a security
alert—should enable a set of security tools that will help deflect
attacks against them. Various attacks rely upon certain characteristics of
Linux binaries that allow them to be exploited. By altering the way the
binaries are built, those particular threats can be mitigated.
The experimental hardening-wrapper
package makes enabling the various toolchain differences as easy as setting
DEB_BUILD_HARDENING=1 in the environment. This will change
gcc, g++, and ld to use the desired flags when
building packages. Each hardening feature can also be disabled separately
by setting DEB_BUILD_HARDENING_xyzzy=0 (where xyzzy is the name of
a hardening feature) if they cause build or
performance problems for a particular package.
The specific features enabled are described in the original posting as well
as with more detail on the Debian wiki entry for
Hardening. They are:
- using -Wformat to catch printf() family calls that do
not have a string literal for the format string which can lead to problems
if the argument came from an untrusted source and contains format specifiers.
- using -D_FORTIFY_SOURCE_ to validate glibc calls such as
strcpy() when the buffer sizes are known at compile time, which
can help stop buffer overflow attacks.
- using -fstack-protector to thwart most stack smashing attacks.
- creating Position Independent Executables (PIE) which facilitates using
the Address Space Layout Randomization that is available in some kernels.
This makes it difficult for an attacker to have any knowledge of what the
addresses for the program's sections will look like.
- using ld -z relro to change certain sections to be read-only
once ld has made its modifications while loading the program. This can
thwart attacks that try to overwrite the Global Offset Table (GOT).
Many other distributions have already been down this path: Gentoo
has a page describing their hardened toolchain, Mark Cox of Red Hat has
a detailed look
at the evolution of security features in Red Hat and Fedora releases,
OpenSUSE has a page
about its security features, and so on. There is a price to be paid in
binary size, execution speed, and cache behavior for these techniques, but
for most environments, where resources are not massively constrained, the
cost is worth it. It makes new attacks against those systems more
difficult to design, which will make users and administrators sleep a
little better at night.
to post comments)