Kiril
Kiril

Reputation: 331

How to protect request url against going upper in NodeJS?

I'm trying to develope simple server in pure NodeJS for my own purposes. The problem I recently realized is that there is a little possibility to go upper or elsewhere from web on my local machine by adding something like ../../../ in path. My server looks like this:

var server = require('http').createServer(function(request, response) {
    var file_path = './web' + request.url;

    if (file_path == './web/')
        file_path = file_path + 'index.html';

    var extname = path.extname(file_path);

    switch (extname) {
        case '.js':
            content_type = 'text/javascript';
            break;
        case '.css':
            content_type = 'text/css';
            break;
        case '.json':
            content_type = 'application/json';
            break;
        default:
            content_type = 'text/html';
            break;
    }


    fs.readFile(file_path, 'utf8', function (err, data) {
        if (err) {
            response.writeHead(404);

            return response.end('Error loading ' + request.url);
        }

        response.writeHead(200, {'Content-Type': content_type});

        return response.end(data);
    });
});

So I'm wondering what is the best way to protect from such things?

Upvotes: 2

Views: 213

Answers (2)

jfriend00
jfriend00

Reputation: 707366

Let's say the root for your web files is /web/files and you want to make sure that no request outside that hierarchy is processed. You can use path.normalize() to process all the . and .. in it to then check the resulting path like this:

var path = require('path');

var file_path = '/web/files' + request.url;
var resolvedPath = path.normalize(file_path);
if (resolvedPath.indexOf('/web/files/') !== 0) {
    // illegal request
}

You can read about path.normalize() here. It resolves all . and .. segements in a path so you can see what the real path will look like and then see if that is still a legal path.


Or, in a utility function:

var path = require('path');

function isPathContained(testPath, containerPath) {
    var resolvedPath = path.normalize(fullPath);
    return resolvedPath.indexOf(containerPath) === 0;
}

Then, you would use that like this:

var webFiles = '/web/files';
var file_path =  webFiles + request.url;
if (!isPathContained(file_path, webFiles)) {
    // illegal request
}

Upvotes: 1

Roman Dibikhin
Roman Dibikhin

Reputation: 856

Just use Express.js Static Files for this.

Upvotes: 1

Related Questions