Bug#840685: TOCTOU race condition in initscript on chown'ing JVM_TMP temporary directory (was: Re: Bug#840685: tomcat8: DSA-3670 incomplete)
Salvatore Bonaccorso
carnil at debian.org
Fri Oct 14 19:40:42 UTC 2016
Hi Paul,
Markus followed already up, I just want to give some additional
comments on the below:
On Fri, Oct 14, 2016 at 07:07:52PM +1100, paul.szabo at sydney.edu.au wrote:
> Dear Salvatore,
>
> > ... if the attacher created a symlink between the rm and the mkdir
> > then mkdir will still fail with -p on a symlink. (Or do I miss
> > something?). ...
>
> Yes, you missed a simple test:
>
> $ mkdir mydir
> $ ln -s mydir mylink
> $ ls -ld my*
> drwx------ 2 psz amstaff 4096 Oct 14 18:46 mydir
> lrwxrwxrwx 1 psz amstaff 5 Oct 14 18:46 mylink -> mydir
> $ mkdir -p mylink || echo failed
> $ mkdir -p mylink; echo $?
> 0
> $ mkdir mylink || echo failed
> mkdir: cannot create directory `mylink': File exists
> failed
> $ mkdir mylink; echo $?
> mkdir: cannot create directory `mylink': File exists
> 1
> $ ls -ld my*
> drwx------ 2 psz amstaff 4096 Oct 14 18:46 mydir
> lrwxrwxrwx 1 psz amstaff 5 Oct 14 18:46 mylink -> mydir
> $
>
> showing that "mkdir -p" does not fail (but plain mkdir does).
You are doing all the tests with the same user. But yes mkdir -p will
succeed for the root user still in some cases. Let's recapitulate your
described attack. The attacker has shell-access on the tomcat8 running
host or by other mean can run code on the server by an unprivileged
user and used inotify to detect when $JVM_TMP will be removed.
Let's say the tomcat8 service is started.
JVM_TMP=/tmp/tomcat8-tomcat8-tmp
# rm -rf "$JVM_TMP".
With inotify the evil user detects, that /tmp/tomcat8-tomcat8-tmp got
removed and has several options for proceeding. Either create a
directory, or directly a malicious symlink.
evil at jessie:~$ ln -s /etc/passwd /tmp/tomcat8-tomcat8-tmp
evil at jessie:~$ ls -l /tmp/tomcat8-tomcat8-tmp
lrwxrwxrwx 1 evil evil 11 Oct 14 20:20 /tmp/tomcat8-tomcat8-tmp -> /etc/passwd
evil at jessie:~$
raced before root will issue the mkdir -p call:
root at jessie# mkdir -p /tmp/tomcat8-tomcat8-tmp
mkdir: cannot create directory ‘/tmp/tomcat8-tomcat8-tmp’: File exists
root at jessie# echo $?
1
root at jessie#
if the evil user instead created a directory, then yes you are right
for that part:
evil at jessie$ mkdir -p /tmp/tomcat8-tomcat8-tmp
evil at jessie$ ls -ld /tmp/tomcat8-tomcat8-tmp
drwxr-xr-x 2 evil evil 4096 Oct 14 20:25 /tmp/tomcat8-tomcat8-tmp
evil at jessie$
followed by the root user
root at jessie# mkdir -p /tmp/tomcat8-tomcat8-tmp
root at jessie# echo $?
0
root at jessie#
If now the evil user wins again the race, and removes the directory in
time and replaces it with the symlink to a desired file to overwrite,
before the chown call of the root user:
evil at jessie$ rmdir /tmp/tomcat8-tomcat8-tmp
evil at jessie$ ln -s /etc/passwd /tmp/tomcat8-tomcat8-tmp
evil at jessie$ ls -l /tmp/tomcat8-tomcat8-tmp
lrwxrwxrwx 1 evil evil 11 Oct 14 20:28 /tmp/tomcat8-tomcat8-tmp -> /etc/passwd
evil at jessie$
root at jessie# chown tomcat8 /tmp/tomcat8-tomcat8-tmp
chown: cannot dereference ‘/tmp/tomcat8-tomcat8-tmp’: Permission denied
root at jessie# echo $?
1
root at jessie# ls -l /etc/passwd
-rw-r--r-- 1 root root 1631 Oct 14 20:07 /etc/passwd
root at jessie#
The same if the evil user created a symlink to a existing directory:
evil at jessie$ ln -sf /etc /tmp/tomcat8-tomcat8-tmp
evil at jessie$ ls -l /tmp/tomcat8-tomcat8-tmp
lrwxrwxrwx 1 evil evil 4 Oct 14 21:01 /tmp/tomcat8-tomcat8-tmp -> /etc
evil at jessie$
root at jessie# mkdir -p /tmp/tomcat8-tomcat8-tmp
mkdir: cannot create directory ‘/tmp/tomcat8-tomcat8-tmp’: File exists
root at jessie#
root at jessie# chown tomcat8 /tmp/tomcat8-tomcat8-tmp
chown: cannot dereference ‘/tmp/tomcat8-tomcat8-tmp’: Permission denied
root at jessie#
because of the kernel hardening.
> > On the practicality for Debian systems though this is mitigated by the
> > Kernel hardenings which are enabled by default:
> >
> > fs.protected_hardlinks=1
> > fs.protected_symlink=1
> >
> > which will prevent that the target of the symlink in /tmp will be
> > changed on the chown call.
>
> Another missing test (besides: who is changing anything?):
>
> # grep . /proc/sys/fs/prot*
> /proc/sys/fs/protected_hardlinks:1
> /proc/sys/fs/protected_symlinks:1
> # cd ~psz
> # ls -ld my*
> drwx------ 2 psz amstaff 4096 Oct 14 18:46 mydir
> lrwxrwxrwx 1 psz amstaff 5 Oct 14 18:46 mylink -> mydir
> # chown mike mylink
> # ls -ld my*
> drwx------ 2 mike amstaff 4096 Oct 14 18:46 mydir
> lrwxrwxrwx 1 psz amstaff 5 Oct 14 18:46 mylink -> mydir
> #
You are operating here outside of /tmp (sticky world-writable
directory) which the above issue for the init scripts relies on,
right? fs.protected_(hardlinks|symlinks) is exactly a hardening for
those issues:
https://www.kernel.org/doc/Documentation/sysctl/fs.txt
https://sources.debian.net/src/linux/3.16.36-1%2Bdeb8u1/Documentation/sysctl/fs.txt/#L205
In the release notes such issues are not treated as security-issues
anymore since:
https://www.debian.org/releases/stable/amd64/release-notes/ch-whats-new.en.html#security
> > So while I think it should be fixed, this would not warrant a DSA,
> > since mitigated by default in Debian.
>
> No mitigation: fix and DSA, please!
See my explanation above. I'm not saying the issue should not be
fixed, if that was the impression from our replies, then this can be
rectified; but it does not seem warrant a DSA (so can be fixed via a
regular update via a point release). Maybe still I'm missing
something, so if you have a PoC could you please share your PoC it
with apo at debian.org and team at security.debian.org?
Regards,
Salvatore
More information about the pkg-java-maintainers
mailing list