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.
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]$
{ alarm(30); // Enough time to change password
system("/usr/bin/passwd"); // Run the password program
}
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: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
User: test2 Password: passw0rd
User: test3 Password: ti&#arb
User: test4 Password: .|_/Fa
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.
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.
Safe Programming techniques can be summarized as follows:
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:
-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
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:
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]# 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...
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.
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
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.
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]$
[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]#