Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Request for Equivalent of --path-as-is #2396

Open
i5-650 opened this issue Aug 19, 2024 · 3 comments
Open

Request for Equivalent of --path-as-is #2396

i5-650 opened this issue Aug 19, 2024 · 3 comments
Labels
B-rfc Blocked: Request for comments. More discussion would help move this along.

Comments

@i5-650
Copy link

i5-650 commented Aug 19, 2024

Hello,

I'm currently exploring ATAC as a potential replacement for curl.

However, for cybersecurity purposes, I frequently use curl with the --path-as-is option, which disables URL normalization.

At present, the main obstacle preventing @Julien-cpsn from implementing this feature in ATAC is the absence of support for it in the reqwest library.

Would it be possible to have this feature implemented?

Best regards

@seanmonstar
Copy link
Owner

Do you have some examples of paths that you wish weren't normalized, and what reqwest does with them?

@i5-650
Copy link
Author

i5-650 commented Aug 19, 2024

Let's take a simple example:

I have a web server:

const STATIC_DIR: &str = "./static/";

#[get("/")]
async fn index() -> impl Responder {
    NamedFile::open(Path::new(STATIC_DIR).join("index.html"))
}

#[get("/static/{filename:.*}")]
async fn static_files(filename: web::Path<String>) -> impl Responder {
    let path = Path::new(STATIC_DIR).join(filename.into_inner());
    match NamedFile::open(path) {
        Ok(file) => file,
        Err(_) => NamedFile::open(Path::new(STATIC_DIR).join("404.html")).unwrap(),
    }
}

async fn not_found() -> impl Responder { NamedFile::open(Path::new(STATIC_DIR).join("404.html")) }

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    return HttpServer::new(|| {
        App::new()
            .service(index).service(static_files)
            .default_service(web::route().to(not_found))
    }).bind(("127.0.0.1", 8080))?.run().await;
}

As explained in the Actix documentation about static files, this server is vulnerable to a path traversal attack.

Let's say it's a CTF, and the file is located at the root of the server. You would need to access this URL: http://localhost:8080/static/../a_file. However, it will be normalized to http://localhost:8080/a_file, which prevents exploitation of this vulnerability.

To exploit such a vulnerability, you can use curl with the following command:

curl --path-as-is http://localhost:8080/statitc/../a_file

If you try to do this with reqwest:

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let resp = reqwest::get("http://127.0.0.1:8080/static/../a_file").await?;
    let content = resp.text().await?;
    println!("{}", content);
    Ok(())
}

It will be logged on the server as a request to /a_file directly, bypassing the intended path traversal.

@seanmonstar
Copy link
Owner

Ok, thanks for the example. So you're referring to path segments being flattened. Makes sense. I wasn't sure if you also meant percent encoding, etc.

reqwest currently makes use of the url crate for request targets. (That might change next version, undecided.) So, it'd either need to be supported in url, or a workaround added to reqwest directly. I'm not going to work on that myself, but discussing how to do so in this issue is welcome.

@seanmonstar seanmonstar added the B-rfc Blocked: Request for comments. More discussion would help move this along. label Aug 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
B-rfc Blocked: Request for comments. More discussion would help move this along.
Projects
None yet
Development

No branches or pull requests

2 participants