Path Traversal in Aspnet with Hmac Signatures
Path Traversal in Aspnet with Hmac Signatures — how this specific combination creates or exposes the vulnerability
Path Traversal in ASP.NET occurs when an attacker manipulates file path inputs to access files outside the intended directory, such as ../../../etc/passwd. When HMAC signatures are used to protect route or query parameters (e.g., a signed file identifier), a common misconfiguration can weaken the protection. For example, an endpoint might accept a signed parameter like fileId=123&signature=abc, verify the HMAC, and then directly concatenate the decoded identifier into a filesystem path without proper validation. If the HMAC only covers part of the request—such as the identifier but not the resolved path or the user’s access context—an attacker who knows the signing algorithm and key material (or can leak it via other means) can forge valid signatures for other identifiers. Because the server trusts the signature and skips additional authorization checks, traversing paths becomes possible.
Consider an ASP.NET Core controller that uses HMAC to sign a file download token:
// Example: vulnerable composition of HMAC verification and path resolution
[HttpGet("download")]
public IActionResult Download(string fileId, string signature)
{
if (!VerifyHmac(fileId, signature))
{
return Unauthorized();
}
// Vulnerable: fileId used directly in path construction
var path = Path.Combine("/var/app/uploads", fileId);
if (!System.IO.File.Exists(path))
{
return NotFound();
}
var bytes = System.IO.File.ReadAllBytes(path);
return File(bytes, "application/octet-stream");
}
private bool VerifyHmac(string fileId, string signature)
{
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes("super-secret-key"));
var computed = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(fileId)));
return computed == signature;
}
If fileId is not canonicalized and the HMAC does not bind to the resolved absolute path, an attacker can supply fileId=../../../etc/passwd and a valid signature for that string, causing the server to read sensitive files. The risk is higher when the HMAC scope is narrow (e.g., only the user-controlled identifier) and the server skips checks such as Path.GetFullPath normalization or directory prefix enforcement. This pattern resembles issues seen in frameworks where signature validation is treated as a substitute for access control and input validation, a misalignment that can lead to unauthorized file disclosure.
Additionally, if logs or error messages inadvertently expose HMAC keys or the signing process is implemented differently across services (e.g., using timestamps or nonces inconsistently), the attack surface grows. For instance, an attacker who can observe multiple valid requests might infer key material or replay signatures if nonce management is weak. In such cases, Path Traversal is not only about directory escape but also about leveraging trust in the HMAC to bypass intended authorization layers. The vulnerability is not in HMAC itself—a secure cryptographic primitive—but in how its output is used to gate filesystem operations without complementary checks.
Hmac Signatures-Specific Remediation in Aspnet — concrete code fixes
To remediate Path Traversal when using HMAC signatures in ASP.NET, ensure that signature verification tightly binds to the intended resource and that any filesystem interaction is protected by multiple, independent checks. Do not rely on the HMAC alone to enforce path safety; treat it as one layer within a defense-in-depth strategy. The following approach combines HMAC verification with path canonicalization, prefix validation, and strict allowlisting.
First, scope the HMAC to include contextual data such as a resource type or a short-lived user identifier, and always resolve paths using canonical forms:
// Secure composition: canonicalize, prefix-check, and scope HMAC
[HttpGet("download")]
public IActionResult Download(string fileId, string signature)
{
// 1) Validate Hmac over a scoped payload
if (!VerifyHmac($"file:{fileId}", signature))
{
return Unauthorized();
}
// 2) Canonicalize and enforce a strict base directory
var baseDir = Path.GetFullPath("/var/app/uploads");
var candidate = Path.GetFullPath(Path.Combine(baseDir, fileId));
// 3) Ensure the resolved path remains within the allowed directory
if (!candidate.StartsWith(baseDir, StringComparison.Ordinal))
{
return Forbid();
}
if (!System.IO.File.Exists(candidate))
{
return NotFound();
}
var bytes = System.IO.File.ReadAllBytes(candidate);
return File(bytes, "application/octet-stream");
}
private bool VerifyHmac(string payload, string signature)
{
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes("super-secret-key"));
var computed = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(payload)));
// Use a time-constant comparison to avoid timing attacks
return CryptographicOperations.FixedTimeEquals(
Encoding.UTF8.GetBytes(computed),
Encoding.UTF8.GetBytes(signature));
}
Second, prefer GUIDs or opaque tokens for fileId instead of user-supplied filenames. This eliminates traversal risk at the source because tokens do not contain path characters. If filenames must be supported, normalize and sanitize them before combining with the base directory:
// Using a sanitized filename with Path.GetInvalidFileNameChars
string SanitizeFileName(string name)
{
var invalid = Path.GetInvalidFileNameChars();
return string.Concat(name.Split(invalid, StringSplitOptions.RemoveEmptyEntries));
}
var safeName = SanitizeFileName(Path.GetFileName(fileId)); // strips directory components
var path = Path.Combine(baseDir, safeName);
Third, align logging and monitoring to detect unusual signature requests that could indicate probing or key leakage. Combine these practices with OWASP API Top 10 references to Broken Object Level Authorization (BOLA) and Path Traversal, and note how controls such as input validation and authorization checks complement HMAC-based designs. The goal is not to make HMAC responsible for security boundaries but to use it as a verifiable token within a broader access control strategy.
Related CWEs: inputValidation
| CWE ID | Name | Severity |
|---|---|---|
| CWE-20 | Improper Input Validation | HIGH |
| CWE-22 | Path Traversal | HIGH |
| CWE-74 | Injection | CRITICAL |
| CWE-77 | Command Injection | CRITICAL |
| CWE-78 | OS Command Injection | CRITICAL |
| CWE-79 | Cross-site Scripting (XSS) | HIGH |
| CWE-89 | SQL Injection | CRITICAL |
| CWE-90 | LDAP Injection | HIGH |
| CWE-91 | XML Injection | HIGH |
| CWE-94 | Code Injection | CRITICAL |