Public Access
Keep downloads inside the folder they were sent to, never run a file opened for editing, and let a bucket upload be retried
- A remote name went straight into Path.Combine. A POSIX name may hold backslashes, a colon or a drive letter, and an S3 key may hold "../", so a name chosen by whoever could write to the host decided where on this machine a download landed. LocalDirectory.ChildPath cleans the name and requires the resolved parent to be the target folder; every download path and EDIT use it, and a name that cannot be a file there is left on the host and reported. - EDIT handed the copy to the shell's default action, which for .bat, .hta, .js and friends is to run it. LocalEditor opens such a file with its own "edit" verb or Notepad on Windows and `open -t` on macOS, and refuses a .desktop launcher on Linux. - A failed bucket upload leaves its part object, and a retry asked for an offset no bucket accepts, so the row could never finish. IRemoteFileStore.CanWriteFromAnOffset is false for buckets and the queue starts those over. - The SFTP host picker re-found its selection from the empty moment of every vault reload and landed on the first host once a minute; the chosen host is now remembered, and a typed password is only sent to the host it was typed for.
This commit is contained in:
1 parent
4c7f47c026
commit
03c8e8589a
12 files changed
+586
-83
No files matched your search
@@ -131,6 +131,35 @@ public sealed class TransferQueueingTests : IDisposable
|
||||
/// SFTP fake that a real connect produces.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <summary>
|
||||
/// A name the host chose cannot choose where on this machine the download lands.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Backslashes and colons are ordinary in a POSIX file name and are separators and drive letters on
|
||||
/// Windows, and a slash arrives in a name from an S3 key — so every one of these would have escaped the
|
||||
/// folder through <c>Path.Combine</c> somewhere. They are queued inside it under a cleaned name, and the
|
||||
/// bare <c>..</c>, which no cleaning can make a file name, is left on the host and said so.
|
||||
/// </remarks>
|
||||
[Fact]
|
||||
public void ADownloadNamedToEscapeTheFolder_LandsInsideItOrNotAtAll()
|
||||
{
|
||||
Connected();
|
||||
|
||||
transfers.QueueDownloads(
|
||||
[
|
||||
RemoteFile(@"..\..\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\x.bat"),
|
||||
RemoteFile(@"C:\Windows\evil.dll"),
|
||||
RemoteFile("../../escaped.txt"),
|
||||
RemoteFile(".."),
|
||||
]);
|
||||
|
||||
var landed = Queued().Select(row => row.Transfer.LocalPath).ToList();
|
||||
|
||||
landed.Count.ShouldBe(3);
|
||||
landed.ShouldAllBe(path => Path.GetDirectoryName(path) == directory);
|
||||
transfers.Status.ShouldContain("1 name points outside the folder");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TheDownloadButton_GoesThroughTheSamePathAsADrop()
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user