-
Vulnerability Name: Path Traversal in xxhsum command-line utility
- Description:
The
xxhsum
command-line utility is vulnerable to path traversal. It directly uses user-provided file paths from command-line arguments withos.Open()
without any validation or sanitization. This allows an attacker to specify paths like../../sensitive_file
to access files outside the intended directory. Step by step an attacker can:- Execute the compiled
xxhsum
binary. - Provide a command-line argument containing path traversal sequences, such as
../../../../etc/passwd
. - The
xxhsum
utility will attempt to open and process the file specified by the manipulated path.
- Execute the compiled
- Impact:
Information Disclosure. An attacker can read the content of arbitrary files on the system that the
xxhsum
utility has permissions to access. This could include sensitive configuration files, application data, or other confidential information. - Vulnerability Rank: High
- Currently Implemented Mitigations:
None. There is no input validation or sanitization of file paths in the
xxhsum
utility. - Missing Mitigations:
Input validation and sanitization for file paths provided as command-line arguments. The application should validate that the provided paths are within the expected directories or sanitize the paths to prevent traversal attempts. For example, using functions like
filepath.Clean()
to resolve path traversals or explicitly checking if the path is within an allowed base directory. - Preconditions:
- The attacker must be able to execute the compiled
xxhsum
binary. - The
xxhsum
binary must have sufficient permissions to read the target files that the attacker wants to access via path traversal.
- The attacker must be able to execute the compiled
- Source Code Analysis:
The
// File: /code/xxhsum/xxhsum.go package main import ( "fmt" "io" "os" "github.com/cespare/xxhash/v2" ) func main() { // ... (help message and stdin handling) ... for _, path := range os.Args[1:] { // Vulnerable code: Iterating through user provided paths f, err := os.Open(path) // Vulnerability: Directly opening user provided path without validation if err != nil { fmt.Fprintln(os.Stderr, err) continue } printHash(f, path) f.Close() } }
main
function inxxhsum.go
iterates through the command-line arguments starting from the second argument (os.Args[1:]
). Each argument is treated as a file path and directly passed toos.Open()
. Theos.Open()
function opens the file at the given path without any checks to prevent directory traversal. This allows an attacker to provide paths containing..
to navigate up the directory structure and access files outside the intended working directory of thexxhsum
utility. - Security Test Case:
- Compile the
xxhsum
utility:go build ./xxhsum/xxhsum.go
- Run the compiled binary
xxhsum
with a path traversal payload to access the/etc/passwd
file (or any other accessible sensitive file):./xxhsum ../../../../../etc/passwd
- Observe the output. The command should execute without errors and print the xxhash of the
/etc/passwd
file along with the provided path:If you can successfully execute the command and observe an output similar to the above, it confirms that the path traversal vulnerability exists. The<xxhash> ../../../../../etc/passwd
<xxhash>
will be the calculated xxhash of the content of/etc/passwd
.
- Compile the
- Description:
The
-
Vulnerability Name: Unsafe Memory Layout Assumption in String-to-Byte Conversion
- Description:
The functions in the package that are built for non‑appengine environments (in particular, in xxhash_unsafe.go) convert a string into a byte slice by means of an unsafe pointer cast. For example, in the function
Sum64String
, the conversionis used to avoid copying the string’s data. This code assumes that the first two words of a slice header (used for ab := *(*[]byte)(unsafe.Pointer(&sliceHeader{s, len(s)}))
[]byte
) match the layout of the customsliceHeader
type (which simply holds the string and its length). An attacker who is able to supply untrusted or specially crafted string inputs—or who manages to run the binary on an architecture or future Go version where the assumed memory layout no longer holds—could force the function into reading memory outside the intended boundaries. Step by step:- Identify an interface (for example, an HTTP endpoint or other public API) that passes attacker‑controlled string data to functions such as
Sum64String
orWriteString
. - Deliver specially crafted string inputs (e.g. extremely long strings or patterns near internal boundaries) that force the unsafe conversion to misinterpret the underlying memory layout.
- Trigger undefined behavior leading to memory corruption, a crash, or even bypassing memory‐safety if the compiler’s internal assumptions are altered.
- Identify an interface (for example, an HTTP endpoint or other public API) that passes attacker‑controlled string data to functions such as
- Impact:
- Potential memory corruption or out-of‑bounds memory reads.
- Application crashes or panics that could lead to denial of service.
- In extreme cases, undefined behavior may be exploitable for arbitrary code execution, especially if other memory safety issues are present downstream.
- Vulnerability Rank: High
- Currently Implemented Mitigations:
- A safe implementation (xxhash_safe.go) is provided for builds targeting App Engine (via build tag
appengine
), which performs the conversion by copying the string. - The unsafe conversion is isolated behind specific build tags (e.g.
!appengine
andgc
), which means that on many production environments (outside appengine) the performance‑optimized, unsafe path is chosen knowingly.
- A safe implementation (xxhash_safe.go) is provided for builds targeting App Engine (via build tag
- Missing Mitigations:
- No runtime or compile–time verification is performed to ensure that the underlying assumptions about memory layout hold on all target architectures or future Go versions.
- There is no fallback method in non‑appengine builds that uses the safe conversion when uncertainty exists; a more conservative approach (e.g. copying the string data or using a verified conversion via reflection with explicit checks) would mitigate the risk if the layout assumptions were ever broken.
- Preconditions:
- The application must be deployed using a non‑appengine build (or any build that does not select the safe path) such that the unsafe pointer conversion is active.
- The attacker must have a way to inject or control the string input data that is passed to
Sum64String
orWriteString
.
- Source Code Analysis:
- In xxhash_unsafe.go, the functions
Sum64String
andWriteString
both cast a string to a byte slice without an intermediate copy. - They use a custom
sliceHeader
type defined as:and then perform:type sliceHeader struct { s string cap int }
*(*[]byte)(unsafe.Pointer(&sliceHeader{s, len(s)}))
- This relies on the assumption that the internal memory layout of a Go string (typically a pointer and a length) matches the layout of the slice’s first two words (Data pointer and Length). Any change to this layout or unexpected compiler behavior would invalidate this assumption.
- Because the conversion avoids a data copy for performance, any misinterpretation of the header could lead to improper slicing of memory.
- In xxhash_unsafe.go, the functions
- Security Test Case:
- Setup: Build and deploy the xxhash-based application in an environment where the unsafe implementation is active (i.e. without the
appengine
build tag). - Input Injection: Create or use an API endpoint that passes arbitrary string data to a service function which in turn calls
Sum64String
(orWriteString
). - Fuzzing: Employ fuzzing strategies to supply strings of varying lengths and crafted content (including extremely large strings or boundary‑crossing patterns).
- Observation: Monitor the application for abnormal behavior such as segmentation faults, panics, or inconsistent hash outputs.
- Result Verification: Confirm that under specific crafted inputs the application crashes or exhibits memory corruption—thereby validating that the unsafe memory layout assumption can be subverted.
- Setup: Build and deploy the xxhash-based application in an environment where the unsafe implementation is active (i.e. without the
- Description:
The functions in the package that are built for non‑appengine environments (in particular, in xxhash_unsafe.go) convert a string into a byte slice by means of an unsafe pointer cast. For example, in the function
-
Vulnerability Name: Unsafe Deserialization of Digest Internal State
- Description:
The method
UnmarshalBinary
implemented on theDigest
type allows external binary data to directly set the internal state of the hash digest. Although the function performs basic checks—confirming that the input data starts with the expected magic header ("xxh\x06"
) and that the total length of the blob is exactly equal to an expected constant—it does not perform any cryptographic verification (such as a digital signature or HMAC) of the data. An attacker who can control the binary input could craft a valid-looking blob that, when unmarshaled, sets the internal state variables (v1
,v2
,v3
,v4
, andtotal
) and the memory buffer (d.mem
) to attacker‑chosen values. In practice, this would allow the attacker to force predictable or manipulated hash outputs in any context where the deserialized digest is later used. Step by step, an attacker would:- Create a binary blob that is exactly 76 bytes long (the expected
marshaledSize
), starts with the required magic header, and contains arbitrary but controlled values for the digest’s state. - Submit this blob to an application component that calls
UnmarshalBinary
on untrusted data. - Once the digest’s state is crafted, subsequent calls to
Sum64
would yield attacker‑controlled hash outputs.
- Create a binary blob that is exactly 76 bytes long (the expected
- Impact:
- An attacker could force predictable or manipulated hash values, undermining any integrity checks or logic that depend on hash computations.
- This manipulation could lead to hash collisions or undermine hash‑based partitioning, caching, or verification mechanisms, potentially facilitating further attacks such as bypassing acceptance checks.
- Vulnerability Rank: High
- Currently Implemented Mitigations:
- The
UnmarshalBinary
method checks that the binary input begins with the correct magic header and that its total length matches the expected size. - These checks ensure that only data formatted in the exact expected binary layout is accepted.
- The
- Missing Mitigations:
- There is no cryptographic mechanism (such as a message authentication code) to verify that the binary blob originates from a trusted source.
- The method does not perform any sanity checking on the decoded state values beyond the size and magic header checks.
- As a consequence, if the digest state is deserialized from an untrusted source, an attacker can set internal variables arbitrarily without further validation.
- Preconditions:
- The application (or any library using xxhash) must accept and directly deserialize digest state from external (untrusted) sources.
- The attacker must be able to supply a binary blob that passes the basic formatting checks (correct magic header and length).
- Source Code Analysis:
- In xxhash.go, the
UnmarshalBinary
function begins by verifying:ensuring that only fixed-length inputs with the expected header are processed.if len(b) < len(magic) || string(b[:len(magic)]) != magic { return errors.New("xxhash: invalid hash state identifier") } if len(b) != marshaledSize { return errors.New("xxhash: invalid hash state size") }
- Following this, it sequentially decodes five 8‑byte unsigned integers into the digest’s internal state (
v1
–v4
andtotal
) and copies the remaining data into the internal memory bufferd.mem
. - The final state is derived (for example,
d.n
is computed asint(d.total % uint64(len(d.mem)))
) without any further validation of whether the state is internally consistent or reasonable. - An attacker who can supply a crafted binary blob can control these internal parameters, thereby controlling the outcome of subsequent calls to
Sum64
.
- In xxhash.go, the
- Security Test Case:
- Setup: Develop a test harness that calls
UnmarshalBinary
on aDigest
instance. - Crafted Input: Construct a binary blob of exactly 76 bytes that:
- Starts with the expected magic header
"xxh\x06"
. - Contains attacker‑controlled values for
v1
,v2
,v3
,v4
, andtotal
, as well as an arbitrary 32‑byte block ford.mem
.
- Starts with the expected magic header
- Injection: Pass the crafted binary blob to
UnmarshalBinary
and subsequently invokeSum64
on the same digest instance. - Observation: Verify that the hash output corresponds exactly to the manipulated internal state (i.e. differing from the value computed by a normally initialized digest using the same input).
- Result Verification: Confirm that by controlling the internal state via deserialization, the attacker can force predictable or chosen hash outputs—demonstrating the vulnerability if the system were to rely on the digest’s output for security‑critical operations.
- Setup: Develop a test harness that calls
- Description:
The method
-
Vulnerability Name: No vulnerabilities identified.
- Description: There are no identified vulnerabilities of high or critical rank in the provided project files that meet the specified criteria.
- Impact: N/A
- Vulnerability Rank: Low
- Currently Implemented Mitigations: N/A
- Missing Mitigations: N/A
- Preconditions: N/A
- Source Code Analysis: N/A
- Security Test Case: N/A