Security vulnerabilities

  • Status Assigned
  • Assigned To
    cbay
  • Private
Attached to Project: Security vulnerabilities
Opened by zlynv - 24.09.2026

FS#497 - WebDAV path jail bypass via %-encoded traversal (..%2f) - read/write outside configured user root

Summary field: WebDAV path jail bypass via %-encoded traversal (..%2f) - read/write outside configured user root

—

Details field:

Affected endpoint (in scope): https://webdav-[account].alwaysdata.net/

Summary

A WebDAV user created with a restricted path (API field: "Chemin relatif a la racine de votre compte. Les repertoires parents du repertoire racine ne seront ni accessibles ni visibles.") can escape that restriction using URL-encoded directory traversal (..%2f) and list, read, write and delete files anywhere inside the hosting account - exactly what the restriction is supposed to prevent.

The per-user root is only enforced against normalized () traversal. The encoded form ..%2f is passed through to the path mapper, which resolves it relative to the account root (the WsgiDAV security check still passes because the final path stays inside the account), so the configured subdirectory jail is silently skipped.

Cross-account access is NOT possible: going one level above the account root returns HTTP 500 with "Security exception: tried to access file outside root: /home" (verbose error disclosure, see additional notes).

Steps to reproduce

1. Create a test account with a site (path www/).

2. Create a WebDAV user restricted to the site directory:

POST https://api.alwaysdata.com/v1/webdav/
Authorization: Basic <token-id>:

{"name":"<account>_recon","password":"<pwd>","path":"www/"}

Confirm the restriction is stored: GET /v1/webdav/ returns "path": "www/".

3. Confirm the jail with Digest auth:

PROPFIND https://webdav-<account>.alwaysdata.net/
-> 207, displayname = www (configured root), children = site files only

4. Bypass with encoded traversal. Control test proving the file lands OUTSIDE the jail:

PUT      /..%2f_recon_proof2.txt   -> 201 Created
PROPFIND /                         -> 207: children of www, does NOT contain the file
PROPFIND /..%2f                    -> 207: displayname=<account>, children =
                                      admin/, www/, _recon_proof2.txt   (parent listed)
GET      /_recon_proof2.txt        -> 404   (file is not inside the jail)
GET      /..%2f_recon_proof2.txt   -> 200, exact body read back
DELETE   /..%2f_recon_proof2.txt   -> 204
GET      /..%2f_recon_proof2.txt   -> 404   (cleanup verified)

Plain GET /../ does NOT bypass (client and server normalize it to /) - only the encoded variant does, which is why it is easy to miss.

Raw request for the PUT (after Digest handshake):

PUT /..%2f_recon_proof2.txt HTTP/1.1
Host: webdav-<account>.alwaysdata.net
Authorization: Digest <...>

recon-proof2-XYZZY

5. Above the account root the protection holds:

PROPFIND /..%2f..%2f  -> 500 Security exception: tried to access file outside root: /home

Validation notes (re-tested same day)

- Restriction is genuinely stored: GET /v1/webdav/ shows path "www/" for the test user (a separate default user with path "" has full root legitimately - that is not this vector).
- The 404-inside-jail / 200-escaped control with the identical filename proves this is not URL-normalization noise: the same name resolves differently depending on the encoded traversal.
- Parent listing exposes sibling directories (e.g. admin/) that must be unreachable per the API documentation.
- All proof files were deleted and deletion verified.

Impact

Any delegated WebDAV user limited to a subdirectory becomes a full-account credential: it can reach sibling directories of its configured root - other sites' document roots, mail storage, SSH keys and config, application source, any secrets in the account. Combined with the confirmed write access this is account takeover within the tenant.

Worst case per your methodology: full read/write of one customer account's content by a principal who was deliberately given access to a single directory.

CVSS estimate: between Medium and High. Suggested metrics: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N (adjust as you see fit; PR:L is a deliberately delegated credential).

Additional observations (not standalone reports)

- Verbose 500 pages leak internals: exception text with filesystem layout (/home) and exact software: WsgiDAV/4.3.3. Invalid alone (version/path disclosure) but it directly helped diagnose the bypass.
- WWW-Authenticate: Digest realm="alwaysdata" on webdav; Server: gunicorn behind "Via: 1.1 alproxy".

Account used for testing

- Test customer account created for this program (panel login available on request for verification).
- WebDAV user created: <account>_recon (path www/) - can be deleted on request.
- Proof files already deleted, deletion verified.
- No other account or third-party data was accessed at any point.

Admin
cbay commented on 25.09.2026 07:42

Hello,

Thanks for the report. Can you confirm that the vulnerability is now fixed?

Kind regards,
Cyril

zlynv commented on 25.09.2026 10:51

Hello Cyril,

Confirmed - re-tested, the vulnerability is fixed.

Kind regards,
zlynv

Admin
cbay commented on 25.09.2026 13:04

Thanks, you can now claim your bounty by opening a support ticket.

Loading...

Available keyboard shortcuts

Tasklist

Task Details

Task Editing