CVE-2022-25848 is a serious Directory Traversal vulnerability found in the popular Node.js package static-dev-server. This security hole can allow attackers to access sensitive files outside the specified static directory simply by manipulating URL paths – making it a risk for any project using this package in any version.
In this deep dive, we’ll explain how CVE-2022-25848 works, why it happens, provide code samples and exploitation details, and suggest fixes. If you use static-dev-server for local development or in production, you’ll want to read this!
What is static-dev-server?
static-dev-server is a lightweight Node.js package that makes it easy to serve static files during development. It’s widely used for quickly spinning up servers for front-end projects.
How it should work
When the server receives a request, it joins the requested path with a pre-defined root directory and serves the corresponding file. For example:
// Example (not vulnerable) path joining:
const filePath = path.join(rootDir, requestedUrlPath);
Ideally, this makes sure users can access files *only* within the rootDir folder.
What’s the Vulnerability?
CVE-2022-25848 is a Directory Traversal vulnerability. The problem is that the static-dev-server did not properly sanitize user input in URL paths. So, if an attacker sends a path like /../../etc/passwd, the code may resolve it to a file outside of the intended root directory – e.g., your system password file (!).
Why is this possible?
The vulnerable code simply joins the user-supplied path to the root directory without checking for directory traversal patterns (../). Node.js’s path.join() will resolve these, possibly pointing *outside* the root directory.
Here’s a simplified version illustrating the unsafe logic
const http = require('http');
const path = require('path');
const fs = require('fs');
const rootDir = '/var/www/public';
http.createServer((req, res) => {
let filePath = path.join(rootDir, req.url);
fs.readFile(filePath, (err, data) => {
if (err) {
res.writeHead(404);
return res.end('Not found');
}
res.writeHead(200);
res.end(data);
});
}).listen(808);
Problem:
If an attacker requests http://localhost:808/../../etc/passwd, filePath would resolve to /etc/passwd on Unix-like systems.
An attacker can craft a URL such as
GET /../../../../etc/passwd HTTP/1.1
Host: victim.com
If the server is running as root or a user with enough permission
- /etc/passwd is read and sent to the attacker’s browser
Proof of Concept with curl
curl http://localhost:808/../../../../etc/passwd
References
- NPM Advisory – static-dev-server
- Snyk CVE entry
- Official CVE reference
How to Fix?
The best way is to make sure resolved file paths are always within your root directory. Here’s how you can make your code safe:
http.createServer((req, res) => {
const requestedPath = decodeURIComponent(req.url);
const safePath = path.normalize(path.join(rootDir, requestedPath));
// Check if the final path is inside rootDir
if (!safePath.startsWith(rootDir)) {
res.writeHead(403);
return res.end('Forbidden');
}
fs.readFile(safePath, (err, data) => {
if (err) {
res.writeHead(404);
return res.end('Not found');
}
res.writeHead(200);
res.end(data);
});
}).listen(808);
This fix ensures an attacker cannot escape the root directory.
Conclusion
CVE-2022-25848 is a classic example of why it’s vital to sanitize user input, especially in file-serving code. Directory traversal bugs remain a favorite tool for attackers, and fixing them is usually simple but crucial.
Stay safe and keep your dependencies up to date!
*For more details, always check the official advisories and monitor feeds like NVD.*
*Exclusive for you by GPT – keep learning, keep coding securely!*
Timeline
Published on: 11/29/2022 17:15:00 UTC
Last modified on: 12/01/2022 20:56:00 UTC