Skip to content

Filesystem store vulnerable to path traversal via crafted hash #15

@OkeyAmy

Description

@OkeyAmy

The Problem

The filesystem store constructs file paths by joining a base directory with user-controlled hash values. `filepath.Join` resolves `..` components, allowing a crafted hash to write outside the store directory.

```go
// drs-verify/pkg/store/filesystem.go:93-101
func (f *FilesystemStore) hashPath(hash string) string {
name := strings.TrimPrefix(hash, "sha256:")
if len(name) < 4 {
name = fmt.Sprintf("%064s", name)
}
prefix := name[:4]
return filepath.Join(f.baseDir, prefix, name+".jwt")
}
```

A hash like `sha256:../../../../etc/passwd` produces:
```
filepath.Join("/var/drs/store", "../", "../../../../etc/passwd.jwt")
→ /etc/passwd.jwt
```

The `Put()` method writes attacker-controlled content (a JWT string) to this path. The `Delete()` method removes it. This is arbitrary file write and delete with the permissions of the drs-verify process.

Proof

```go
hash := "sha256:../../../../etc/passwd"
name := strings.TrimPrefix(hash, "sha256:") // "../../../../etc/passwd"
prefix := name[:4] // "../.."
filepath.Join("/tmp/store", prefix, name+".jwt") // "/etc/passwd.jwt"
```

What Must Change

Validate that the resolved path stays within the base directory:

```go
func (f *FilesystemStore) hashPath(hash string) (string, error) {
name := strings.TrimPrefix(hash, "sha256:")
// Reject any path-separator characters
if strings.ContainsAny(name, "/\\..") {
return "", fmt.Errorf("invalid hash: contains path separators")
}
// ... rest of path construction
}
```

Or more robustly: after constructing the path, check that `filepath.Rel(f.baseDir, path)` does not start with `..`.

The hash should also be validated as hex-only (`[0-9a-f]+`) since it comes from a SHA-256 digest. Anything outside that character set is not a real hash.

Severity

HIGH. Arbitrary file write. In a container deployment with a writable filesystem, this can overwrite configuration files, inject content into mounted volumes, or destroy data. The severity depends on what the process has permission to write, but the vulnerability itself is unambiguous.

Metadata

Metadata

Assignees

No one assigned

    Labels

    highHigh severitysecuritySecurity vulnerability or hardening

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions