next up previous contents
Next: 6.3 Summary Up: 6. Host Security Solutions Previous: 6.1 Theory

Subsections

6.2 Practical

6.2.1 Denial of Service

We have already stated that most shells have resource restriction mechanisms built into them. We will consider the Bourne Again Shell (bash). Bash provides resource management through a built in command called ``ulimit''. This utility allows the restriction of such resources as the maximum number of user processes, maximum open file descriptors and the maximum filesize that can be created. Below is a log illustrating how the DoS attack using the script 'a' (see 3.2.1) fails when resources are restricted in this manner. It should be noted that what is shown below are soft limits, meaning they can be changed. Hard limits, on systems that support them, can be set by supplying the ``-H'' flag.

% In the /etc/profile file, the command below is inserted

ulimit -c 1000000 -t 60 -u 20 -f 1

 

% When users type 'ulimit -a', they see the allowed resources [trimmed]

[siviwe@lucifer siviwe]$ ulimit -a

core file size (blocks)  1000000

file size (blocks)       1

cpu time (seconds)       60

max user processes       20

[siviwe@lucifer siviwe]$ ./a

bash: fork: Resource temporarily unavailable

[siviwe@lucifer siviwe]$

Our proposed solution to password locking was to give a user a set amount of time to change his password. If he fails to change it in that timeframe, we exit the program on his behalf. As part of our problems section, we wrote a script that ran the passwd program in an infinite loop. Our timing solution would not solve that problem. Logging every time a user takes too long to change a password allows the administrator to see who may have attempted a password file locking DoS attack. Our simple wrapper for the password program therefore looks as follows:

void main(void)

{       alarm(30); // Enough time to change password

        system("/usr/bin/passwd"); // Run the password program

}       

A better version of the wrapper, that incorporates logging of every attempt that takes too long, is included in Appendix A.

6.2.2 Password Cracking

We introduced the principle of password shadowing in our theoretical section. We noted that FreeBSD is shipped with shadow passwords enabled by default. RedHat Linux on the other hand ships with an unshadowed password file. There is a set of utilities available on RedHat Linux machines that allows one to convert between normal and shadowed password formats. The utility to convert to shadow password format is called pwconv. To go back to normal format, the utility to use is pwunconv. We continue to show an extract of the password file, before and after the conversion to shadow passwords. We also show the strict file permissions on the shadow password file.

[root@lucifer /root]# head -1 /etc/passwd

root:0cmzrAQpGheqA:0:0:Meneer Wortel:/root:/bin/bash

[root@lucifer /root]# pwconv 

 

% The /etc/passwd file when shadowed

root:x:0:0:Meneer Wortel:/root:/bin/bash

% The /etc/shadow file - includes the encrypted password

root:0cmzrAQpGheqA:10532:0:99999:7:::

% File permissions of the /etc/shadow file

-r----   1 root     root          583 Nov  2 10:30 /etc/shadow

We mentioned that short passwords (<6 characters) are easily guessable and that that is the reason most Unix implementations do not allow them. Passwords should not be based on :

We ran a test with the two password Crackers mentioned previously, John the Ripper and Crack. We created four user accounts with the following usernames and passwords :

User: test1    Password: password

User: test2    Password: passw0rd

User: test3    Password: ti&#arb

User: test4    Password: .|_/Fa

We then ran both password crackers at different times on the same password file for half an hour. John was run in incremental mode while Crack used dictionary mode. After ten minutes, John had cracked test1's password. It cracked no more until the time was up. After two minutes, Crack had cracked test1's password and test2's after twelve minutes. The time elapsed before it had cracked any more. The experiment conducted shows that even carefully chosen short (==6 chars) passwords are safe against both brute force and dictionary attacks. Although the test was run only for a limited time, it shows that dictionary words fall victim to both (intelligent) brute force and dictionary attacks.

6.2.3 Misconfigured Software

As stated in the theoretical section, there is no clear-cut solution to this problem. The solution lies in testing one's own configuration until reasonably comfortable with its security.

6.2.4 Buffer Overflows

6.2.4.1 Non-executable stack

