Repository: seanmonstar/warp (language: rust)

Issue:
User can access arbitrary files with static file hosting on Windows
**Version**
`0.3.2`

**Platform**
Windows 10 64 bit

**Description**
I'm creating this issue from https://github.com/tower-rs/tower-http/pull/204, where more details can be found. Essentially, if a user inputs a drive letter into the file path, it replaces the entire path. This allows a user to view anything in the current directory of the program, and everything in other attached disks, provided the program can access those files.

I tried this code, which I copied and edited from the attached PR:
```Cargo.toml```
```toml
[package]
name = "warp-tower-204"
version = "0.1.0"
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
tokio = { version = "1.15.0", features = ["full"] }
tracing-subscriber = { version = "0.2.7", features = [ "fmt" ] }
warp = "0.3.2"

```
```main.rs```
```rust
use tracing_subscriber::fmt::format::FmtSpan;

#[tokio::main]
async fn main() {
    tracing_subscriber::fmt().with_env_filter("tracing=info,warp=debug").with_span_events(FmtSpan::CLOSE).init();
    warp::serve(warp::fs::dir("d:/js/OnlyOne/Dist/"))
        .run(([127, 0, 0, 1], 3030))
        .await;
}
```

I ran this program on drive D. Then I opened the url in chrome: `http://127.0.0.1:3030/static/asdf/c:/windows/win.ini`

I expected to see this happen: 
I expected the request to fail with a 404.

Instead, this happened: 
The server responded with:
```
; for 16-bit app support
[fonts]
[extensions]
[mci extensions]
[files]
[Mail]
MAPI=1
[ResponseResult]
ResultCode=0
```



Discussion / hints:
Thank you for the report! Windows is a joy... So, can we add `:` as an illegal character when `cfg(windows)`?
I think that works. [You just cant pass an absolute path or a path with a prefix to push](https://doc.rust-lang.org/std/path/struct.PathBuf.html#method.push). Looking at [Prefix](https://doc.rust-lang.org/std/path/enum.Prefix.html), I don't think its possible to push a path with a prefix in the validate function without a `:` as I think all other variants have characters that cannot be present at that point.  I'm not sure how prefixes affect other platforms.

Edit:
Actually, I think its possible to create files with `:` in them on Windows. However, its not easy; I accidentally created a file called `:.txt` under WSL, but maybe its easier with UNC paths. [NTFS also seems to allow `:` in file names, but only under the POSIX namespace](https://en.wikipedia.org/wiki/NTFS). Not sure if that's something worth supporting. The alternative to denying `:` would be something like tower's fix, just ensuring each path component is not understood as a prefix. 
FYI I've filed a rustsec about this for tower-http https://github.com/rustsec/advisory-db/pull/1159. The vulnerable code in tower-http was based on code from warp. Might wanna do the same for warp 👀 

Fix patch:
diff --git a/src/filters/fs.rs b/src/filters/fs.rs
index 87165f1a9..0949b66ec 100644
--- a/src/filters/fs.rs
+++ b/src/filters/fs.rs
@@ -123,7 +123,10 @@ fn sanitize_path(base: impl AsRef<Path>, tail: &str) -> Result<PathBuf, Rejectio
             tracing::warn!("dir: rejecting segment starting with '..'");
             return Err(reject::not_found());
         } else if seg.contains('\\') {
-            tracing::warn!("dir: rejecting segment containing with backslash (\\)");
+            tracing::warn!("dir: rejecting segment containing backslash (\\)");
+            return Err(reject::not_found());
+        } else if cfg!(windows) && seg.contains(':') {
+            tracing::warn!("dir: rejecting segment containing colon (:)");
             return Err(reject::not_found());
         } else {
             buf.push(seg);


Test patch: