Securing
Linux Systems with grsecurity
Keith McDuffee
As systems administrators know, there are a multitude of open
source tools available for securing a Linux system. Most of these
tools are installed and run on top of the operating system, either
executing at given intervals via cron, in the background as a daemon,
or directly triggered by specific activity.
grsecurity is another open source security package available for
Linux, but it works quite a bit differently from applications executing
in user space. Instead, grsecurity works primarily as a set of patches
that are applied to the 2.4 Linux kernel, improving upon system
security with more restricted process privileges, enhanced OpenBSD-like
entropy pools, additional auditing capabilities, chroot and buffer
overflow protections, and additions designed to thwart portscans
and OS fingerprinting.
What Does It Do?
Rather than running specific tools to detect security breaches
or vulnerabilities in a Linux system, grsecurity works by implementing
process restrictions through the patched kernel, essentially invisible
to any user. grsecurity goes further by imposing restrictions not
only on basic users of a running system, but also on privileged
accounts such as root.
The possibility always exists that an installed program can yield
unexpected results because of programming bugs or improper configuration
or implementation of features. Once these flaws are located and
exposed, an attacker can use the vulnerabilities for malicious intent,
sometimes gaining elevated privileges in the process. As a set of
patches to the actual kernel, grsecurity attempts to thwart these
attacks by applying itself to all applications.
One of the advanced features of grsecurity is protection from
stack overflow exploits by including a complete implementation of
non-executable pages. This feature ensures that no arbitrary code
can be executed by disallowing an area of memory from ever having
write and execute ability. In the past, if a malicious user was
successful in causing a stack overflow on an application that stored
data temporarily on the stack or heap, it was sometimes possible
to cause the new stack data to execute and crash. If the original
code was running at an elevated privilege, this in turn could allow
the user to gain root access, and of course everything would tumble
downhill from there. grsecurity prevents this scenario by prohibiting
execution from unauthorized memory areas. There are several other
similar improvements that prevent applications and users from executing
unintentional functions, further improving the chances that familiar
exploits are not located and used on your system.
grsecurity takes further steps in locking down a chroot'ed environment,
beyond those that exist in default setups. For example, in the original
implementation of chroot, it's possible for the root user to escape
from a "chroot jail" by using a program similar to the following:
int main()
{
chdir("/");
mkdir("foo");
chroot("foo");
chdir("../../../../../../..");
chroot(".");
execl("/bin/sh", "sh", (char *)0);
}
One of grsecurity's options is to enforce chdir(/) on all chroots,
eliminating the possibility of this behavior. There are also additional
restrictions available for chroots, such as denying the use of mknod
to create device entries, disallowing double-chroots to break out
of chroot jails, protecting outside processes (hiding their existence
to processes inside the jail), and denying chrooted processes from
mounting or remounting filesystems. These options are invaluable,
particularly to Web, mail, and DNS servers, where chroot'ed environments
are often used, and the elimination of these abilities makes perfect
sense.
There are other features that may be a bit more noticeable upfront,
such as the utilization of randomized PIDs (Figure 1), IP IDs, and
TCP source ports (Figure 2). Randomized PIDs are particularly effective
when used in conjunction with grsecurity's /proc restrictions, disallowing
users from guessing PIDs of privileged applications and daemons.
In some cases, PIDs are used by applications for naming temporary
files, where merely locating a given PID would help one predict
the name of the next successive filename; randomized PIDs make these
predictions much more difficult.
Additionally on the network side, grsecurity provides a "stealth"
networking module to iptables. Essentially when this module is activated
(via an iptables ruleset), it matches any UDP or TCP packets destined
for unserved ports on the system. These packets are then dropped,
effectively slowing down port scanners set to search for blocked
ports. Although usually not all that common in secured environments,
this feature is particularly useful on systems where a default rule
of DROP isn't possible because of users running their own servers
on ports that are difficult to track.
If you're interested in utilizing the ACL (Access Control List)
system of grsecurity, you may be interested in enabling grsecurity's
Sysctl support (CONFIG_GRKERNSEC_SYSCTL), as it will give you the
ability to change the options that run with grsecurity at boot time
without having to recompile your kernel. With this option, by echo'ing
0 (off -- the initial default for all options) or 1 (on) to the
files located in /proc/sys/kernel/grsecurity, you can easily enable
or disable the features you want. Once the grsec_lock file
contains 1, no further configuration is possible without
a reboot. Note that if you choose to enable Sysctl support, the
effectiveness of grsecurity's added security can be significantly
reduced without the presence of the ACL system.
Some additional enhancements of note:
- Dmesg restriction: Denies non-root users from using dmesg(8)
to view up to the last 4Kb of messages in the kernel's log buffer.
- Larger entropy pools: Doubles the size of the Linux and grsecurity
entropy pools, similar to modifying /proc/sys/kernel/random/poolsize.
- Linking restrictions: Disables the ability to follow symlinks
owned by other users in world-writable +t directories (i.e., /tmp)
or hardlink to files the user does not own.
- FIFO restrictions: Denies users from writing to FIFOs they
don't own in world-writable +t directories.
- Altered ping IDs: Ping replies will use an ID equal to the
ID of the echo request, helping to confuse OS detection.
- Logging options: Mount logging, chdir logging, IPC logging,
signal logging, fork failure logging, and time change logging,
among others.
- Additional ACL options: Hiding kernel processes.
- Kernel symbol hiding and non-executable user and kernel pages:
Helps stop many exploits in the kernel itself.
Installing grsecurity
grsecurity is updated religiously to be compatible with the latest
release of the 2.4 Linux kernel. You will need to download the latest
2.4 kernel sources from:
http://www.kernel.org/
before applying the patches. You'll also want to obtain the latest
iptables sources from:
http://www.netfilter.org/downloads.html
For the full grsecurity package, grab the two sets of patches (grsecurity
and iptables patch) and the gradm utility from:
http://www.grsecurity.net/download.php
Next, unpack the kernel and iptables sources and apply the patches:
# cd /usr/src
# tar xvfz linux-2.4.20.tar.gz
# patch -p0 < grsecurity-1.9.9f-2.4.20.patch
# bunzip2 < iptables-1.2.8.tar.bz2 | tar xvf -
# patch -p0 < grsecurity-1.2.8-iptables.patch
When you configure the newly patched kernel with make menuconfig,
you'll notice a new section added to the bottom of the options list,
aptly titled "grsecurity" (Figure 3). There is an additional module
for Netfilter that handles the new "stealth" matching located under
"Networking Options->IP: Netfilter Configuration->stealth match
support", which needs to be selected separately for installation if
you want this capability.
This new section contains the various options available with grsecurity.
You can simply choose among the three levels of grsecurity (low,
medium, and high -- see Figure 4), or you can customize with the
numerous options available. If you're not experienced with grsecurity,
you'll likely want to avoid starting off with using the "high" level,
as it will be more difficult to determine which components are causing
grief should a problem with the installation arise. In my testing,
using the "medium" or "low" levels worked best, with no application
or daemon startup issues. Figure 3 shows a listing of what comprises
each level, however, there are a few options not included in any
of the levels that must be chosen individually if desired.
Once you've chosen the grsecurity options you want and have configured
the rest of the kernel to meet your needs, you can compile and install
it:
# make dep && make clean && make
# make modules && make modules_install && make install
Be sure to edit your LILO or Grub configuration to allow you to choose
from the new or existing kernel at boot time in case something goes
wrong with the installation. If your first attempts at booting fail
from the grsecurity kernel, which may happen on occasion when enabling
the ACL options, try rebooting into the old kernel, then reconfigure
and recompile grsecurity with different options. If you did not enable
the ACL system, you can now boot into the new kernel, otherwise you'll
first need to proceed through the next step.
Using the ACL system
An ACL system provides detailed control of access privileges to
your system. Such a system is used to further restrict access to
files, resources, sockets, or other capabilities to every user on
the system, including root. While the primary features of grsecurity
help protect against unauthorized access to root, the ACL system
takes the next step in protecting beyond a potentially successful
attack. Essentially, once a user gains root access, he or she does
not have complete access to the system.
If you've chosen to enable the ACL portion of grsecurity, you'll
need to build the gradm utility downloaded from the grsecurity site:
# gradm-1.9.9h.tar.gz
# cd gradm
# ./configure
# make && make install
...
Setting up grsecurity ACL password
Password:
Re-enter Password:
Password written to /etc/grsec/pw.
Note that gradm is installed into /sbin by default. gradm will automatically
detect where it is being executed and auto-secure itself. Also note
that once you enable the ACL system with gradm, you must use the same
binary to disable or reload the system.
The configuration file for the ACL system is located at /etc/grsec/acl,
containing the following structure:
<path of subject process> <optional subject modes> {
<file object> <optional object modes>
[+|-]<capability
<resource name> <soft limit> <hard limit>
connect {
<ip>/<netmask>:<low port>-<high port> <type> <proto>
}
bind {
<ip>/<netmask>:<low port>-<high port> <type> <proto>
}
}
The configuration file must at least contain a subject ACL for /,
but as you can see from the initial file created by the installation
of gradm, there are far more ACLs you'll want to configure to achieve
the full effect of the system.
As a brief example, consider a portion of the first subject process:
/ {
/ r
/opt rx
/home rwx
/var/log r
/dev
...
}
Simply stated, this base ACL pertains to all applications unless an
exception is made. In this case, applications are only permitted to
read files in /, read/execute files in /opt, read/write/execute files
in /home, read files in /mnt, and have no access to files within /dev.
Once we put an exception ACL in place under this, we can carefully
refine which applications can go beyond these initial rules:
/sbin/syslogd {
/dev/log rw
/var/log w
}
With this ACL, we're allowing the syslogd daemon to make an exception
to the rules put on /dev and /var/log in the first ACL. Obviously
this is necessary for syslogd to function properly. There are many
of these ACLs in the default file, and there's sure to be a few more
you'll want to add or edit before proceeding.
The gradm utility is used to enable (gradm -E) or disable
(gradm -D) the ACLs, as well as administrate the ACLs for
short periods of time (gradm -a). Any action that disables
the ACLs will require the password you initially entered upon installation
of gradm, which can also be changed with the same utility (gradm
-P).
There are far more options and capabilities that aren't mentioned
here. A good place to start would be to read the ACL documentation
on the grsecurity's site:
http://www.grsecurity.org/gracldoc.pdf
Make sure you fully understand the implications of enabling ACL and
the full set of options that must exist in the configuration file.
It's very easy to miss something and cause programs to fail if great
care isn't taken in this task.
Stealth Networking Support
As previously mentioned, also packaged with the grsecurity patches
is support for "stealth" packet matching. Enabling this option in
the kernel configuration will drop all syn packets coming to unserved
TCP ports, as well as any packets coming to unserved UDP ports on
the network. To make full use of this feature, you will need to
install your previously patched iptables sources:
# cd /usr/src/iptables-1.2.8
# make clean
# make && make install
This will place the new iptables user executable into /usr/local/sbin
by default, so you will need to update your startup scripts to point
to the new location. Once you have booted into the new grsecurity-patched
kernel and have installed the stealth module, you can make use of
the new feature in your iptables startup file.
If you are using your system to route any type of packets (i.e.,
via NAT), you should put these at the end of your ruleset, since
it will drop packets that aren't going to ports that are listening
on your system itself. In the case of NAT, the module doesn't take
into account that the packet might be destined for someone on your
internal network.
Here's an example of a portion of an iptables startup script:
---
#!/bin/csh
set IPTABLES = /usr/local/sbin/iptables
$IPTABLES -N stealth-n-log
$IPTABLES -A stealth-n-log -j LOG --log-level 4 --log-prefix
"stealth-n-log:"
$IPTABLES -A stealth-n-log -j DROP
## Input/Output accept rules go here
$IPTABLES -A INPUT -p tcp -m stealth -j stealth-n-log
$IPTABLES -A INPUT -p udp -m stealth -j stealth-n-log
---
With the above rules activated, if someone were to portscan your system
(with nmap for example), you'd see something like this in your logs:
stealth-n-log:IN=eth1 OUT= MAC=00:e0:18:2e:9c:3a:00:20:78:c9:f5:b8:08:00
SRC=192.168.1.101 DST=192.168.1.108 LEN=60 TOS=0x00 PREC=0x00 TTL=51
ID=26988 DF PROTO=TCP SPT=28920 DPT=30 WINDOW=5840 RES=0x00 SYN URGP=0
stealth-n-log:IN=eth1 OUT= MAC=00:e0:18:2e:9c:3a:00:20:78:c9:f5:b8:08:00
SRC=192.168.1.101 DST=192.168.1.108 LEN=60 TOS=0x00 PREC=0x00 TTL=51
ID=33605 DF PROTO=TCP SPT=15569 DPT=366 WINDOW=5840 RES=0
x00 SYN URGP=0
If your iptables did not contain stealth rules, from the
attacker's side, an nmap scan on your system would look something
like this:
---
# nmap -P0 192.168.1.108 -p 5003-5009
Starting nmap V. 3.00 ( www.insecure.org/nmap/ )
All 7 scanned ports on no-grsecurity (192.168.1.108) are: close
d
Nmap run completed -- 1 IP address (1 host up) scanned in 1 second
---
While a scan on a stealth protected system would look like this:
---
# nmap -P0 192.168.1.101 -p 5003-5009
Starting nmap V. 3.00 ( www.insecure.org/nmap/ )
Interesting ports on no-grsecurity (192.168.1.101):
Port State Service
5003/tcp filtered unknown
5004/tcp filtered unknown
5005/tcp filtered unknown
5006/tcp filtered unknown
5007/tcp filtered unknown
5008/tcp filtered unknown
5009/tcp filtered unknown
Nmap run completed -- 1 IP address (1 host up) scanned in 48 seconds
---
Note the length of time the nmap scan took on both systems. These
results can be somewhat unexpected on the attacker's end, causing
them to at least have to reevaluate their methods.
grsecurity in Practice
Not every Linux system will necessarily benefit a whole lot from
the use of grsecurity. The more exposed a system is to outside access,
the more grsecurity makes sense. If a particular server can get
away with the access controls put in place, it's certainly a consideration.
grsecurity helps implement file system and process protection
not existing in the default 2.4 Linux kernel, and also provides
ports of several 2.2 kernel enhancements. Particularly for shared
use systems, the ACL system can be invaluable where many users have
shell access. The enhancements to the chroot jail are particularly
useful for Web, ftp, and DNS servers that are often executed chroot'ed.
For anyone who has compiled the Linux kernel before, installing
the grsecurity patches should be relatively easy. One possible downside
of grsecurity is lack of support for slightly earlier kernels or
iptables, requiring you to update to the latest sources should you
want to use the currently available version of the patches. Choosing
the appropriate options for your needs and implementing the ACLs
can also be tricky. The grsecurity folks did an excellent job commenting
each of the configuration options, so be sure to check them all
out, as well as the ACL documentation, before committing to anything.
Resources
http://www.grsecurity.org/
http://freshmeat.net/projects/grsecurity/
http://pageexec.virtualave.net/
Special thanks to Brad Spengler (spengler@grsecurity.net)
of grsecurity for his assistance.
Keith McDuffee (gudlyf@realistek.com) has been a Network
and Systems Administrator for more than 10 years and is currently
employed as the IT Manager for Etnus in Natick, Massachusetts.
|