As the author of the non-executable stack for Linux notes, it does not catch all buffer overflows. Using the simple example of a buffer overflow we showed previously, the non-executable stack code did not catch and report the buffer being overflowed. If, with such a simple example of a buffer overflow, the non-executable stack does not solve buffer overflow problems, the solution seems relies more on safe programming techniques. After investigating further, it appeared that the non-executable stack code was not functioning properly. After testing on different hosts with different kernel versions to no avail, it was abandoned.

6.2.4.2 Safe Programming Techniques

Safe Programming techniques can be summarized as follows:

1.
Avoid using functions that perform no boundary checking. e.g. strcpy(), strcat(), sprintf() and vsprintf().
2.
If using the scanf() family of commands, always specify the maximum field width.
3.
If reading a character at a time from stdin, for example, check for both the delimiter and the buffer bounds.
4.
If allocating memory for a buffer to be copied into, test if the memory was actually allocated before proceeding.
5.
Whenever possible, check array subscript bounds.

6.2.5 Set User ID Files

The first step is to find all SUID files. The next step is to remove the SUID bit of all files but the ones that really need it. An example is included below:

[root@lucifer /root]# find / -perm -4000 -user root -print | xargs ls -l

-rwsr-xr-x   1 root     root        35876 May  1  1998 /bin/mount

-rwsr-xr-x   1 root     root        14340 May  6  1998 /bin/ping

-rwsr-xr-x   1 root     root        17884 May  1  1998 /bin/umount

-rwsr-xr-x   1 root     root         8952 May  8 22:16 /sbin/cardctl

-r-sr-xr-x   1 root     root        28258 Apr 24  1998 /sbin/pwdb_chkpwd

-rwsr-xr-x   1 root     root        30520 May  5  1998 /usr/bin/at

-rwsr-xr-x   1 root     root        30040 May  8 06:30 /usr/bin/chage

-rwsr-xr-x   1 root     root        20328 May  6  1998 /usr/bin/crontab

-rwsr-xr-x   1 root     root        29432 May  8 06:30 /usr/bin/gpasswd

-rwsr-xr-x   1 root     root         5104 May 10 20:12 /usr/sbin/usernetctl

The above files are only a subset of all SUID files reported. Programs such as ``passwd'' need to have the SUID bit flag set, and are therefore not included. Only those that have yet to have their SUID bit justified are included. Let us now look at how we would decide whether the files keep their SUID flag or not, together with some recommendations.

It should be noted that if appropriate wrappers to SUID files can be written, access to the wrappers can remain unlimited. Access to the SUID files themselves can therefore be limited to the wrappers.

Safe programming techniques are also important when writing secure SUID files. Writers of SUID files have to follow the same safe programming techniques for the prevention of buffer overflows. On top of that, writers of SUID files should follow guidelines specific to the writing of such files. These include:

1.
Being as restrictive as possible in choosing UID and GID
2.
Closing all but necessary file descriptors before calling exec()
3.
Not writing interpreted scripts that are SUID
4.
Catching all signals.
The above and other guidelines are discussed in detail in [4].

6.2.6 Backdoors and Trojan Horses

As mentioned in our theoretical section, integrity checkers are a solution to these problems. We investigated two integrity checkers, Tripwire and Tiger. We shall consider Tiger. Tiger checks for a variety of things, including calculating and comparing MD5 checksums on files. Here we shall only consider new SUID files which appear on the system. We run Tiger initially to get a listing of all files on the host that have their SUID flags set. This first run is most useful after the system has been freshly installed, configured and secured. The initial log should be written preferably onto a WORM device. Subsequent runs of Tiger would then compare their results with the initial log (which is certain not to change) and report on inconsistencies. If the inconsistencies are the administrator's doing, the latest log would be more accurate. The latest log would then be written to a WORM device and all subsequent output from runs checked against it.

[root@lucifer tiger-2.2.3]# ./scripts/find_files > firstrun

[root@lucifer tiger-2.2.3]# mkdir -p /.../foo/hidden

[root@lucifer tiger-2.2.3]# cp /bin/bash /.../foo/hidden

[root@lucifer tiger-2.2.3]# chmod 4755 /.../foo/hidden

[root@lucifer tiger-2.2.3]# ./scripts/find_files > secondrun

[root@lucifer tiger-2.2.3]# diff -DCHANGES firstrun secondrun 

# Checking setuid executables...

/home/siviwe/pscript: setuid perl commands text

