Command Injection in Hapi with Basic Auth
Command Injection in Hapi with Basic Auth — how this specific combination creates or exposes the vulnerability
Command Injection in a Hapi application using HTTP Basic Authentication occurs when untrusted input from an authenticated request is passed to a system command without proper validation or sanitization. Even when credentials are verified via Basic Auth, an attacker who has obtained or guessed a valid username and password can still exploit weak server-side handling to execute arbitrary shell commands.
In Hapi, route handlers often receive parameters from authentication artifacts (e.g., credentials stored in request.auth.credentials) combined with query or payload inputs. If these values are used to construct shell commands—such as calling child_process.exec or child_process.spawn with concatenated strings—an attacker can inject shell metacharacters like ;, &&, or backticks to alter command logic. For example, a route that builds a system command using a username from Basic Auth and a user-supplied filename can become a vector for OS command execution.
Because Basic Auth transmits credentials in an encoded (not encrypted) format unless protected by TLS, an attacker who intercepts or reuses a valid token can repeatedly abuse a vulnerable endpoint. The presence of valid credentials does not prevent command injection; it simply means the attacker has cleared the authentication barrier. Once injection is possible, outcomes can include unauthorized file access, environment enumeration, or lateral movement, depending on the server’s permissions.
middleBrick detects this risk by analyzing OpenAPI/Swagger specs with full $ref resolution and correlating them with runtime tests. Among its 12 parallel security checks, Input Validation flags unsafe usage of external input in command construction, while Authentication and BOLA/IDOR checks verify whether credentials are handled in a way that prevents privilege misuse. The scanner does not fix the code but provides severity-ranked findings with remediation guidance, mapping to OWASP API Top 10 and other compliance frameworks.
Basic Auth-Specific Remediation in Hapi — concrete code fixes
To mitigate Command Injection in Hapi while using Basic Auth, avoid building shell commands from any request-derived data, including authenticated user information. Use parameterized APIs, strict allowlists, and server-side validation. The following examples show vulnerable patterns and secure alternatives.
Vulnerable Hapi route with Basic Auth and command injection risk:
const Hapi = require('@hapi/hapi');
const { exec } = require('child_process');
const init = async () => {
const server = Hapi.server({ port: 4000, host: 'localhost' });
server.auth.scheme('custombasic', () => ({
authenticate(request, h) {
const credentials = request.headers.authorization;
if (!credentials || !/^Basic\s(\S+)$/.test(credentials)) {
return { isValid: false };
}
const token = credentials.split(' ')[1];
const userBuffer = Buffer.from(token, 'base64');
const userPass = userBuffer.toString('utf8');
const [user, pass] = userPass.split(':');
if (user === 'admin' && pass === 'secret123') {
return { isValid: true, credentials: { user } };
}
return { isValid: false };
}
}));
server.auth.strategy('default', 'custombasic');
server.route({
method: 'GET',
path: '/ping/{filename}',
options: {
auth: 'default',
handler: (request, h) => {
const { filename } = request.params;
const username = request.auth.credentials.user;
// Dangerous: using user input in shell command
exec(`echo ${username} > /tmp/${filename}`, (err, stdout, stderr) => {
if (err) return { error: err.message };
return { stdout };
});
}
}
});
await server.start();
};
init();
In the example above, filename from the route parameter and username from Basic Auth are concatenated into a shell command. An authenticated attacker could supply ../../../etc/passwd or use shell metacharacters to read arbitrary files or change behavior.
Secure Hapi route with input validation and safe APIs:
const Hapi = require('@hapi/hapi');
const { execFile } = require('child_process');
const init = async () => {
const server = Hapi.server({ port: 4000, host: 'localhost' });
server.auth.scheme('custombasic', () => ({
authenticate(request, h) {
const credentials = request.headers.authorization;
if (!credentials || !/^Basic\s(\S+)$/.test(credentials)) {
return { isValid: false };
}
const token = Buffer.from(credentials.split(' ')[1], 'base64').toString('utf8');
const [user, pass] = token.split(':');
if (user === 'admin' && pass === 'secret123') {
return { isValid: true, credentials: { user } };
}
return { isValid: false };
}
}));
server.auth.strategy('default', 'custombasic');
server.route({
method: 'GET',
path: '/ping/{filename}',
options: {
auth: 'default',
handler: (request, h) => {
const { filename } = request.params;
const username = request.auth.credentials.user;
// Safe: use execFile with explicit arguments and no shell
return new Promise((resolve, reject) => {
execFile('echo', [username], { timeout: 5000 }, (err, stdout, stderr) => {
if (err) return reject({ error: err.message });
// Further validate filename to prevent path traversal
if (!/^[a-zA-Z0-9._-]+$/.test(filename)) {
return reject({ error: 'Invalid filename' });
}
const fs = require('fs');
fs.writeFileSync(`/tmp/${filename}`, stdout);
resolve({ status: 'ok' });
});
});
}
}
});
await server.start();
};
init();
The secure version uses execFile with explicit arguments to avoid shell interpretation, validates filename against an allowlist, and removes direct concatenation of user input into shell commands. This approach aligns with remediation guidance provided by middleBrick findings, which highlight unsafe consumption patterns and offer prioritized steps.
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 |