The Ravens’ site lets you upload a profile picture, stores the file in a folder it serves to visitors, and never checks its type. If you upload a server-code file, it will run when opened.
The profile-picture upload in Ravens Members takes a file name and content and stores it in a folder the server serves to visitors. There is no file-type check, so you can upload a file that runs as server code — a web shell.
Upload a server-code file (a web shell) that will run on the server.
You uploaded a server-code file that runs.
Why the solution worked
An upload with no checks lets you plant code that runs on the server (a web shell), handing the attacker full control. The fix: validate the type with an allowlist of permitted extensions, actually inspect the file content (magic bytes), rename the file to a random name, and store it outside the web root or somewhere nothing executes, served through a path that does not run code.
The root cause
The server accepts any file and stores it in a folder that executes content, so a file with a code extension becomes a web shell. The root is no type check plus storing uploads where they can run.
How the code is fixed
An allowlist of types, content inspection, renaming, and storing outside the web root: four layers that complete each other.
Vulnerable code
app.post('/upload', (req, res) => {
// Stores whatever was sent, under the user's name, in a served folder.
fs.writeFileSync('/var/www/uploads/' + req.file.name, req.file.data);
res.json({ ok: true });
});
Safe code
const ALLOW = new Set(['image/png', 'image/jpeg']);
app.post('/upload', (req, res) => {
if (!ALLOW.has(detectType(req.file.data))) return res.status(400).end(); // check content
const name = randomId() + '.' + extFor(req.file.data); // rename
fs.writeFileSync('/srv/blobs/' + name, req.file.data); // outside web root
res.json({ ok: true });
});
Impact in the real world
Malicious file upload leads to remote code execution and full server takeover, among the most severe flaws in upload features.
How defenders detect it
Defenders alert on uploads with executable extensions, store uploads outside the web root with generated names, and disable their execution.