-FAIL- [fsys001f] File /home/siviwe/pscript is a setuid script: 

-rwsr-xr-x   1 siviwe   siviwe         28 Oct 27 08:53 /home/siviwe/pscript

-WARN- [misc013w] /usr/X11R6/bin/nxterm: see CERT Advisory CA-93:17 about a 

         security hole in xterm. 

 

% Trimmed output - shows changes and other things the script checks for

#ifdef CHANGES

-rwsr-xr-x root     root     /.../foo/hidden/bash

#endif /* CHANGES */

# Checking setgid executables...

# Checking unusual file names...

# Checking symbolic links...

Tiger is a suite of shell scripts which can be run individually or at once by running the ``tiger'' command. Since processes such as finding all the SUID files on the system are resource intensive, tiger comes with a script (called tigercron) that uses the crontab. This is used to schedule the resource intensive parts of Tiger to be run at times when the resources may not be needed much, e.g. 2am.

6.2.7 Keystroke Logging

6.2.7.1 Keystroke Logging

Our login spoofing program was first written to simply capture the login and password typed in at the console. When a user typed Enter for the login and password, it captured those as real. We then modified it to ignore Enter as a login name but a user could type Ctrl-Z to suspend or Ctrl-C to break the execution of the program. The example shown below illustrates the version of the program that does no signal catching. We then wrote code in to ignore all signals (those the system allows us to ignore). With that version of the program, remote login is needed to check what is running on the console. Since the program cannot be killed by a regular user, the only solution is to ask an administrator to kill the process.

% ^C is Ctrl-C

Red Hat Linux release 5.1 (Manhattan)

Kernel 2.0.34 on an i586

 

lucifer login: ^C

[test@lucifer test]$ ./plogin

[root@lucifer test]# w

  1:02pm  up  3:13,  7 users,  load average: 3.00, 2.73, 1.70

USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU  WHAT

root     tty2                       9:55am  1.00s  0.47s  0.09s  w

test     tty3                      12:52pm  3.00s  0.26s  0.01s  ./plogin

siviwe   tty4                      10:11am 16:08   0.27s  0.12s  -bash

 

6.2.7.2 The X windowing system

The first solution we will illustrate is that which uses a host-based method of access control. When this method is in use, anyone who logs in on the hostname running an X display will be able to mount an attack against it. This solution is obviously not adequate if users on the host itself cannot be trusted. It does however work well for remote hosts, as illustrated below.

[root@angel /root]# xhost - %Disable access to all hosts except the current one

access control enabled, only authorized clients can connect

[siviwe@lucifer siviwe]$ export DISPLAY=angel:0.0

[siviwe@lucifer siviwe]$ xhost

Xlib: connection to "angel:0.0" refused by server

Xlib: Client is not authorized to connect to Server

xhost:  unable to open display "angel:0.0"

[siviwe@lucifer siviwe]$ 

Our second solution is to use the user-based access control method, namely cookies. The cookies are used to allow access to the X display on a per user basis. In normal operation, before starting X-windows, the user creates a cookie file that contains the hostname, socket type, display name, and a hexadecimal string which represents the cookie. The cookie is created using the program ``xauth''. The cookie is stored in the ~/.Xauthority file. The X server would then be started with the ``-auth'' flag set and the authorization filename set to ~/.Xauthority. Let us illustrate :

[siviwe@lucifer siviwe]$ xauth add lucifer.ru.ac.za/unix:0 . 1452244399087612

[siviwe@lucifer siviwe]$ xauth add lucifer.ru.ac.za:0 . 9823651234239087

[siviwe@lucifer siviwe]$ xinit - -auth ~/.Xauthority

[root@lucifer /root]# export DISPLAY=:0.0

[root@lucifer /root]# xhost

Xlib: connection to ":0.0" refused by server

Xlib: Invalid MIT-MAGIC-COOKIE-1 key

xhost:  unable to open display ":0.0"

[root@lucifer /root]#

Everytime a connection without the correct cookie connects to our display, the attempt to access our display is logged. Through testing, we observed that the combination of both host and user based access controls was the best solution.


next up previous contents
Next: 6.3 Summary Up: 6. Host Security Solutions Previous: 6.1 Theory
Shaun Bangay
1998-11-19