[Slirp] [PATCH] slirp: tftp: restrict relative path access
Eric Blake
eblake at redhat.com
Thu Jan 2 18:38:51 UTC 2020
On 1/2/20 3:28 AM, Marc-André Lureau wrote:
>> /* do sanity checks on the filename */
>> - if (!strncmp(req_fname, "../", 3) ||
>> - req_fname[strlen(req_fname) - 1] == '/' || strstr(req_fname, "/../")) {
>> + if (strstr(req_fname, "../") || strstr(req_fname, "..\\")
>> + || req_fname[strlen(req_fname) - 1] == '/'
>> + || req_fname[strlen(req_fname) - 1] == '\\') {
>> tftp_send_error(spt, 2, "Access violation", tp);
>> return;
>> }
>
> Please divide the rule for #ifdef G_OS_WIN32 .. #else ..
>
> You changed the existing rule, and it seems to break some valid cases
> ex: /foo/bar/../blah
Hmm. The existing code rejects "/foo/../" but accepts "/foo/..". I
don't know why it is special-casing on whether the last character of the
string is "/".
What's more, it is not obvious whether "/foo/bar/../blah" is an escape
attempt if /foo/bar can be a symlink under user control. Windows lacks
symlinks, so it is easier to tell: as long as there are fewer ../
components than there are earlier non-.. components, there is no escape.
But on Linux, where earlier components can be symlinks, you can't
blindly shorten "/foo/bar/../blah" into "/foo/blah" because bar might be
a symlink.
Another problem with the proposed code of using just strstr("../"
instead of "/../" is that it has false positives on the non-escape
"/foo.../bar" (not that a suffix of 3 dots is common, but it shouldn't
be a reason for us to incorrectly reject it).
> This traversal problem is so common, I wonder if there are known good
> practices...
Sadly, path sanitization is tough, and I don't know of any good turnkey
solutions out there :(
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3226
Virtualization: qemu.org | libvirt.org
More information about the Slirp
mailing list