HIGH cwe 22restify

CWE-22 in Restify

How Cwe 22 Manifests in Restify

CWE-22 (Path Traversal) occurs when an application uses attacker-controlled input to construct file paths without proper validation. In Restify applications, this vulnerability commonly appears in several specific patterns:

const restify = require('restify');
const fs = require('fs');
const server = restify.createServer();

// Vulnerable: direct path concatenation
server.get('/download/:filename', (req, res) => {
const filePath = `/uploads/${req.params.filename}`;
fs.readFile(filePath, (err, data) => {
if (err) return res.send(404);
res.send(data);
});
});

// Vulnerable: path.join without normalization
server.get('/static/:file', (req, res) => {
const filePath = path.join(__dirname, 'public', req.params.file);
fs.readFile(filePath, (err, data) => {
if (err) return res.send(500);
res.send(data);
});
});

// Vulnerable: user-controlled directory traversal
server.get('/user-files/:user/:file', (req, res) => {
const filePath = path.join(__dirname, 'files', req.params.user, req.params.file);
fs.readFile(filePath, (err, data) => {
if (err) return res.send(404);
res.send(data);
});
});

Attackers can exploit these patterns by sending requests like:

GET /download/../../etc/passwd
GET /static/../../package.json
GET /user-files/../../../../etc/passwd

The core issue is that Restify's default routing doesn't sanitize path parameters. When combined with Node.js's path.join() or string concatenation, attackers can navigate outside intended directories using ../ sequences.

Restify's middleware architecture makes this particularly dangerous because path parameters are accessible throughout the request lifecycle. Even if you validate later in your handler, the path has already been constructed insecurely.

Another Restify-specific manifestation occurs with file uploads and static serving:

const serveStatic = require('serve-static');
server.get('/static/:path', serveStatic(__dirname + '/public'));

// Vulnerable: dynamic file serving without validation
server.get('/upload/:user/:filename', (req, res) => {
const userDir = path.join(__dirname, 'uploads', req.params.user);
const filePath = path.join(userDir, req.params.filename);
fs.createReadStream(filePath).pipe(res);
});

The last example is especially problematic because it allows directory traversal across user boundaries, potentially exposing other users' files.

Restify-Specific Detection

Detecting CWE-22 in Restify applications requires both static analysis and runtime scanning. Here's how to identify path traversal vulnerabilities:

Static Code Analysis

// Search for dangerous patterns in your Restify codebase
const fs = require('fs');
const path = require('path');

