Lack of data validation - Path Traversal In tar
Description
node-tar Vulnerable to Arbitrary File Creation/Overwrite via Hardlink Path Traversal
Summary
node-tar contains a vulnerability where the security check for hardlink entries uses different path resolution semantics than the actual hardlink creation logic. This mismatch allows an attacker to craft a malicious TAR archive that bypasses path traversal protections and creates hardlinks to arbitrary files outside the extraction directory.
Details
The vulnerability exists in lib/unpack.js. When extracting a hardlink, two functions handle the linkpath differently:
Security check in [STRIPABSOLUTEPATH]:
const entryDir = path.posix.dirname(entry.path); const resolved = path.posix.normalize(path.posix.join(entryDir, linkpath)); if (resolved.startsWith('../')) { /* block */ }
Hardlink creation in [HARDLINK]:
const linkpath = path.resolve(this.cwd, entry.linkpath); fs.linkSync(linkpath, dest);
Example: An application extracts a TAR using tar.extract({ cwd: '/var/app/uploads/' }). The TAR contains entry a/b/c/d/x as a hardlink to ../../../../etc/passwd.
Security check resolves the linkpath relative to the entry's parent directory: a/b/c/d/ + ../../../../etc/passwd = etc/passwd. No ../ prefix, so it passes.
Hardlink creation resolves the linkpath relative to the extraction directory (this.cwd): /var/app/uploads/ + ../../../../etc/passwd = /etc/passwd. This escapes to the system's /etc/passwd.
The security check and hardlink creation use different starting points (entry directory a/b/c/d/ vs extraction directory /var/app/uploads/), so the same linkpath can pass validation but still escape. The deeper the entry path, the more levels an attacker can escape.
PoC
Setup
Create a new directory with these files:
poc/ ├── package.json ├── secret.txt ← sensitive file (target) ├── server.js ← vulnerable server ├── create-malicious-tar.js ├── verify.js └── uploads/ ← created automatically by server.js └── (extracted files go here)...
package.json
{ "dependencies": { "tar": "^7.5.0" } }
secret.txt (sensitive file outside uploads/)
DATABASE_PASSWORD=supersecret123
server.js (vulnerable file upload server)
const http = require('http'); const fs = require('fs'); const path = require('path'); const tar = require('tar'); const PORT = 3000; const UPLOAD_DIR = path.join(__dirname, 'uploads'); fs.mkdirSync(UPLOAD_DIR, { recursive: true });...
create-malicious-tar.js (attacker creates exploit TAR)
const fs = require('fs'); function tarHeader(name, type, linkpath = '', size = 0) { const b = Buffer.alloc(512, 0); b.write(name, 0); b.write('0000644', 100); b.write('0000000', 108); b.write('0000000', 116); b.write(size.toString(8).padStart(11, '0'), 124); b.write(Math.floor(Date.now()/1000).toString(8).padStart(11, '0'), 136); b.write(' ', 148);...
Run
# Setup npm install echo "DATABASE_PASSWORD=supersecret123" > secret.txt # Terminal 1: Start server node server.js # Terminal 2: Execute attack...
Impact
An attacker can craft a malicious TAR archive that, when extracted by an application using node-tar, creates hardlinks that escape the extraction directory. This enables:
Immediate (Read Attack): If the application serves extracted files, attacker can read any file readable by the process.
Conditional (Write Attack): If the application later writes to the hardlink path, it modifies the target file outside the extraction directory.
Remote Code Execution / Server Takeover
Attack Vector | Target File | Result |
|---|---|---|
SSH Access | ~/.ssh/authorized_keys | Direct shell access to server |
Cron Backdoor | /etc/cron.d/*, ~/.crontab | Persistent code execution |
Shell RC Files | ~/.bashrc, ~/.profile | Code execution on user login |
Web App Backdoor | Application .js, .php, .py files | Immediate RCE via web requests |
Systemd Services | /etc/systemd/system/*.service | Code execution on service restart |
User Creation | /etc/passwd (if running as root) | Add new privileged user |
Data Exfiltration & Corruption
Overwrite arbitrary files via hardlink escape + subsequent write operations
Read sensitive files by creating hardlinks that point outside extraction directory
Corrupt databases and application state
Steal credentials from config files, .env, secrets
Mitigation
Update Impact
Minimal update. May introduce new vulnerabilities or breaking changes.
Aliases
References