Xpath Injection in Fiber with Hmac Signatures
Xpath Injection in Fiber with Hmac Signatures — how this specific combination creates or exposes the vulnerability
XPath Injection occurs when an attacker can influence an XPath expression used to query XML or HTML documents, leading to data extraction or bypass of authorization. In Fiber, a common pattern is to validate incoming requests using Hmac Signatures to ensure integrity and authenticity. If a request parameter that influences the XPath expression is included in the Hmac calculation without strict validation, an attacker may be able to tamper with the parameter while still producing a valid Hmac, provided the server’s key is unknown.
Consider a scenario where a Fiber handler uses a query parameter user_id to select user data from an XML store via XPath, and the Hmac is computed over the full URL including that parameter. An attacker who can observe or guess a valid Hmac for a benign user_id might attempt to change the parameter to another user’s ID. Because the Hmac verifies integrity but not semantic safety, the server may process the malicious XPath, leading to Insecure Direct Object Reference (IDOR) or BOLA. This is especially risky when combined with XPath expressions that do not use parameterized queries, allowing concatenation of attacker-controlled strings directly into the path.
Furthermore, if the Hmac is computed over only part of the request (e.g., the path and headers but not the query), an attacker can modify the query to inject XPath predicates without invalidating the signature. For example, changing ?user_id=123 to ?user_id=123 or 1=1 could alter the XPath evaluation logic if the application constructs expressions like //user[id=' + user_id + ']. The server may interpret this as a boolean injection in the XPath context, returning unintended nodes or bypassing access controls. Because the Hmac remains valid, the server trusts the request, and the vulnerability manifests as unauthorized data access or privilege escalation.
Compounding the issue, if the application deserializes XML using an unsafe parser that supports external entity references, an attacker might combine XPath Injection with SSRF or data exfiltration techniques. The Hmac does not protect against unsafe parsing behaviors; it only ensures the request has not been altered in transit. Therefore, the combination of dynamic XPath construction and Hmac-signed requests can create a blind spot where integrity checks pass while the underlying query logic is compromised.
Hmac Signatures-Specific Remediation in Fiber — concrete code fixes
To mitigate XPath Injection when using Hmac Signatures in Fiber, ensure that the parameters influencing XPath expressions are strictly validated, normalized, and excluded from integrity-sensitive contexts where possible. Use parameterized XPath APIs rather than string concatenation. If dynamic values must be used, encode or whitelist them before inclusion in the Hmac calculation so that tampering changes the signature.
Example 1: Safe XPath with parameterized evaluation in Fiber
Instead of building XPath via string interpolation, use a library that supports compiled expressions or positional parameters. Below is a realistic example using a hypothetical XPath library in Fiber that supports parameterized queries:
const express = require('express');
const bodyParser = require('body-parser');
const crypto = require('crypto');
const { evaluateXPath } = require('xpath-helpers'); // hypothetical safe library
const app = express();
app.use(bodyParser.json());
function verifyHmac(req) {
const key = process.env.HMAC_KEY;
const expected = req.headers['x-hmac'];
const payload = req.method + req.path + JSON.stringify(req.body);
const computed = crypto.createHmac('sha256', key).update(payload).digest('hex');
return crypto.timingSafeEqual(Buffer.from(computed), Buffer.from(expected));
}
app.post('/user', (req, res) => {
if (!verifyHmac(req)) {
return res.status(401).send('Invalid signature');
}
const userId = req.body.userId;
if (!Number.isInteger(userId) || userId <= 0) {
return res.status(400).send('Invalid user ID');
}
// Use parameterized XPath; userId is passed as a variable, not concatenated
const result = evaluateXPath('//user[id=$id]', { id: userId });
res.json(result);
});
app.listen(3000);
Example 2: Hmac computed after canonicalizing and filtering parameters
If you must include query parameters in the Hmac, canonicalize the input and exclude dangerous ones from the XPath construction:
const crypto = require('crypto');
function buildCanonicalString(urlObj) {
// Only include safe, expected parameters
const params = new URLSearchParams();
if (urlObj.searchParams.has('user_id')) {
const val = urlObj.searchParams.get('user_id');
if (/^\d+$/.test(val)) {
params.set('user_id', val);
}
}
return params.toString();
}
app.get('/data', (req, res) => {
const canonical = buildCanonicalString(req.url);
const key = process.env.HMAC_KEY;
const signature = crypto.createHmac('sha256', key).update(canonical).digest('hex');
const expected = req.headers['x-hmac'];
if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
return res.status(401).send('Invalid signature');
}
const userId = req.url.searchParams.get('user_id');
// Use userId safely in XPath with parameterization
const users = selectNodes(`//user[id=${encodeURIComponent(userId)}]`); // hypothetical safe selector
res.json(users);
});
General recommendations
- Never directly concatenate user input into XPath strings.
- Use libraries that support variable binding or compiled XPath expressions.
- Validate and sanitize all inputs before using them in XPath or any query language.
- Ensure the Hmac covers all parts of the request that influence behavior, or explicitly exclude non-essential parameters from the signed payload to avoid mismatch between integrity and safety checks.