Reputation: 217
I am trying to learn security best practices for NodeJS/Express. How can I secure this file upload? Currently, it just places files in a folder. I concerned about users uploading malicious files/code.
This is a simple file upload that comes from a form on my react frontend. The goal is to allow people to upload avatars for their profile. I am using Formidable, so I can check the type of the images, but I am wondering if this is secure enough?
server.js
const express = require('express');
const server = express();
server.listen(8000, () => {
console.log('Server started!');
});
server.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept',
);
});
const upload = require('./upload');
server.post('/upload', upload);
upload.js
const IncomingForm = require('formidable').IncomingForm;
module.exports = function upload(req, res) {
var form = new IncomingForm();
form.parse(req);
form.on('file', (field, file) => {
console.log(file);
});
form.on('fileBegin', function(name, file) {
file.path = __dirname + '/uploads/' + file.name;
});
form.on('end', () => {
res.json();
});
};
Upvotes: 1
Views: 3142
Reputation: 2493
Following 2 steps are basic steps.
In frontend only allow specific file extensions like(.pdf,.png etc.) with limitations like size. (Don't forget front end code can be manipulated). 2.You shoul also need to check file extenstions & sizes in backend(if you are using node you can use multer to achieve this.)
What more we can do in backend?
If we only rely on checking with extensions it doesn't help. (anyone can modify name of sample.exe to sample.jpg & upload). For example if you check whether file uploaded image or not in backend other than checking with file extension you can follow below approach also.
The first eight bytes of a PNG file always contain the following (decimal) values: 137 80 78 71 13 10 26 10
If you want to check whether uploaded file is png or not above condition will work. Not only that if you want to check files uploaded properly or not you can follow some approaches like mentioned above. (for .pdf, .doc some rules might be there). You can check MIME signature data which is the best practice.
Don't save uploaded files in backend code repository. Store them some other workspace. (optional) Following links might help.
Cloud Storages
Other than storing files in local server you can save uploaded files on cloud like amazon s3 bucket. After every time any file is uploaded to that s3 bucket you can trigger scanner using lambdas(automatic file scanners on amazon).
Other than amazon you can also use google drive for files upload (not optimal one). But when someone downloads uploaded file google will automatically scan for viruses.
amazon's s3 bucket file's scan links::
amazon s3 bucket files scan SO
s3 files scanning using lambda & clamav
For local server::
check image content without extension SO 1
check image content without extensions SO 2
Upvotes: 1
Reputation: 371
You could also check the MIME Content-type with the request:
if (contype.indexOf('image/png') !== 0)
Also, checking for file extensions:
file.extname('cool_picture.png')
And last but not least, check for file headers in hex format. All file types start with a sequence of hex digits. What does that mean?
PNG always start with the sequence: 5089 474e 0a0d 0a1a
JPG always start with the sequence: d8ff e0ff 1000 464a
And so on, so you can create basic strings or arrays with the initial file headers for images, like PNG_HEADER = '5089 474e 0a0d 0a1a';
, read the file headers on the upload and compare if matches the file content-type and extension.
This should be ok for your upload.
Upvotes: 2