DOKIMASecurity review report

Overview

Public share-password verification has no rate limiting and no minimum password length, enabling online brute force

low Fully Valid medium confidence

DOK-100043-FILEBROWSER-SHARES-PUBLIC-NO-RATE-LIMITING-O · filebrowser · shares-public

Status

Fully Valid

Absence of rate limiting is confirmed, and the missing minimum-length on share passwords (verified at share.go:177) makes weak passwords genuinely brute-forceable — stronger than the login case. Fully_valid, low.

Repository / Component

Repository
filebrowser
Component
shares-public

Plain-English Description

Password-protected share links can be guessed at without limit: the server never throttles or locks out repeated wrong guesses, and it never enforces a minimum length for share passwords. A weak share password can be brute-forced online by anyone holding the share link.

Description of the Underlying Issue

authenticateShareRequest (http/public.go:129-154) verifies the attacker-supplied X-SHARE-PASSWORD header with bcrypt.CompareHashAndPassword (http/public.go:138-146) with no attempt counter, lockout, or delay. getSharePasswordHash (http/share.go:172-183) bcrypt-hashes the chosen password but enforces no minimum length (http/share.go:177). The only router middleware is the CSP header setter, and handle() injects no limiter (http/http.go:30-40). Together, unauthenticated share-password verification is both unthrottled and permitted to protect a share with an arbitrarily short/weak password.

Potential Attack

An attacker who possesses a share hash/URL repeatedly sends requests to /api/public/... with guessed X-SHARE-PASSWORD header values. No counter or lockout intervenes, so guessing continues at a rate bounded only by bcrypt's per-attempt CPU cost. Because share passwords have no minimum length, many real shares are protected by short/weak passwords that fall to online guessing.

Outcomes of Potential Attack

The attacker can recover a weak share password and gain the access the share grants (viewing/downloading the shared file or directory), plus impose auth-path CPU load through repeated bcrypt verifications.

Affected Scope

authenticateShareRequest (http/public.go:129-154), X-SHARE-PASSWORD verification on public share access

Suggested Fix (plain english)

Enforce a minimum length for share passwords and add rate limiting or lockout to the public share-password check.

Suggested Fix (detailed)

Enforce a minimum share-password length in getSharePasswordHash (http/share.go:172-183) and add rate limiting / lockout keyed on share hash plus client IP in front of authenticateShareRequest (http/public.go:129-154). Verify by attempting rapid repeated X-SHARE-PASSWORD guesses against a known share hash and confirming throttling/lockout, and by attempting to set a too-short share password and confirming rejection. Related: DOK-100042 (same missing rate-limiting control on /api/login). Enforce a minimum share-password length and add rate limiting/lockout keyed on share hash + client IP.

Validation

Absence of rate limiting is confirmed, and the missing minimum-length on share passwords (verified at share.go:177) makes weak passwords genuinely brute-forceable — stronger than the login case. Fully_valid, low.

first_opinion

Full Evidence

http/public.go:138-146 bcrypt.CompareHashAndPassword on attacker-supplied X-SHARE-PASSWORD with no attempt counter/lockout/delay
http/share.go:172-183 getSharePasswordHash hashes body.Password with bcrypt but enforces NO minimum length
http/http.go:30-40 only middleware is the CSP header; handle() injects no limiter
Proven fact: Unauthenticated share-password verification has no rate limiting AND share passwords have no minimum-length requirement, so weak share passwords are online-brute-forceable (bcrypt only CPU-throttles each attempt)
Unvalidated fact: The attacker must already possess the share hash (distributed in the share URL); actual password strength is user-chosen and deployment-dependent
http/public.go:138-146 — bcrypt.CompareHashAndPassword on the attacker-supplied X-SHARE-PASSWORD with no attempt counter/lockout/delay
http/share.go:172-183 — getSharePasswordHash hashes body.Password with bcrypt but enforces NO minimum length (share.go:177)
http/http.go:30-40 — the only middleware is the CSP header; handle() injects no limiter
Proven fact: Unauthenticated share-password verification has no rate limiting, and share passwords have no minimum-length requirement, so weak share passwords are online-brute-forceable (bcrypt only CPU-throttles each attempt).
Unvalidated fact: The attacker must already possess the share hash (distributed in the share URL); actual share-password strength is user-chosen and deployment-dependent.
http/public.go:138-151 — bcrypt.CompareHashAndPassword on attacker-supplied X-SHARE-PASSWORD with no attempt counter or delay
http/http.go:30-40 and http/data.go:50-85 — the only middleware is a CSP header; handle() injects no rate limiter or lockout
repo-wide search for ratelimit|throttl|limiter|lockout|backoff|failed_attempt yields no security control (only an unrelated comment in runner/commands.go)
Distinct from prior dismissal 'Non-constant-time token comparison and 48-bit share-hash entropy' (SP-A4/SP-A6), which reasoned from HIGH entropy of the 768-bit token and 48-bit hash; that infeasibility argument does not apply to a low-entropy user-chosen password