Assorted Security Tips for UNIX
Arthur Donkers
This article is a collection of tips and tricks to secure
your internal
network. By using the standard supplied tools and configuring
your
system with a bit of common sense, you should be able
to prevent about
80% of security-related problems.
Why should you secure your internal network? Simply
because most
break-ins occur from another machine on your local network.
These
intrusions might be accidental or malicious, but that
does not matter.
They might be done by your own staff or people you hired
for a project,
but that does not matter either. These break-ins happen,
and you must
prevent them. Because there are so many internal networks,
I cannot
cover them all in this article, so I will concentrate
on TCP/IP-based
networks built of UNIX computers connected directly
via the LAN, or via
a router and a WAN connection.
Tip 1: Know Your Network
This may seem obvious, but to make your network secure,
you must know
how it works, what is connected to what, and who the
users are.
Typically, you would divide the machines connected to
your network into
two groups, the servers and the clients. This division
makes sense;
however, it does not always depict the real situation.
A client machine
may double as a sort of server machine, in that it has
extra privileges
with one or more servers. Using these privileges, it
could mount a
special NFS volume with sensitive data on it.
Most modern networks today contain not only UNIX machines,
but also PCs.
People can install freely available UNIX implementations,
like Linux and
FreeBSD, onto their local PCs, which gives them access
to a full-blown
UNIX machine, including root access. Root access allows
them to use all
kinds of tools available on the Internet to roam your
network looking
for information. For instance, they might use a program
like tcpdump to
monitor all packets traveling on the wire. Or, they
might use a number
of NIS (formerly known as Yellow Pages) snoopers that
can copy your
company password file from the server. Once they have
access to this
password file, they can use a program like crack to
"guess" your
passwords. You might be surprised at how many passwords
can be found
(approximately 30%) in a reasonably short time.
The best strategy is to try to protect yourself from
this sort of
attack, rather than to forbid it. One way to protect
yourself is to keep
up with the dynamics of your network. Larger networks
in particular have
a tendency to grow and shrink and constantly change.
It is important
that once you have established a secure environment,
you keep it safe.
Tip 2: Keep Close Watch on Your Network
Once you have a grasp of your network, you should begin
to get an idea
of what a "normal" day will look like on your
network. This means you
need a sort of traffic profile of your network. Some
machines will
generate more traffic than others, and over time you
can build this type
of profile for each system.
You can build these profiles using a packet sniffer,
or a program like
tcpdump that monitors your network traffic. It would
be a good thing for
a larger network to keep a network monitor running permanently
because
some kinds of attacks and break-ins generate traffic
that will not fit
into your normal profile. An IP spoofing attack, for
instance, will
generate a lot of SYN packets on your network to flood
a machine (a
so-called SYN flood). If you are able to detect this
while it is
actually happening, you might keep the break-in from
succeeding.
Building a traffic profile might also help you in troubleshooting
problems on your network. It is easier to see which
hosts are working
within their operation parameters and which are exhibiting
irrational
behavior. Another benefit of these profiles is that
you can better
handle growth. You can more easily estimate when all
available bandwith
will be used up, and you can thus take adequate measures
to prevent your
network from clogging up.
Tip 3: Decide What You Want to Protect
The first question that arises is one of risk assessment.
What do you
protect and how strongly do you want to protect it?
You can use the
information you gathered for Tip 1 to help make this
decision. That
information will show you which machines contain sensitive
data, and
which systems have access to these data. You'll need
to protect these
systems if you want to protect your data.
Securing all machines on your network may seem like
a good idea, but on
a large network (or at least one with more than 100
connected machines),
this might turn into a real challenge to manage. So
you will have to
find a workable balance between these two strategies.
Tip 4: Establish a Workable Security Policy
Implementing a workable security policy is probably
the biggest
challenge of all. It is not done by simply applying
technical gadgets
and widgets alone. A complete security solution involves
your network
topology, your network administration, and most importantly,
your users.
Before you start applying technical solutions, you must
decide what kind
of security policy you will adopt. There are basically
two kinds, each
with a different approach.
The first one is based on the following statement: "That
which is not
explicitly forbidden is allowed." This means that
all users are allowed
to do everything they want, unless some service, system
or user is
explicitly prohibited. Your first reaction might be
to discard this
policy as being unsafe. This is true for some services,
but certainly
not for all. An example of this is the SMTP service
which is used for
email. Everybody is allowed to send email (i.e., make
a connection to
the SMTP service on the mail server); only the people
who tend to send
mail bombs are prohibited. So, to save yourself much
unnecessary work,
you allow everybody by default to send email.
The second policy (as you probably guessed) is based
on the statement:
"That which is not explicitly allowed is forbidden."
Nobody can use the
service unless he or she has reached some special level
of clearance and
is explicitly allowed in. An example of this might be
the telnet service
on the server of the financial department. Everybody
is denied access to
the telnet port of this machine unless he or she has
a special clearance
and works from a trusted system. To implement this policy,
the system
must provide you with appropriate tools that allow you
to select a "deny
by default" strategy. This minimizes the administrative
work and makes
for a much more secure situation. Most standard (Unix)
system supplied
tools do not allow for such a policy. They either allow
everyone in
(service enabled) or deny everyone access (service disabled).
Note that
I refer to the tools and services that come with the
basic installation
of UNIX. There are good exceptions to this rule, and
in other cases, you
might replace these with more subtle versions you can
find on the
Internet.
You can use a mix of these two policies on the local
network. As shown
in the examples above, some services are better served
by a "default
allowed" policy and others by a "default forbidden"
policy. The most
important thing is to think before you act and use a
checklist while
implementing changes.
With any policy, you must know which hosts you trust
and which you do
not. Trusted hosts have special status and are allowed
more privileges
than untrusted hosts. Furthermore, the host address
is, in most cases,
the "finest" level of discrimination you can
apply. So, to balance
security with the cost of administration, making a difference
at the
address level may be the best you can do. Sometimes,
this is not enough.
Some users on your one machine should have more privileges
than other
users. It is best to move these users to a new machine
(or move the
unprivileged users to another machine). It can be very
difficult to
enforce a different security level for different users
on the same
machine at the network level. Furthermore, there is
no reliable way to
establish the identity of a user beyond reasonable doubt.
It is fairly
easy to pretend to be another user, so user-based security
is not a good
thing.
Tip 5: Know thy TCP/IP
To be able to implement, or at least appreciate, a security
solution,
you must first know a few things about the TCP/IP protocol.
A TCP/IP
protocol stack contains a number of layers (protocols).
Figure 1 shows
the structure of the TCP/IP stack. The basic layer is
called IP. It
handles getting a packet from here to there. This also
the layer that
uses the IP addresses for finding a destination. Very
few applications
talk directly to this IP layer.
On top of the IP layer, there are a number of different
protocols. Each
of these protocols offers a programming interface to
the application
that wants to use it. In Figure 1, the height of the
protocol bar
indicates the level of functionality that is offered
to the application.
The first of these protocols is the ICMP protocol. It
is mainly used for
managing and controlling the IP layer. With it, you
can force routing
options, declare a destination unreachable, etc. The
most widely used
functions, however, are echo request and echo reply.
These two functions
are used by the ping program to see if you can reach
a certain host on
your (or somebody else's) network.
In general, this is a bit of a dangerous protocol, because
it directly
interacts with the IP layer of your machine. If possible,
you should
only enable the echo request and echo reply functions
and disable the
other ones. If this is not possible, you should enable
it so you can use
the ping command to verify the reachability of your
hosts.
The second protocol is UDP. This is a datagram protocol,
which means it
does not have to establish a connection to another machine
before
sending data. The UDP protocol takes the data an application
provides,
packs it into a UDP packet, and hands it to the IP layer.
The packet is
then put on the wire, and that is where it ends. There
is no way to
guarantee that the packet will reach its destination.
The UDP protocol
is mostly used by (old implementations of) NFS and by
the Name Service.
The last, and probably most widely used, protocol is
TCP. This offers
the application (client) a virtual circuit to a program
(server) on
another machine. This virtual circuit needs to be established,
which
means that the client has to open a connection to the
server. Once this
connection is established, the TCP protocol guarantees
the correct (both
in content and in order) delivery of the data transmitted
through this
circuit. While establishing the connection, both the
client and the
server exchange a sequence number that they will use
as a ruler for
their sliding window protocol. These sequence numbers
should be
generated at random, so they are impossible to guess.
However, a large
number of TCP/IP implementations use an algorithm to
generate these
numbers. Once a hacker knows that algorithm, he or she
can predict a
sequence number and use it in a spoofing attack. Also,
see the sidebar
on IP spoofing.
Tip 6: Enable Only What You Need
A very important tip is to enable only the things that
you need. In most
cases, a preinstalled UNIX machine comes with a setup
that enables all
the bells and whistles. One of the first things you
should do is disable
the IP_FORWARDING option in your kernel (if you do not
use the machine
as a gateway!). Most machines normally have this option
enabled, which
means that it can send a network packet from one interface
to another.
If you have connected this machine to both a trusted
and an untrusted
network, you could allow a machine on your untrusted
network to connect
or probe machines on the trusted network. How you must
disable this is
system dependent and can normally be found in the System
Manual.
You should also disable all of the services that are
not required for
your machine to work properly. In most cases, this means
that only the
telnet and ftp services will be enabled, and all others
will be
disabled, including finger, systat and friends. This
last set of
services especially can provide snoopers with information
about active
users on your system, programs running on your system,
and much more.
Before you can disable these services, you must first
know how they are
used. When a client system wants to connect to your
server, it contacts
a program running on your server machine in one of two
ways.
First, the program might be running all by itself, a
so-called daemon.
Each daemon provides one or more services to the network.
These daemons
are normally started during system startup, in one of
the rc files or
the inittab file. Not all of these daemons are necessary
(e.g., do all
machines need to run sendmail?). So, you should change
your system
startup files so that only the necessary daemons are
started. A tip here
is not to remove the unnecessary programs from your
startfiles, but
simply to comment them out. You might need them later,
and it is much
easier to remove a comment than to add programs to the
startfiles again.
The second way to start a server program is through
the superdaemon,
inetd. This inetd program listens on all the ports to
which it is
configured. Once a connection comes in on one of these
ports, inetd will
complete it. Once this connection is completed, inetd
will start the
program associated with that port and hand it the connection
on stdin
and stdout. This mechanism is used for telnet connections,
ftp
connections, and many, many more.
The configuration of inetd is stored in a special file
called
/etc/inetd.conf. This file tells inetd which services
it should listen
to and what it should do once it receives a connection
request. A short
fragment of this file is shown in Listing 1.
All unused services in this file should have a "#"
on the first line.
Note that the services on the last eight lines are internal
services of
inetd. This means that they are served by inetd itself.
As inetd is
running under the root account, any bugs or exploits
for these services
are likely to give a hacker root access to your machine.
I suggest you
normally disable these. Do not forget to send the inetd
program the HUP
signal whenever you have changed something in the inetd.conf
file. Only
then will it read its new configuration.
Tip 7: Accept Only Trusted Hosts (from Trusted Interfaces)
A system should only accept connections from machines
it trusts. This
cannot be configured with the normal Unix configuration,
so you must
resort to extra tools, such as tcpwrapper, or write
one yourself, like I
did. One thing these tools all have in common is that
they work only for
the services started by inetd. The reason for this is
simple. Once inetd
has completed a connection, it will start the program
that is associated
with the service. It is therefore very easy to insert
a wrapper program
between inetd and the real program. This wrapper program
will then check
the address of the client. If the address belongs to
the trusted group,
it will hand the connection over to the server program.
If the host is
not trusted, the wrapper program will close the connection
and the
server program is will not be started. You can find
the source for
tcpwrapper on the following ftp site:
ftp://ftp.win.tue.nl/pub/security
Listing 2 contains the wrapper program I wrote, which
is simpler and has
a few advantages. First, it uses IP addresses of clients
instead of
hostnames. Thus, it does not rely on the name server
for authentication
of the client. This can be an advantage especially in
local network
situations, as the name server is often one of the first
machines to be
compromised. Furthermore, the program in Listing 2
and Listing 3 checks the
interface on which the packet was received. For a client
to be able to
connect to a server program, the following three items
must match one of
the rules in the configuration file:
interface address client address/mask service
To be able to handle groups of hosts, the client address
may be followed
by a mask, which denotes the bits in the IP address
that are used for
matching. Listing 2 contains the main module of the
program. Listing 3
contains the routine that checks the address of both
client and
interface. If you need the complete source for this
program, you can
find this at:
ftp://ftp.reseau.nl/pub/divert
Adding such a wrapper program to inetd is simple, but
how is it done for
the standalone daemons? The answer is that it cannot
be done. These
daemons open and complete their own connections, so
there is no way to
put a wrapper in between.
However, there are other ways to make daemons more secure.
A notorious
standalone daemon (for security holes anyway) is sendmail.
It is used to
send and receive mail and normally runs under the root
account.
Furthermore, sendmail can start programs for users on
the system, so it
has all the ingredients for a good attack target. The
Firewall Toolkit
(FWTK), however, contains a placebo sendmail daemon
called smap that can
be used in place of the standalone sendmail daemon.
All smap does is
adhere to SMTP protocol and store the data it receives
in a file. Once
the message has been completed and stored, smap will
hand the data over
to the real sendmail. This prevents anyone who telnets
directly to the
SMTP port (port 25) from establishing an interactive
connection with the
real sendmail to try a few exploits. You can find this
firewall toolkit
at:
ftp://ftp.tis.com/pub /firewalls/toolkit
Another way to secure your standalone daemons is to
run them in their
own part of the filesystem. This means that the daemon
is started
through another program that first does a chroot system
call. Thus, the
program has its root on a secure directory in the filesystem
and cannot
access any files above this directory. So, should the
daemon be
compromised, then the hacker will not be able to access
real files in
the filesystem, just secured copies. The copies of these
files, however,
should not contain any sensitive information such as
real passwords from
real users. You can find this chroot utility at:
ftp://ftp.win.tue.nl/pub/security
Tip 8: Log and scan as much as you can
Preventing a break-in is important, however, you should
also prepare for
the fact that sometimes someone will succeed in gaining
unwanted access.
Therefore, you need to have a reliable way of detecting
a break-in. The
best thing you can do is to enable logging of the different
tools. If at
all possible, this logging information should be written
to a secure
disk or a sent to another machine through a serial port.
You can then
use a program like Perl or awk to continuously analyze
the stream of
logging information for strange messages (i.e., repeated
failed
connections from one host or connections during non-office
hours). When
such a situation arises you should alert the administrator
to take
action.
You can also scan your local network with a network
scanner like SATAN
or Internet Scanner. These programs test all hosts on
your network for a
large number of well-known security holes. If a program
detects a hole,
it will tell you so you can take appropriate action.
Apart from scanning
your network, you can also scan the machine itself with
a program like
COPS. COPS will check your system for strange things
like dangerous
permissions on system files (group and/or world writeable),
unknown
setuid scripts, and much more. You should perform these
scans on a
regular basis, so you can keep a close eye (not a closed
eye) on your
security. Both SATAN and COPS are freely available through
ftp.win.tue.nl. Internet Scanner is a commercial product
available
through Internet Security Systems.
Tip 9: Watch the security mailing lists on the Internet
There are a number of security-related mailing lists
available on the
Internet. You should probably subscribe to a few of
them to keep
informed on the newest exploits and problems. In any
case, it is a good
idea to subscribe to the CERT mailing list. This is
one of the official
organs that releases security alerts and fixes. Visit
their Web site at
http://www.cert.org for more information on subscribing.
Tip 10: Always Test a Password Scheme before Implementing It
In this picture of networking security, there is still
one big unknown:
the human factor. You can build a very safe networking
environment, but
if users stick their password on the monitor to remember
it, you still
have a major problem. This may sound crazy, but has
actually happened
when a security policy forced users to use system-generated
passwords.
These passwords were so difficult to remember that users
wrote them on
yellow notes and stuck them to their monitors or (if
more
security-aware) to the bottom of their keyboards.
So, you need to involve your users, and make them security
aware so they
are willing to cooperate. You will also need to draw
up some guidelines
for the users to follow so they can continue working
in a safe manner.
With respect to the human factor, some companies enforce
a password
policy to prevent users from using guessable passwords.
This is wise,
but such a password scheme should be selected with care.
In some cases,
this scheme leads to a situation where passwords are
generated
automatically, which often results in passwords like
:
Grbl%6x
Pfg$%12
Admittedly, these passwords are hard to guess, but are
probably even
harder to remember. So, you might have users follow
a rule similar to
this: Make up a sentence of words and numbers you can
easily remember.
Pick all the first letters from each word and the numbers,
and use these
as your password. An example:
I live in Holland and my zipcode is 9991 AM. My password
would then be:
IliHamzi9A
This is also hard to guess, but at least it is easier
to remember. (BTW,
this is not my real password.).
You could also write a password program that will check
the new password
of a user against a (preferably large) dictionary before
accepting it.
Whenever the program finds a match with a word in the
dictionary, the
password is rejected, and the user must choose a new
one.
Conlusions
A few simple tips can improve the security on your local
network. These
simple things do not need to cost money; usually they
can be implemented
by correctly configuring your systems. Furthermore,
a number of tools
are available through the Internet at no extra cost.
However, these measures only cover 80% of the cases.
If you have a more
than average need for a secure environment, you probably
need to build
the expertise yourself or hire it. But before implementing
a solution,
you should always weigh the risks against the effort
you will need to
expend. The costs involved should not exceed the possible
damage of a
break-in.
About the Author
Arthur Donkers graduated from the Delft University
of Technology with a
degree in Electrical Engineering and a major in Computer
Architecture.
Since then he has worked for a number of major software
houses in the
Netherlands and participated in several major projects.
His primary
field of interest in these projects has been, and still
is,
datacommunications, especially the integration of multivendor
network
systems. For the past four years, he worked as an independent
consultant
for his own company, Le Reseau (french for "The
Network"). Because of
the demand in the market, Le Reseau now focuses on network
security-related projects and consultancy.
|