Anybody can easily get a root-shell and change your passwords by entering "<name-of-your-bootimage> init=/bin/sh" at the boot prompt. After changing the passwords and rebooting the system, the person has unlimited root-access and can do anything they want to the system. After this procedure you will not have root access to your system, as you do not know the root password.
To make sure that this can not happen, you should set a password for the boot loader. You can choose between a global password or a password for a certain image.
For LILO you need to edit the config file /etc/lilo.conf and add a "password" and "restricted" line as in the example below.
image=/boot/2.2.14-vmlinuz label=Linux read-only password=hackme restricted
When done, rerun lilo. Omitting the "restricted" line causes lilo to always prompt for a password, regardless of whether LILO was passed parameters. The default permissions for /etc/lilo.conf grant root read and write permissions, and enable read-only access for lilo.conf's group, root.
If you use GRUB instead of LILO, edit /boot/grub/menu.lst
and add
the following two lines at the top (substituting, of course 'hackme' with the
desired password). This prevents users from editing the boot items. 'timeout
3' specifies a 3 second delay before grub boots the default item.
timeout 3 password hackme
To further harden the integrity of the password, you may store the password in a crypted form. The utility grub-md5-crypt generates a hashed password which is compatible with grub's crypted password algorithm (md5). To specify in grub that md5 format password will be used, use the following directive:
timeout 3 password --md5 $1$bw0ez$tljnxxKLfMzmnDVaQWgjP0
The --md5 paramater was added to instruct grub to perform the md5 authentication process. The provided password is the md5 crypted version of hackme. Using the md5 password method is preferable to choosing its cleartext counterpart. More information about grub passwords may be found in the grub-doc package.
The default MBR in Debian before version 2.2 did not act as a usual master boot record and left open a method to easily break into a system:
This behavior can be changed by entering:
lilo -b /dev/hda
Now LILO is put into the MBR. This can also be achieved by adding "boot=/dev/hda" to lilo.conf. There is another solution which will disable the MBR prompt completely:
install-mbr -i n /dev/hda
On the other hand, this "back door", of which many people are just not aware, may save your skin as well if you run into deep trouble with your installation for whatever reasons.
FIXME check whether this really is true as of 2.2 or was it 2.1? INFO: The bootdisks as of Debian 2.2 do NOT install the mbr, but only LILO
When mounting an ext2 partition, you have several additional options you apply
to the mount call or to /etc/fstab
. For instance, this my fstab
entry for the /tmp partition:
/dev/hda7 /tmp ext2 defaults,nosuid,noexec,nodev 0 2
You see the difference in the options sections. The option nosuid ignores the setuid and setgid bits completely, while noexec forbids execution of any program on that mount point, and nodev, ignores devices. This sounds great, but it
The noexec option prevents binaries from being executed directly, but is easily circumvented:
alex@joker:/tmp# mount | grep tmp /dev/hda7 on /tmp type ext2 (rw,noexec,nosuid,nodev) alex@joker:/tmp# ./date bash: ./date: Permission denied alex@joker:/tmp# /lib/ld-linux.so.2 ./date Sun Dec 3 17:49:23 CET 2000
However, many script kiddies have exploits which try to create and execute files in /tmp. If they do not have a clue, they will fall into this pit. In other words, a user cannot be tricked into executing a trojanized binary in /tmp e.g. when he incidentally adds /tmp into his PATH.
The following is a more thorough example. A note, though: /var could be set noexec, but some software like Smartlist keeps its programs in /var. The same applies to the nosuid option.
/dev/sda6 /usr ext2 defaults,ro,nodev 0 2 /dev/sda12 /usr/share ext2 defaults,ro,nodev,nosuid 0 2 /dev/sda7 /var ext2 defaults,nodev,usrquota,grpquota 0 2 /dev/sda8 /tmp ext2 defaults,nodev,nosuid,noexec,usrquota,grpquota 0 2 /dev/sda9 /var/tmp ext2 defaults,nodev,nosuid,noexec,usrquota,grpquota 0 2 /dev/sda10 /var/log ext2 defaults,nodev,nosuid,noexec 0 2 /dev/sda11 /var/account ext2 defaults,nodev,nosuid,noexec 0 2 /dev/sda13 /home ext2 rw,nosuid,nodev,exec,auto,nouser,async,usrquota,grpquota 0 2 /dev/fd0 /mnt/fd0 ext2 defaults,users,nodev,nosuid,noexec 0 0 /dev/fd0 /mnt/floppy vfat defaults,users,nodev.nosuid,noexec 0 0 /dev/hda /mnt/cdrom iso9660 ro,users,nodev.nosuid,noexec 0 0
As soon as new security bugs are revealed in packages, debian maintainers and
upstream authors generally patch them within days or even hours. After the bug
is fixed, a new package is provided on http://security.debian.org
. Put
the following line in your sources.list and you will get security updates
automatically, whenever you update your system.
deb http://security.debian.org/debian-security stable/updates main contrib non-free
Most people, who don't live in a country which prohibits importing or using strong cryptography, should add this line as well:
deb http://security.debian.org/debian-non-US stable/non-US main contrib non-free
If you like, you can add the deb-src lines to apt as well. See
apt(8)
for further details.
FIXME: Add info on how the signature of packages is done so that this can be done automatically through a cron job (big warning: DNS spoofing).
PAM allows system administrators to choose how applications authenticate users.
Note that PAM can do nothing unless an application is compiled with support for
PAM. Most of the applications that are shipped with Debian 2.2 have this
support built in. Furthermore Debian did not have PAM support before 2.2. For
each application there is a configuration file in /etc/pam.d/
.
PAM offers you the possibility to go through several authentication steps at once, without the user's knowledge. You could authenticate against a Berkeley database and against the normal passwd file, and the user only logs in if he authenticates correct in both. You can restrict a lot with PAM, just as you can open your system doors very wide. So be careful. A typical configuration line has a control field as its second element. Generally it should be set to "requisite", which returns a login failure if one module fails.
The first thing I like to do, is to add MD5 support to PAM applications, since this helps protects against dictionary cracks. The following two lines should be added to all files in /etc/pam.d/ that grant access to the machine, like login and ssh.
# Be sure to install libpam-cracklib first or you will not be able to log in password required pam_cracklib.so retry=3 minlen=12 difok=3 password required pam_unix.so use_authtok nullok md5
So, what does this incantation do? The first line loads the cracklib PAM module, which provides password strength-checking, prompts for a new password with a minimum length of 12 characters, a difference of at least 3 characters from the old password, and allows 3 retries. The second line introduces the standard authentication module with MD5 passwords and allows a zero length password. The use_authtok directive is necessary to hand over the password from the previous module.
To make sure that the user root can only log into the system from local
terminals, the following line should be enabled in
/etc/pam.d/login
:
auth requisite pam_securetty.so
Then you should add the terminals from which the user root can log into the
system into /etc/security/access.conf
. Last but not least the
following line should be enabled if you want to set up user limits.
session required pam_limits.so
This restricts the system resources that users are allowed. For example, you could restrict the number of concurrent logins users may have.
Now edit /etc/pam.d/passwd
and change the first line. You should
add the option "md5" to use MD5 passwords, change the minimum length
of password from 4 to 6 (or more) and set a maximum length, if you desire. The
resulting line will look something like:
password required pam_unix.so nullok obscure min=6 max=11 md5
If we want to protect su, so that only some people can use it to become root on your system, we need to add a new group "wheel" to your system (that is the cleanest way, since no file has such a group permission yet). Add root and the other users that should be able to "su" to the root user to this group. Then add the following line to /etc/pam.d/su:
auth requisite pam_wheel.so group=wheel debug
This makes sure that only people from the group wheel can use su
to become root. Other users will not be able to become root. In fact they
will get a denied message if they try to become root.
If you want only certain users to authenticate at a PAM service, this is quite
easy to achieve by using files where the users who are allowed to login (or
not) are stored. Imagine you only want to allow user 'ref' to login via ssh.
So you put him into /etc/sshusers-allowed
and write the following
into /etc/pam.d/ssh
:
auth required pam_listfile.so item=user sense=allow file=/etc/sshusers-allowed onerr=fail
Last, but not least, create /etc/pam.d/other and enter the following lines:
auth required pam_securetty.so auth required pam_unix_auth.so auth required pam_warn.so auth required pam_deny.so account required pam_unix_acct.so account required pam_warn.so account required pam_deny.so password required pam_unix_passwd.so password required pam_warn.so password required pam_deny.so session required pam_unix_session.so session required pam_warn.so session required pam_deny.so
These lines will provide a good default configuration for all applications that support PAM (access is denied per default).
You should really take a serious look into this file. Here you can define user
resource limits. If you use PAM, the file /etc/limits.conf
is
ignored and you should use /etc/security/limits.conf
instead.
FIXME: Get a good limits.conf up here
You should stop all unneeded services on your system, like echo, chargen, discard, daytime, time, talk, ntalk and the HIGHLY insecure considered r-services (rsh, rlogin and rcp. Use ssh instead). After disabling those, you should check if you really need the inetd daemon. Many people prefer to use daemons instead of calling services via inetd. Denial of Service possibilities exist against inetd, which can increase the machine's load tremendously. If you still want to run some kind of inetd service, switch to a more configurable inet daemon like xinetd or rlinetd.
You can disable services by editing /etc/inetd.conf
directly, but
Debian provides an alternative to this: update-inetd. You could
remove the telnet daemon by executing this commands to change the config file
and to restart the daemon (in this case the telnet service is disabled):
/usr/sbin/update-inetd --disable telnet
If you do want services listening, but do not want to have them listen on all
IP addresses of your host, you might want to use some undocumented feature on
inetd. . Or use an alternate inetd daemon like xinetd
.
The next step is to edit the basic configuration and action upon user login.
FAIL_DELAY 10
This variable should be set to a higher value to make it harder to use the terminal to log in using brute force. If a wrong password is typed in, the possible attacker (or normal user!) has to wait for 10 seconds to get a new login prompt, which is quite time consuming when you test passwords. Pay attention to the fact that this setting is useless if using program other than getty, such as mingetty for example.
FAILLOG_ENAB yes
If you enable this variable, failed logins will be logged. It is important to keep track of them to catch someone who tries a brute force attack.
LOG_UNKFAIL_ENAB yes
If you set the variable "FAILLOG_ENAB" to yes, then you should also set this variable to yes. This will record unknown usernames if the login failed. If you do this, make sure the logs have to the proper permissions (640 for example, with an appropriate group setting such as adm), because users often accidentally enter their password as the username and you do not want others to see it.
SYSLOG_SU_ENAB yes
This one enables logging of su attempts to syslog. Quite important on serious machines but note that this can create privacy issues as well.
SYSLOG_SG_ENAB yes
The same as SYSLOG_SU_ENAB but applies to the sg
program.
MD5_CRYPT_ENAB yes
As stated above, MD5 sum passwords greatly reduce the problem of dictionary attacks, since you can use longer passwords. If you are using slink, read the docs about MD5 before enabling this option. Otherwise this is set in PAM.
PASS_MAX_LEN 50
If MD5 passwords are activated in your PAM configuration, then this variable should be set to the same value as used there.
This file contains a list of users who are not allowed to log into the host using ftp. Only use this file if you really want to allow ftp (which is not recommended in general, because it uses cleartext passwords). If your daemon supports PAM, you can also use that to allow and deny users for certain services.
TCP wrappers were developed when there were no real packet filters available
and access control was needed. The TCP wrappers allow you to allow or deny a
service for a host or a domain and define a default allow or deny rule. If you
want more informations take a look at hosts_access(5)
.
Now, here comes a small trick, and probably the smallest intrusion detection system available. In general, you should have a decent firewall policy as a first line, and tcp wrappers as the second line of defense. One little trick is to set up a SPAWN [1] command in /etc/hosts.deny that sends mail to root whenever a denied service triggers wrappers:
ALL: ALL: SPAWN ( \ echo -e "\n\ TCP Wrappers\: Connection refused\n\ By\: $(uname -n)\n\ Process\: %d (pid %p)\n\ User\: %u\n\ Host\: %c\n\ Date\: $(date)\n\ " | /bin/mail -s "Connection to %d blocked" root) &
Beware: The above printed example can easily be DoSed by doing lots of connections in a short period of time. Many emails mean a lot of file I/O by sending only a few packets.
How log and alerts are treated is an important issue in a secure system. It is easily to see that, even if the system is perfectly configured and, supposedly, 99% secure. If the 1% comes to happen, and there are no security measures in place to, first, detect this and, second, raise alarms, the system is not secure at all.
Debian comes with a standard syslog configuration (in /etc/syslog.conf) that
logs messages to the appropriate files depending on the system facility. You
should be familiar with this; have a look at the syslog.conf
file
and the documentation if not. If you intend to maintain a secure system you
should be wary of where log messages are sent so they do not go unnoticed.
For example, sending messages to the console also is an interesting setup useful for many production-level systems. But for many such systems it is important to also add a new machine that will serve as loghost (i.e. it receives logs from all other systems).
Root's mail should be considered also, many security controls (like
snort
) send alerts to root's mailbox. This mailbox usually points
to the first user created in the system (check /etc/aliases). Take care to
send root's mail to some place where it will be read (either locally or
remotely).
There are other role accounts and aliases on your system. On a small system, it's probably simplest to make sure that all such aliases point to the root account, and that mail to root is forwarded to the system administrator's personal mailbox.
FIXME: it would be interesting to tell how a Debian system can send SNMP traps
related to security problems (jfs). Check: snmptraglogd
,
snmp
and snmpd
.
A loghost is a host which collects syslog data remotely over the network. If
one of your machines is cracked, the intruder is not able to cover his tracks,
unless he hacks the loghost as well. So, the loghost should be especially
secure. Making a machine a loghost is simple. Just start the syslogd with
'syslogd -r' and a new loghost is born. In order to do this permanently in
Debian, edit /etc/init.d/sysklogd
and change the line
SYSLOGD=""
to
SYSLOGD="-r"
Next, configure the other machines to send data to the loghost. Add an entry
like the following to /etc/syslog.conf
:
facility.level @your_loghost
See the documentation for what to use in place of facility and level (they should not be entered verbatim like this). If you want to log everything remotely, just write:
*.* @your_loghost
into your syslog.conf. Logging remotely as well as locally is the best
solution (the attacker might presume to have covered his tracks after deleting
the local log files). See the syslog(3)
, syslogd(8)
and syslog.conf(5)
manpages for additional information.
It is not only important to decide how alerts are used, but also who has access to them, i.e. can read or modify the logfiles (if not using a remote loghost). Security alerts which the attacker can change or disable are not much worth in the event of an intrusion.
Some logfile permissions are not perfect after the installation. First
/var/log/lastlog
and /var/log/faillog
do not need to
be readable by normal users. In the lastlog file you can see who logged
recently, and in the faillog you see a summary of failed logins. The author
recommends chmod'ing both to 660. Take a brief look over your log files and
decide very carefully which logfiles you make readable/writeable for a user
with another UID than 0 and a group other than 'adm' or 'root'.
I want to emphasize that the apache logfile permissions are really screwed due to the fact that the apache user owns the apache log files. If a user gets a shell with a back door in apache, they can easily remove the logfiles.
Debian provides a cron job that runs daily in
/etc/cron.daily/standard
this cron job will run the
/usr/sbin/checksecurity
script that will store information of this
changes.
In order for this check to be made you must set
CHECKSECURITY_DISABLE="FALSE" in
/etc/checksecurity.conf
. Note, this is the default, so unless you
have changed something, this option will already be set to "FALSE".
The default behavior does not send this information to the superuser but,
instead keeps daily copies of the changes in
/var/log/setuid.changes
. You should set the CHECKSECURITY_EMAIL
(in /etc/checksecurity.conf
) to 'root' to have this information
mailed to him. . See checksecurity(8)
for more configuration
info.
If you really need to become the super user on your system, e.g. for
installing packages or adding users, you can use the command su
to
change your identity. You should try to avoid any login as user root and
instead use su. Actually, the best solution is to remove su and switch to
sudo
, as it has more features than su. However, su is more common
as is used on many other Unixes.
sudo
allows the user to execute defined commands under another
user's identity, even as root. If the user is added to
/etc/sudoers
and authenticates himself correctly, he is able to
run commands which have been defined in /etc/sudoers
. Violations,
such as incorrect passwords or trying to run a program you don't have
permission for, are logged and mailed to root.
chroot
is one of the most powerful possibilities to restrict a
daemon or a user or another service. Just imagine a jail around your target,
which the target cannot escape from (normally, but there are still a lot of
conditions that allow one to escape out of such a jail). If you do not trust a
user, you can create a change root environment for him. This can use quite a
bit of disk space as you need to copy all needed executables, as well as
libraries, into the jail. Even if the user does something malicious, the scope
of the damage is limited to the jail.
A good example for this case is, if you do not authenticate against
/etc/passwd
but use LDAP or MySQL instead. So your ftp-daemon
only needs a binary and perhaps a few libraries. A chrooted environment would
be an excellent security improvement; if a new exploit is known for this
ftp-daemon, then attackers can only exploit the UID of the ftp-daemon-user and
nothing else. Of course, many other daemons could benefit from this as well.
Of course, many other daemons could benefit from this sort of arrangement as well.
However, be forewarned that a chroot
jail can be broken if the
user running in it is the superuser. So, you need to make the service run as a
non-privileged user. By limiting its environment you are limiting the world
readable/executable files the service can access, thus, you limit the
possibilities of a privilege escalation by use of local system security
vulnerabilities. Even in this situation you cannot be completely sure that
there is no way for a clever attacker to somehow break out of the jail. Using
only server programs which have a reputation for being secure is a good
additional safety measure. Even minuscule holes like open file handles can be
used by a skilled attacker for breaking into the system. After all,
chroot
was not designed as a security tool but as a testing tool.
As an additional note, the Debian default BIND (the Internet name service) is not shipped chrooted per default; in fact, no daemons come chrooted. This might change in the woody (3.0) release.
FIXME: Content missing
Many features of the kernel can be modified while running by echoing something into the /proc file system or by using sysctl. By entering sysctl -A you can see what you can configure and what the options are. Only in rare cases do you need to edit something here, but you can increase security that way as well.
net/ipv4/icmp_echo_ignore_broadcasts = 1
This is a 'windows emulator' because it acts like windows on broadcast ping if this one is set to 1. Otherwise, it does nothing.
net/ipv4/icmp_echo_ignore_all = 0
If you don't want to block ICMP on your firewall, enable this.
net/ipv4/tcp_syncookies = 1
This option is a double-edged sword. On the one hand it protects your system against syn flooding; on the other hand it violates defined standards (RFCs). This option is quite dumb as it floods the other side like it floods you, so the other side is also busy. If you want to change this option you also can change it in /etc/network/options by setting syncookies=yes.
/proc/sys/net/ipv4/conf/all/log_martians = 1
Packets with impossible addresses (due to wrong routes) on your network get logged.
Here is an example to set up this and other useful stuff. You should add this
information to a script in /etc/network/interface-secure
(the name
is given as an example) and call it from /etc/network/interfaces
like this:
auto eth0 iface eth0 inet static address xxx.xxx.xxx.xxx netmask 255.255.255.xxx broadcast xxx.xxx.xxx.xxx gateway xxx.xxx.xxx.xxx pre-up /etc/network/interface-secure
# Script-name: /etc/network/interface-secure # Modifies some default behaviour in order to secure against # some TCP/IP spoofing & attacks # # Contributed by Dariusz Puchalak # echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts # broadcast echo protection enabled echo 0 > /proc/sys/net/ipv4/ip_forward # ip forwarding disabled echo 1 > /proc/sys/net/ipv4/tcp_syncookies # TCP syn cookie protection enabled echo 1 >/proc/sys/net/ipv4/conf/all/log_martians # Log packets with impossible addresses # but be careful with this on heavy loaded web servers echo 1 > /proc/sys/net/ipv4/ip_always_defrag # defragging protection always enabled echo 1 > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses # bad error message protection enabled # now ip spoofing protection for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 1 > $f done # and finally some more things: # Disable ICMP Redirect Acceptance for f in /proc/sys/net/ipv4/conf/*/accept_redirects; do echo 0 > $f done for f in /proc/sys/net/ipv4/conf/*/send_redirects; do echo 0 > $f done # Disable Source Routed Packets for f in /proc/sys/net/ipv4/conf/*/accept_source_route; do echo 0 > $f done # Log Spoofed Packets, Source Routed Packets, Redirect Packets for f in /proc/sys/net/ipv4/conf/*/log_martians; do echo 1 > $f done
Some users might want to set up firewalling rules in this script as well. However, check what firewalling programs/features you might be using since they can tweak other files and change the definitions you add on startup. For example, firewalk, for one, will use another configuration file for firewall setup.
FIXME: I remember a thread about this in debian-security, should add the information posted there here (jfs).
SVGAlib is very nice for console lovers like me, but in the past it has been
proven several times that it is very insecure. Exploits against
zgv
were released, and it was simple to become root. Try to
prevent using SVGAlib programs wherever possible.
Copying files in a secure manner from a host to another can be achieved by using 'scp' which is included in the ssh package. It works like rcp but is encrypted completely, so the bad guys cannot even find out WHAT you copy.
Having a good quota policy is important, as it keeps users from filling up the hard disk(s).
You can use two different quota systems: user quota and group quota. As you probably figured out, user quota limits the amount of space a user can take up, group quota does the equivalent for groups. Keep this in mind when you're working out quota sizes.
There are a few important points to think about in setting up a quota system:
Every partition/directory which users have full write access should be quota enabled. Find out those partitions and directories and calculate a workable quota size, which combines usability and security.
So, now you want to use quotas. First of all you need to check whether you enabled quota support in your kernel. If not, you will need to recompile it. After this, control whether the package 'quota' is installed. If not you will need this one as well.
Enabling quota for the respective filesystems is as easy as modifying the
defaults setting to defaults,usrquota in your
/etc/fstab
file. If you need group quota, substitute
usrquota to grpquota. You can also use them both.
Then create empty quota.user and quota.group files in the roots of the
filesystems you want to use quotas on (e.g. touch /home/quota.user
/home/quota.group for a /home filesystem).
Restart quota by doing /etc/init.d/quota stop;/etc/init.d/quota start. Now quota should be running, and quota sizes can be set.
Editing quotas for a specific user (say 'ref') can be done by edquota -u ref. Group quotas can be modified withedquota -g <group>. Then set the soft and hard quota and/or inode quotas as needed.
For more information about quotas, read the quota man page, and the quota
mini-howto(/usr/share/doc/HOWTO/en-html/mini/Quota.html
).
FIXME. Should we add some comments regarding lshell
here. Is it
useful? (jfs)
These two commands are very useful, but they only work for the ext2 filesystem. With 'lsattr' you can list the attributes of a file and with 'chattr' you can change them. Note that attributes are not the same thing as permissions. There are many attributes, but only the most important for increasing security are mentioned here. There are two flags which can only be set by the superuser.
First there is the 'a' flag. If set on a file, this file can only be opened for appending. This attribute is useful for some of the files in /var/log/, though you should consider they get moved sometimes due to the log rotation scripts.
The second flag is the 'i' flag, short for immutable. If set on a file, it can neither be modified nor deleted or renamed and no link be created to it. If you do not want users to look into your config files you could set this flag and remove readability. Furthermore it can give you a little bit more security against intruders, because the cracker might be confused by not being able to remove a file. Nevertheless, you should never assume that the cracker is blind. After all, he got into your system.
Note that lsattr and chattr are only available on ext2 filesystems.
Are you sure /bin/login on your hard drive is still the binary you installed there some months ago? What if it is a hacked version, which stores the entered password in a hidden file or mails it in cleartext version all over the internet?
The only method to have some kind of protection is to check your files every
day/hour/month (I prefer daily) by comparing the actual and the old md5sum of
this file. Two files cannot have the same md5sum (the MD5 digest is 128 bits,
so the chance that two different files will have the same md5sum is roughly one
in 3.4e3803), , so you're on the safe site here, except someone hacked the
algorithm to create md5sums on that machine, what is, well, pathological. You
really should consider this auditing of your binaries as very important, since
it is an easy way to recognize changes at your binaries. Common tools used for
this are sXid, AIDE
(Advanced Intrusion Detection Environment),
TripWire
(non-free; the new version will be GPL),
integrit
and samhain
.
Installing debsums will help to check the filesystem integrity, by comparing the md5sums of every file against the md5sums used in the Debian package archive. But beware, those files can easily be changed.
Furthermore you can replace locate
with slocate
.
slocate is a security enhanced version of GNU locate. When using slocate, the
user only sees the files he really has access to and you can exclude any files
or directories on the system.
jfs@computer.org