Rute User's Tutorial and Exposition. 44. UNIX Security
Next: A. Lecture Schedule
Up: rute
Previous: 43. The X Window
  Contents
Subsections
This is probably the most important chapter of this
book.(footnote follows) [Thanks to Ryan Rubin for reviewing this chapter.]
LINUX has been touted as both the most secure and
insecure of all operating systems. The truth is both. Take no heed of
advice from the LINUX community, and your server will be
hacked eventually. Follow a few simple precautions, and it will be
safe for years without much maintenance.
The attitude of most novice administrators is ``Since the
UNIX system is so large and complex and since there are so many
millions of them on the Internet,
it is unlikely that my machine
will get hacked.'' Of course, it won't necessarily be a person
targeting your organization that is the problem. It could be a
person who has written an automatic scanner that tries to hack every
computer in your city. It could also be a person who is not an expert
in hacking at all, but who has merely downloaded a small utility to do it
for him. Many seasoned experts write such utilities for public
distribution, while so-called script kiddies (because the
means to execute a script is all the expertise needed) use these to
do real damage. [The word hack means gaining
unauthorized access to a computer. However, programmers
sometimes use the term to refer to enthusiastic work
of any kind. Here we refer to the malicious definition.]
In this chapter you will get an idea of the kinds of ways a UNIX
system gets hacked. Then you will know what to be wary of, and how
you can minimize risk.
I personally divide attacks into two types: attacks that can be
attempted by a user on the system, and network attacks that
come from outside of a system. If a server is, say, only used for mail
and web, shell logins may not be allowed at all; hence, the
former type of security breach is of less concern. Here are some of
the ways security is compromised, just to give an idea of what UNIX
security is about. In some cases, I indicate when it is of
more concern to multiuser systems.
Note also that attacks from users become an issue when a
remote attack succeeds and a hacker
gains user privileges to your system
(even as a
nobody user). This is an issue even if you do not host
logins.
Consider the following C program. If you don't understand C that well, it
doesn't matter--it's the concept that is important. (Before trying this
example, you should unplug your computer from the network.)
5
10
15
|
#include <stdio.h>
void do_echo (void)
{
char buf[256];
gets (buf);
printf ("%s", buf);
fflush (stdout);
}
int main (int argc, char **argv)
{
for (;;) {
do_echo ();
}
}
|
You can compile this program with
gcc -o /usr/local/sbin/myechod myechod.c. Then,
make a system service out of it as follows: For
xinetd, create
file
/etc/xinetd.d/myechod containing:
5
|
service myechod
{
flags = REUSE
socket_type = stream
wait = no
user = root
server = /usr/local/sbin/myechod
log_on_failure += USERID
}
|
while for
inetd add the following line
to your
/etc/inetd.conf file:
|
myechod stream tcp nowait root /usr/local/sbin/myechod
|
Of course, the service
myechod does not exist.
Add the following line to your
/etc/services file:
|
myechod 400/tcp # Temporary demo service
|
and then restart
xinetd (or
inetd)
as usual.
You can now run
netstat -na. You should see a
line like this somewhere in the output:
|
tcp 0 0 0.0.0.0:400 0.0.0.0:* LISTEN
|
You can now run
telnet localhost 400
and type away happily. As you can see, the
myechod service
simply prints lines back to you.
Someone reading the code will realize that typing more than
256 characters will write into uncharted memory of the program. How can
they use this effect to cause the program to behave outside of its
design? The answer is simple. Should they be able to write processor instructions
into an area of memory that may get executed later, they can
cause the program to do anything at all. The process runs with
root
privileges, so a few instructions sent to the kernel could, for example,
cause the
passwd file to be truncated, or the file system superblock
to be erased. A particular technique that works on a particular program is
known as an exploit for a vulnerability. In general, an attack of
this type is known as a buffer overflow attack.
To prevent against such attacks is easy when you are writing new programs.
Simply make sure that any incoming data is treated as being dangerous. In
the above case, the
fgets function should preferably be used, since it limits the
number of characters that could be written to the buffer. There are, however,
many functions that behave in such a dangerous way: even the
strcpy function writes up to a null character that may not be present;
sprintf writes a format string that could be longer than the buffer.
getwd is another function that also does no bound checking.
However, when programs grow long and complicated, it becomes difficult to
analyze where there may be loopholes that could be exploited indirectly.
A program is a legal contract with an impartial jury.
A program like
su must be
setuid (see Chapter 14).
Such a program has to run with
root privileges in order to
switch UIDs to another user. The onus is, however, on
su to
refuse privileges to anyone who isn't trusted. Hence,
su
requests a password and checks it against the
passwd file
before doing anything.
Once again, the logic of the program has to hold up to ensure security,
as well as to provide insurance against buffer overflow attacks. Should
su have a flaw in the authentication
logic, it would enable someone to
change to a UID that they were not privileged to hold.
Setuid programs should hence be considered with the utmost suspicion.
Most setuid programs try be small and simple, to make it easy to verify the
security of their logic. A vulnerability is more likely to be found in any setuid
program that is large and complex.
(Of slightly more concern in systems hosting many
untrusted user logins.)
Consider when your FTP client connects to a remote untrusted site. If
the site server returns a response that the FTP client cannot handle
(say, a response that is too long--a buffer overflow), it could allow
malicious code to be executed by the FTP client on behalf of the server.
Hence, it is quite possible to exploit a security hole in a client
program by just waiting for that program to connect to your site.
(Mostly a concern in systems that host user logins.)
If a program creates a temporary file in your
/tmp/ directory
and it is possible to predict the name of the file it is going to create,
then it may be possible to create that file in advance or quickly
modify it without the program's knowledge. Programs that create
temporary files in a predictable fashion or those that do not set
correct permissions (with exclusive access) to temporary files are
liable to be exploited. For instance, if a program running as superuser
truncates a file
/tmp/9260517.TMP and it was possible to
predict that file name in advance, then a hacker could create a symlink
to
/etc/passwd of the same name,
resulting in the superuser program actually truncating the
passwd file.
(Of slightly more concern in systems that host many
untrusted user logins.)
It is easy to see that a directory with permissions
660 and ownerships
root:admin cannot be accessed by user
jsmith if he is outside
of the
admin group. Not so easy to see is when you have thousands
of directories and hundreds of users and groups. Who can access what, when,
and why becomes complicated and often requires scripts to be written to do
permission tests and sets. Even a badly set
/dev/tty* device can
cause a user's terminal connection to become vulnerable.
(Of slightly more a concern in systems that host many untrusted user logins.)
There are lots of ways of creating and reading environment
variables to
either exploit a vulnerability or obtain some information that will
compromise security. Environment variables should never hold secret
information like passwords.
On the other hand, when handling environment variables, programs
should consider the data they contain to be potentially malicious and
do proper bounds checking and verification of their contents.
(Of more concern in systems that host many untrusted user logins.)
When
telnet,
ftp,
rlogin, or in fact any program at
all that authenticates over the network without
encryption is used, the password is
transmitted over the network in plain text,
that is, human-readable form.
These programs are all common network utilities that old UNIX hands were accustomed to
using. The sad fact is that what is being transmitted can easily be read off
the wire with the most elementary tools (see
tcpdump on page
). None of these services should be exposed
to the Internet. Use within a local LAN is safe, provided the LAN is
firewalled, and your local users are trusted.
This concept is discussed in Section 11.3.
A denial of service (DoS) attack is one
which does not compromise the system
but prevents other users from using a service legitimately. It can
involve repetitively loading a service to the point that no one else
can use it. In each particular case, logs or TCP traffic dumps might
reveal the point of origin. You might then be able to deny access with
a firewall rule. There are many types of DoS attacks that can be
difficult or impossible to protect against.
The preceding lists are far from exhaustive. It never ceases to amaze me how
new loopholes are discovered in program logic.
Not all of these exploits can
be classified; indeed, it is precisely because new and innovative ways of
hacking systems are always being found, that security needs constant
attention.
Security first involves removing known risks, then removing potential
risks, then (possibly) making life difficult for a hacker, then using
custom UNIX security paradigms, and finally being proactively cunning
in thwarting hack attempts.
It is especially sad to see naive administrators install packages that
are well known to be vulnerable
and for which ``script kiddy''
exploits are readily available on the Internet.
If a security hole is discovered,
the package will usually be updated
by the distribution vendor or the author. The
bugtraq <http://www.securityfocus.com/forums/bugtraq/intro.html>
mailing list announces the latest exploits and has many
thousands of subscribers worldwide. You should get on this mailing
list to be aware of new discoveries. The Linux
Weekly News <http://lwn.net/> is a possible source for security
announcements if you
only want to read once a week. You can then download and
install the binary or source distribution provided for that package.
Watching security announcements is critical. [I often ask
``administrators'' if they have upgraded the xxx service and
get the response, that either they are not sure if they need it, do not
believe it is vulnerable, do not know if it is running, where to get a
current package, or even how to perform the upgrade; as if their
ignorance absolves them of their responsibility. If the janitor were to
duct-tape your safe keys to a window pane, would you fire him?]
This goes equally for new systems that you install: never install
outdated packages. Some vendors
ship updates to their older distributions.
This means that you can install from an old distribution and then
upgrade all your packages from an ``update''
package list. Your packages would be then as secure as
the packages of the distribution that
has the highest version number. For instance, you can install RedHat 6.2 from a
6-month-old CD, then download a list of RedHat 6.2 ``update'' packages. Alternatively,
you can install the latest RedHat version 7.? which has a completely different
set of packages. On the other hand, some other vendors may
``no longer support'' an older distribution, meaning that those packages will
never be updated. In this case, you should be sure to install or upgrade with
the vendor's most current distribution or manually recompile vulnerable
packages by yourself.
Over and above this, remember that vendors are sometimes slow to respond
to security alerts. Hence, trust the free software
community's alerts over anything vendors may fail to tell you.
Alternatively, if you discover that a service is insecure, you may just want
to disable it (or better still, uninstall it) if it's not really needed.
Packages that are modified by a hacker can allow him a back door
into your system: so called Trojans.
Use the package verification
commands discussed in Section 24.2.6 to check package
integrity.
It is easy to locate world-writable files.
There should be only a few in the
/dev and
/tmp directories:
|
find / -perm -2 ! -type l -ls
|
Files without any owner are an indication of mismanagement or compromise
of your system. Use the
find command with
|
find / -nouser -o -nogroup -ls
|
It is obvious that variety in user passwords is more secure.
It is a good idea to rather not let novice users choose their
own passwords. Create a randomizing program to generate
completely arbitrary 8 character passwords for them.
You should also use the
pwconv utility from the
shadow-utils package to create the shadow password
files (explained in Section 11.3).
See
pwconv(8) for information.
Services that are inherently insecure are those that allow the
password to be
sniffed over the Internet or provide no proper authentication to begin with.
Any service that does not encrypt traffic should not be used for
authentication over the Internet. These are
ftp,
telnet,
rlogin,
uucp,
imap,
pop3, and
any service that does not use encryption
and yet authenticates with a password.
Instead, you should use
ssh and
scp.
There are secure versions of POP and IMAP
(SPOP3 and SIMAP),
but you may not be able to find good client programs.
If you really have to use a service,
you should limit the networks that are allowed to connect to it, as described
on page and .
Old UNIX hands are notorious for exporting NFS shares
(
/etc/exports) that are readable
(and writable) from the Internet. The
group of functions to do Sun Microsystems' port mapping and NFS--the
nfs-utils (
rpc....) and
portmap packages--don't
give me a warm, fuzzy feeling. Don't use these on machines exposed to the
Internet.
Install
libsafe.
This is a library that wraps all those vulnerable
C functions discussed above, thus testing for a buffer overflow attempt
with each call. It is trivial to install, and sends email to the administrator upon
hack attempts. Go to http://www.avayalabs.com/project/libsafe/index.html
for more information, or send email to
libsafe@research.avayalabs.com. The
libsafe library effectively
solves 90% of the buffer overflow problem. There is a very slight
performance penalty, however.
Disable all services that you are not using. Then, try to evaluate whether the
remaining services are really needed. For instance, do you really
need IMAP or would POP3 suffice? IMAP has had a lot more security alerts
than POP3 because it is a much more complex service. Is the risk worth it?
xinetd (or
inetd)
runs numerous services, of which only a
few are needed. You should trim your
/etc/xinetd.d directory (or
/etc/inetd.conf file) to a minimum. For
xinetd, you can add the
line
disable = yes to the relevant file. Only one or two files should
be enabled. Alternatively, your
/etc/inetd.conf should have only a
few lines in it. A real-life example is:
|
ftp stream tcp nowait root /usr/sbin/tcpd in.ftpd -l -a
pop-3 stream tcp nowait root /usr/sbin/tcpd ipop3d
imap stream tcp nowait root /usr/sbin/tcpd imapd
|
This advice should be taken quite literally. The rule of
thumb is that if you don't know what a service does, you
should disable it. See also Section 29.6.
In the above real-life case, the services were additionally limited to permit
only certain networks to connect (see page and
).
xinetd (or
inetd) is not the only problem. There are many
other problematic services. Entering
netstat -nlp
gives initial output, like
5
10
15
|
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:25 0.0.0.0:* LISTEN 2043/exim
tcp 0 0 0.0.0.0:400 0.0.0.0:* LISTEN 32582/xinetd
tcp 0 0 0.0.0.0:21 0.0.0.0:* LISTEN 32582/xinetd
tcp 0 0 172.23.80.52:53 0.0.0.0:* LISTEN 30604/named
tcp 0 0 127.0.0.1:53 0.0.0.0:* LISTEN 30604/named
tcp 0 0 0.0.0.0:6000 0.0.0.0:* LISTEN 583/X
tcp 0 0 0.0.0.0:515 0.0.0.0:* LISTEN 446/
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 424/sshd
udp 0 0 0.0.0.0:1045 0.0.0.0:* 30604/named
udp 0 0 172.23.80.52:53 0.0.0.0:* 30604/named
udp 0 0 127.0.0.1:53 0.0.0.0:* 30604/named
raw 0 0 0.0.0.0:1 0.0.0.0:* 7 -
raw 0 0 0.0.0.0:6 0.0.0.0:* 7 -
|
but doesn't show that PID
446 is actually
lpd. For that
information just type
ls -al /proc/446/.
You can see that ten services are actually open:
1,
6,
21,
22,
25,
53,
400,
515,
1045, and
6000.
1 and
6 are kernel ports, and
21 and
400 are FTP and our echo daemon, respectively.
Such a large number of open ports provides ample opportunity for attack.
At this point, you should go through each of these services and
(1), decide whether you really need them. Then (2), make sure
you have the latest version; finally (3), consult the packages
documentation so that you can limit the networks that are allowed to connect
to those services.
It is interesting that people are wont to make assumptions about
packages to the tune of ``This service is so popular it can't possibly be
vulnerable.'' The exact opposite is, in fact, true: The more obscure and
esoteric a service is, the less likely that someone has taken the trouble to
find a vulnerability. In the case of
named
(i.e.,
bind), a number of most serious
vulnerabilities were made public as regards every Bind release prior to 9.
Hence, upgrading to the latest version (9.1 at the time of writing) from source
was prudent for all the machines I administered (a most-time consuming
process).
It is easy to find all the setuid programs on your system:
|
find / -type f -perm +6000 -ls
|
Disabling them is just as easy:
There is nothing wrong with the decision that
ordinary users are not allowed to use
even the
ping command. If you do allow any
shell logins on your system, then you should
remove setuid permissions from all shell commands.
There is much that you can do that is not ``security'' per se but that
will make life considerably more difficult for a hacker, and certainly impossible
for a stock standard attack, even if your system is vulnerable. A hack attempt
often relies on a system being configured a certain way. Making your system
different from the standard can go a long way.
- Read-only partitions:
- It is allowable
to mount your
/usr partition
(and critical top-level directories like
/bin)
read-only since these are, by definition, static data. Of course, anyone with root
access can remount it as writable, but a generic attack script may not know this.
Some SCSI disks can be configured as read-only by using dip switches (or so I hear).
The
/usr partition can be made from an ISO 9660 partition
(CD-ROM file system) which is read-only by design. You can also mount your CD-ROM
as a
/usr partition:
access will be slow, but completely unmodifiable. Finally, you can manually modify
your kernel code to fail write-mount attempts on
/usr.
- Read-only attributes:
- LINUX has additional file attributes to make a
file unmodifiable over and above the usual permissions. These attributes are controlled by the
commands
chattr and
lsattr. You can make a log file
append-only with
chatter +a /var/log/messages /var/log/syslog or make files
immutable
with,
chatter +i /bin/login: both actions are a good idea. The command
|
chattr -R +i /bin /boot /lib /sbin /usr
|
- is a better idea still. Of course,
anyone with superuser privileges can switch them back.
- Periodic system monitoring:
- It is useful to write your own
crond scripts
to check whether files have changed. the scripts can check for new setuid programs, permissions, or
changes to binary files; or you can reset permissions to what you think is secure. Just remember
that
cron programs can be modified by anyone who hacks into the system. A simple
command
|
find / -mtime 2 -o -ctime 2
|
- searches for all files that have been modified in the last two days.
- Nonstandard packages:
- If you notice many security alerts for a package,
switch to a different one. There are alternatives to
bind,
wu-ftpd,
sendmail (as covered in Chapter 30), and almost every
service you can think of. You can also try installing an uncommon or security-specialized
distribution. Switching entirely to FreeBSD is also one way of reducing your
risk considerably. [This is not a joke.]
- Nonstandard messages:
- Many services provide banners and informational
messages which give away the version of your software. For example,
mail servers have default
HELO responses to advertise themselves;
and login and FTP banners often display the operating system you are running.
These messages should be customized to provide less information on which to base an attack.
You can begin by editing
/etc/motd.
- Minimal kernels:
- Its easy to compile your kernel without module
support, with an absolutely minimal set of features. Loading of
Trojan modules has been a source of insecurity in the past.
Such a kernel can only make you safer.
- Non-Intel architecture:
- Hackers need to learn assembly language
to exploit many vulnerabilities. The most common assembly language is
that of Intel 80?86 processors.
Using a non-Intel platform adds that extra bit of obscurity.
- Removing fingerprints:
- Your system identifies itself to
- OpenWall project:
- This has a kernel patch that makes the stack
of a process non-executable (which will thwart most kinds of buffer overflow
attempts) and does some other cute things with the
/tmp directory
and process I/O.
Hackers have limited resources. Take oneupmanship away and security is
about the cost of hacking a system versus the reward of success. If you feel
the machine you administer is bordering on this category then you need to start
billing far more for your hours and doing things like those described below.
It is possible to go to lengths that will make a LINUX system secure
against a large government's defense budget.
- Capabilities:
- This is a system of security that gives limited
kinds of superuser access to programs that would normally need to be full-blown
setuid
root executables. Think: Most processes
that run with
root (setuid) privileges do so because of the need to access
only a single privileged function. For instance, the
ping program
does not need complete superuser privileges (run
ls -l /bin/ping
and note the setuid bit). Capabilities are a fine-grained set of privileges
that say that a process can do particular things that an ordinary
user can't, without ever having full
root access. In the
case of
ping, its capability would be certain networking access that
only
root is normally allowed to do.
- Access control lists:
- These lists extend the simple ``user/group/other''
permissions of UNIX files to allow arbitrary lists of users to access
particular files. This really does nothing for network security but is
useful if you have many users on the system and you would like to
restrict them in odd ways. (ACL is a little
out of place in this list.)
- DTE:
- Domain and Type Enforcement works like this: When
a program is executed, it is categorized and only allowed to do certain
things even if it is running as root. These limitations are extended to
child processes that it may execute. This is real security;
there are kernel patches to do this. The National Security Agency
(of the U.S.) (NSA) actually has a LINUX distribution built around DTE.
-
medusa:
- This is a security system that causes the kernel to
query a user daemon before letting any process on the system do anything.
It is the most ubiquitous security system out because it is entirely
configurable--you can make the user daemon restrict anything however
you like.
- VXE:
- Virtual eXecuting Environment dictates that a program
executes in its own protected space while VXE executes a Lisp program to
check whether a system call is allowed. This is effectively a lot like
medusa.
- MAC:
- Mandatory Access Controls. This is also about
virtual environments for processes. MAC is a POSIX standard.
- RSBAC and RBAC:
- Rule-Set-Based Access Controls and
Role-Based Access Controls. These look like a combination
of some of the above.
- LIDS:
- Linux Intrusion Detection System does some meager
preventive measures to restrict module loading, file modifications,
and process information.
Kernel patches exist to do all of the above. Many of these projects are well
out of the test phase but are not in the mainstream kernel, possibly because
developers are not sure of the most enduring approach to UNIX security.
They all have one thing in common: double-checking what a privileged
process does, which can only be a good thing.
Proactive cunning means attack monitoring and reaction, and
intrusion monitoring and reaction. Utilities that do this come under a
general class called
network intrusion detection software. The
idea that one might detect and react to a hacker has an emotional
appeal, but it automatically implies that your system is insecure to
begin with--which is probably true, considering the rate at
which new vulnerabilities are being reported. I am weary of so-called
intrusion detection systems that administrators implement
even before the most elementary of security measures. Really, one
must implement all of the above security measures before thinking
about intrusion monitoring.
To picture the most basic form of monitoring, consider this: To hack a
system, one usually needs to test for open services. To do this, one tries to
connect to every port on the system to see which are open. This is known as
a port scan. There are simple tools to detect a port scan, which will
then start a firewall rule that will deny further access from the offending host
although this can work against you if the hacker has spoofed your own IP
address.
More importantly, the tools will report the IP address from which the attack arose.
A reverse lookup will give the domain name, and then a
whois query
on the appropriate authoritative DNS registration site will reveal the
physical address and telephone number of the domain owner.
Port scan monitoring is the most elementary form of monitoring and reaction.
From there up, you can find innumerable bizarre tools to try and read into all
sorts of network and process activity. I leave this to your own research,
although you might want to start with the
Snort traffic scanner <http://www.snort.org/>,
the Tripwire intrusion detection system <http://www.tripwiresecurity.com/>,
and IDSA <http://jade.cs.uct.ac.za/idsa/>.
A point to such monitoring is also as a deterrent to hackers. A network should
be able to find the origins of an attack and thereby trace the attacker.
The threat of discovery makes hacking a far less attractive pastime,
and you should look into the legal recourse you may have against people who
try to compromise your system.
The preceding is a practical guide. It gets much more interesting than this. A
place to start is the
comp.os.linux.security FAQ. This FAQ gives the
most important UNIX security references available on the net. You can
download it from http://www.memeticcandiru.com/colsfaq.html,
http://www.linuxsecurity.com/docs/colsfaq.html or
http://www.geocities.com/swan_daniel/colsfaq.html. The
Linux Security <http://www.linuxsecurity.com/> web page also
has a security quick reference card that summarizes most everything you need
to know in two pages.
- How many security reports have you read?
- How many packages have you upgraded because of vulnerabilities?
- How many services have you disabled because you were unsure of their security?
- How many access limit rules do you have in your
hosts.*/
xinetd services?
If your answer to any of these questions is fewer than 5, you
are not being conscientious about security.
This chapter is mostly concerned with securing your own LINUX
server. However, if you have a large network, security auditing is
a more extensive evaluation of your systems' vulnerabilities. Security auditing
becomes an involved procedure when multiple administrators maintain many different
platforms across a network. There are companies that specialize in this work:
Any network that does not dedicate an enlightened staff member should budget
generously for their services.
Auditing your network might involve the following:
- Doing penetration testing of firewalls.
- Port scanning.
- Installing intrusion detection software.
- Analyzing and reporting on Internet attack paths.
- Evaluating service access within your local LAN.
- Tracking your administrators' maintenance activities.
- Trying password cracking on all authentication services.
- Monitoring the activity of legitimate user accounts.
|
Network attacks cost companies billions of dollars
each year in service downtime and repair. Failing to
pay attention to security is a false economy.
|
Next: A. Lecture Schedule
Up: rute
Previous: 43. The X Window
  Contents
|