function scanForPathTraversal(filePath) {
const code = fs.readFileSync(filePath, 'utf8');
const patterns = [
/path\.join\(.*req\./g, // path.join with request params
/\+\s*req\./g, // string concatenation with request params
/fs\.readFile\(.*req\./g, // fs.readFile with request params
/fs\.createReadStream\(.*req\./g // fs.createReadStream with request params
];

const findings = [];
patterns.forEach(pattern => {
const matches = code.match(pattern);
if (matches) {
findings.push({
pattern: pattern.toString(),
count: matches.length,
file: filePath
});
}
});
return findings;
}

Runtime Scanning with middleBrick

middleBrick provides automated CWE-22 detection for Restify APIs through black-box scanning. Simply provide your API URL:

# Install middleBrick CLI
npm install -g middlebrick

# Scan your Restify API endpoint
middlebrick scan https://api.yourservice.com

# Or integrate into your CI/CD pipeline
middlebrick scan --url https://api.yourservice.com --fail-below B

middleBrick tests for path traversal by attempting to access files outside your intended directories using common traversal sequences:

../etc/passwd
../../etc/passwd
..\..\..\windows\system32\drivers\etc\hosts
/.//././etc/passwd

The scanner reports findings with severity levels and specific remediation guidance. For Restify applications, middleBrick identifies:

  • Unvalidated path parameters in route definitions
  • Unsafe file system operations using request data
  • Missing input validation for file paths
  • Directory traversal attempts that succeed

Manual Testing

Test your Restify endpoints manually by attempting to access known system files:

# Test path traversal attempts
curl -v https://api.yourservice.com/download/../../etc/passwd
curl -v https://api.yourservice.com/static/../../../../etc/passwd

Look for HTTP 200 responses with file contents, which indicate successful traversal.

Restify-Specific Remediation

Securing Restify against CWE-22 requires a defense-in-depth approach. Here are Restify-specific remediation strategies:

1. Input Validation with Path Normalization

const restify = require('restify');
const path = require('path');
const fs = require('fs');
const server = restify.createServer();

// Secure file serving with validation
function safeReadFile(baseDir, userPath) {
const normalized = path.normalize(userPath);

// Verify the resolved path is within the base directory
if (!resolved.startsWith(baseDir)) {
throw new Error('Path traversal attempt detected');
}

return resolved;
}

server.get('/download/:filename', (req, res) => {
try {
const safePath = safeReadFile(__dirname + '/uploads', req.params.filename);
fs.readFile(safePath, (err, data) => {
if (err) return res.send(404);
res.send(data);
});
} catch (error) {
res.send(400, { error: 'Invalid file path' });
}
});

2. Whitelist-Based File Access

const allowedFiles = new Set(['document.pdf', 'report.xlsx', 'photo.jpg']);

server.get('/download/:filename', (req, res) => {
const filename = req.params.filename;

if (!allowedFiles.has(filename)) {
return res.send(400, { error: 'File not allowed' });
}

const filePath = path.join(__dirname, 'uploads', filename);
fs.readFile(filePath, (err, data) => {
if (err) return res.send(404);
res.send(data);
});
});

3. Restify Middleware for Path Validation

function pathTraversalProtection(req, res, next) {
const dangerousPatterns = [
///////, // multiple slashes
/////////, // excessive slashes
/\.\./, // parent directory
/\x00/ // null byte injection
];

const { filename } = req.params;
if (filename && dangerousPatterns.some(pattern => pattern.test(filename))) {
return res.send(400, { error: 'Invalid file path' });
}
next();
}

server.get('/download/:filename', pathTraversalProtection, (req, res) => {
const filePath = path.join(__dirname, 'uploads', req.params.filename);
fs.readFile(filePath, (err, data) => {
if (err) return res.send(404);
res.send(data);
});
});

4. Using Restify's Built-in Security Features

const restify = require('restify');
const server = restify.createServer();

// Add security middleware
server.use(restify.plugins.conditionalRequest());
server.use(restify.plugins.acceptParser(server.acceptable));

// Custom security middleware
function securityHeaders(req, res, next) {
res.setHeader('X-Content-Type-Options', 'nosniff');
res.setHeader('X-Frame-Options', 'DENY');
next();
}

server.use(securityHeaders);

// Secure static file serving
const serveStatic = require('serve-static');
const safeStatic = serveStatic(__dirname + '/public', {
fallthrough: false,
setHeaders: (res, path) => {
if (!path.startsWith(__dirname + '/public')) {
res.statusCode = 403;
res.end();
}
}
});

server.get('/static/:path', (req, res, next) => {
safeStatic(req, res, next);
});

5. Regular Security Scanning

Integrate middleBrick into your development workflow to continuously scan for CWE-22:

# .github/workflows/security.yml
name: Security Scan
on: [push, pull_request]

jobs:
security-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Scan for Path Traversal
run: |
npm install -g middlebrick
middlebrick scan https://staging.yourservice.com --fail-below B
continue-on-error: true

6. Runtime Protection

function validateFilePath(baseDir, userPath) {
// Normalize and resolve the path
const normalized = path.normalize(userPath);
const resolved = path.resolve(baseDir, normalized);

// Check if resolved path is within base directory
if (!resolved.startsWith(baseDir)) {
return { valid: false, error: 'Path traversal detected' };
}

// Check if file exists and is accessible
try {
const stats = fs.statSync(resolved);
if (!stats.isFile()) {
return { valid: false, error: 'Not a file' };
}
return { valid: true, path: resolved };
} catch (err) {
return { valid: false, error: 'File not found' };
}
}

By implementing these Restify-specific protections, you create multiple layers of defense against path traversal attacks, significantly reducing your API's attack surface.

Frequently Asked Questions

How can I test my Restify API for CWE-22 vulnerabilities?
Use middleBrick's automated scanning by running 'middlebrick scan ' which tests for path traversal attempts. You can also manually test by sending requests with '../' sequences to see if you can access files outside your intended directories. Look for HTTP 200 responses with file contents as indicators of successful traversal.
What's the most effective way to prevent path traversal in Restify?
Implement a combination of input validation, path normalization, and whitelist-based access control. Use path.resolve() to ensure resolved paths stay within your base directory, validate all user-supplied paths against a whitelist of allowed files, and add middleware that checks for dangerous patterns like '../' sequences before processing requests.