UPLOAD FILE VULNERABILITY with multer - node.js

I am using multer to upload file in my application.
like: https://github.com/expressjs/multer/blob/master/README.md
Can path traversal vulnerability possible ? If yes then tell us how we can stop this?
Currenlty, I am using below code. I just want to confirm, Is there any file vulnerable risk? Please comment.
var storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, 'uploads/');
},
filename: function (req, file, cb) {
console.log(file);
var ext = file.originalname.split('.').pop();
cb(null, Date.now() + '_' + file.originalname);
}});
const fileFilter = (req, file, cb) => {
// Accept or reject the file based on if MIME type is found in accepted list
if (acceptedMimeTypes.indexOf(file.mimetype) < 0) {
return cb("エラー:このタイプのファイルはアップロードできません。ZIP形式とLZH形式のファイルのみアップロードしてください。", false) // Error: You can't upload files of this type. Please upload images and zips only.
}
else {
return cb(null, true);
}
}
var upload = multer({ storage: storage, fileFilter: fileFilter, limits: { fileSize: 1024 * 1024 * 1 } }).single('file');
If there is any risk then please suggest me a better approach with expressjs multer.

You can modify the fileName using this code so no one can threaten you :
const storage = multer.diskStorage({
destination: './public',
filename(req, file, cb) {
cb(null, 'Your File Name');
},
});
and also you can make it dynamic using randomatic and time like this :
const storage = multer.diskStorage({
destination: './public',
filename(req, file, cb) {
cb(null, `${new Date().getTime()}`);
},
});

Related

multipart file upload not working using multer's diskStorage

nodejs
I am using multer to upload file in nodejs. The below code seems to work fine.
const upload = multer({ dest: "uploads/" });
But the code below doesn't work.
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "./uploads/");
},
filename: function (req, file, cb) {
cb(null, new Date().toISOString() + file.originalname);
},
});
Any idea on how to solve it?

How can I rename uploaded file in Multer with progressive numbers?

I'm uploading images on the server and when I get the images in Express js using Multer, I'm not able to rename them with a progressive number like:
nameImage_1.jpg
nameImage_2.jpg
nameImage_3.jpg
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "./assets/img/products/");
},
filename: function (req, file, cb) {
cb(null, file.originalname);
},
});
some ideas ??
THX
I don't know if this will help you but I have it like this
var storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, __basedir + "/csvs/");
},
filename: (req, file, cb) => {
console.log(file.originalname);
cb(null, `${Date.now()}-name-${file.originalname}`);
},
});

How to define multer storage in different file?

I have a node application with express.
The server is at server.js and I have routers set up like the following:
app.use('/xyz', xyz);
app.use('/abc', abc);
The routers xyz and abc are in different route modules in /routes.
I want to use multer to upload images to MongoDB. The endpoint for uploading files is /xyz/upload
storage = new GridFsStorage({
url: process.env.DB_URL,
file: (req, file) => {
return new Promise((resolve, reject) => {
const filename = file.originalname;
const fileInfo = {
filename: filename,
bucketName: 'uploads'
};
resolve(fileInfo);
});
}
});
How can I define this const upload = multer({ storage }); in the xyz router file?
All the examples on the internet show multer being defined in server.js and app.post(). What to do if I have a router defined in a different module?
If you are looking for a cleaner architecture then I would suggest following the separation of concerns principle (SoC) and treat the file handling middleware in a separate file as follows:
const multer = require("multer");
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "./public/uploads");
},
filename: function (req, file, cb) {
const uniqueSuffix = Date.now() + "-" + Math.round(Math.random() * 1e9);
cb(
null,
new Date().getTime() + "-" + uniqueSuffix + "-" + file.originalname
);
},
});
const fileFilter = (req, file, cb) => {
// reject all files except jpeg
if (file.mimetype === "image/jpeg") {
cb(null, true);
} else {
cb(null, false);
}
};
module.exports = multer({
storage: storage,
limits: {
fileSize: 1024 * 1024 * 15, // 15mb max size,
},
fileFilter: fileFilter,
});
then, in your routes, a simple require if you are working with CommonJS should be enough:
const upload = require("./fileHandling");
server.post(
`/route`,
upload.array('Photos', 6),
controller,
);
It did the trick for me, hope it helps!

Double backslash into path

I have using this the tuttorial of Academind how to load image using multer into node JavaScript rest service.
About path destination folder I use this code:
const storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, './uploads/');
},
filename: function(req, file, cb) {
cb(null, file.originalname);
}
});
const fileFilter = (req, file, cb) => {
// reject a file
if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
cb(null, true);
} else {
cb(null, false);
}
};
const upload = multer({
storage: storage,
limits: {
fileSize: 1024 * 1024 * 5
},
fileFilter: fileFilter
});
But the path generated have double backslash that show as one backslash:
uploads\2018-09-16T13-02-45.535Z1536685465dummy4.jpg
How I can replace destination path with slash?
i had the same issue, and since i didn't find anything i did this as a work around
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads/');
},
filename: function (req, file, cb) {
cb(null, `${new Date().toISOString().replace(/:/g, '-')}${file.originalname.split(" ").join("_")}`);
}
});
const user= new User({
_id : new mongoose.Types.ObjectId(),
name : req.body.name,
image: req.file.destination + req.file.filename,
});

multer save image without mimetype

I'm using "multer": "^1.0.6", And i Want to save image in upload folder.
My code is
app.post('/post', multer({dest: './uploads/'}).single('file'), function (req, res) {
response = {
message: 'File uploaded successfully',
filename: req.file.filename
};
res.end(JSON.stringify(response));
});
But I Have the file with this name in upload folder 8e6e425f8756e0bafb40ed1a3cb86964
Why I have this name without mimetype?
Multer saves files without extensions you can read this on GitHub:
filename is used to determine what the file should be named inside the folder. If no filename is given, each file will be given a random name that doesn't include any file extension.
If you want to save with the extension that you write your code like here:
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, '/tmp/my-uploads')
},
filename: function (req, file, cb) {
cb(null, file.originalname); // modified here or user file.mimetype
}
})
var upload = multer({ storage: storage })
All information you can find here https://github.com/expressjs/multer/blob/master/README.md
Multer not worried about the extension of the file and leave it completely on your side: you have to define itself a function that will do it. For example, like this:
var multer = require('multer');
var upload = multer({ storage: multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads');
},
filename: function (req, file, cb) {
var ext = require('path').extname(file.originalname);
ext = ext.length>1 ? ext : "." + require('mime').extension(file.mimetype);
require('crypto').pseudoRandomBytes(16, function (err, raw) {
cb(null, (err ? undefined : raw.toString('hex') ) + ext);
});
}
})});
app.post('/post', upload.single('file'), function (req, res) {
response = {
message: 'File uploaded successfully',
filename: req.file.filename
};
res.end(JSON.stringify(response));
});

Resources