DOKIMASecurity review report

Overview

File checksum endpoint omits the Perm.Download gate its sibling branch enforces, giving a content oracle to no-download users

low Fully Valid high confidence

DOK-100028-FILEBROWSER-RESOURCE-FILE-CRUD-CHECKSUM-QUERY-PAR · filebrowser · resource-file-crud

Status

Fully Valid

Complete authorization inconsistency verified in source: checksum sink lacks the Perm.Download gate its sibling branch enforces. Fully_valid, low (hash-only oracle).

Repository / Component

Repository
filebrowser
Component
resource-file-crud

Plain-English Description

Users who are explicitly denied the ability to download files can still ask the server for a file's cryptographic hash. That lets them confirm whether a file has specific known contents or detect when it changes, even though they were never supposed to read the file.

Description of the Underlying Issue

In resourceGetHandler (http/resource.go:70-80) the checksum branch calls file.Checksum(...) without checking d.user.Perm.Download. The adjacent encoding branch (http/resource.go:45-48) does gate on !d.user.Perm.Download and returns 202, and NewFileInfo (http/resource.go:34) deliberately sets Content only when Perm.Download is true — so content is otherwise withheld from these users. Checksum (files/file.go:179-205) opens and reads the entire file to produce an md5/sha1/sha256/sha512 digest. The inconsistency means a no-download user can obtain a strong hash of any file that passes the rules checker.

Potential Attack

An authenticated user whose account has Perm.Download=false issues GET /api/resources/<file>?checksum=sha256. The handler skips the download check present on the sibling branch and returns the digest of the file's full contents.

Outcomes of Potential Attack

The attacker gains a content oracle: they can confirm that a file matches a known/guessed plaintext by comparing hashes, detect when a file's contents change over time, and distinguish among a small set of candidate contents — all without the download permission that was supposed to prevent reading the file. This is a hash-only oracle, not direct content disclosure.

Affected Scope

resourceGetHandler checksum branch (http/resource.go:70-80) -> FileInfo.Checksum (files/file.go:170-207)

Suggested Fix (plain english)

Require the same download permission for hashing a file that is already required for downloading or encoding it.

Suggested Fix (detailed)

Gate the checksum branch (http/resource.go:70-80) on d.user.Perm.Download, returning 202/403 exactly as the encoding branch at http/resource.go:45-48 does. Verify by requesting GET /api/resources/<file>?checksum=sha256 as a Perm.Download=false user and confirming no hash is returned. Note related finding DOK-100035 concerning the checksum read itself. Gate the checksum branch on d.user.Perm.Download (return 202/403) exactly like the encoding branch.

Validation

Complete authorization inconsistency verified in source: checksum sink lacks the Perm.Download gate its sibling branch enforces. Fully_valid, low (hash-only oracle).

first_opinion

Full Evidence

http/resource.go:70-80 checksum branch calls file.Checksum(checksum) with no Perm.Download check
http/resource.go:45-48 the sibling encoding branch DOES gate on !d.user.Perm.Download (returns 202) — inconsistent
http/resource.go:34 NewFileInfo Content:d.user.Perm.Download deliberately withholds content from non-download users
files/file.go:179-205 Checksum opens and reads the entire file to produce the digest
Proven fact: An authenticated user WITHOUT Perm.Download can obtain md5/sha1/sha256/sha512 of any file that passes the rules checker, providing a content oracle (confirm known content, detect changes)
Proven fact: This contradicts the Perm.Download restriction that is enforced on the adjacent content/encoding branches
http/resource.go:70-80 — the checksum branch calls file.Checksum(checksum) with no Perm.Download check
http/resource.go:45-48 — the sibling encoding branch DOES gate on !d.user.Perm.Download (returns 202), an inconsistency
http/resource.go:34 — NewFileInfo sets Content:d.user.Perm.Download, deliberately withholding content from non-download users
files/file.go:179-205 — Checksum opens and reads the entire file to produce the digest
Proven fact: An authenticated user without Perm.Download can obtain md5/sha1/sha256/sha512 of any file that passes the rules checker, providing a content oracle to confirm known content or detect changes.
Proven fact: This contradicts the Perm.Download restriction that is enforced on the adjacent content/encoding branches.
http/resource.go:70-80 checksum branch: no Perm.Download check before file.Checksum(checksum)
http/resource.go:34 NewFileInfo called with Content: d.user.Perm.Download (content correctly withheld) — contrast
http/resource.go:45-48 encoding branch DOES gate on !d.user.Perm.Download (returns 202) — inconsistent with checksum branch
files/file.go:170-207 Checksum opens (:179) and reads the entire file to produce the digest regardless of Download permission