Listening Everywhere, Asking Nothing — JavaScript Bug Hunt

Modelled on the exposed MongoDB databases of 2015. MongoDB releases of the time did not require authentication by default and, depending on how they were…

  • Language: JavaScript
  • Layer: Database
  • Difficulty: Medium
  • Concepts: Security, Config, Networking
  • Modelled on: MongoDB · 2015
  • Visible tests: explicit settings are kept; an empty config is safe
  • Reward: 50 XP for a complete fix

Briefing

Modelled on the exposed MongoDB databases of 2015. MongoDB releases of the time did not require authentication by default and, depending on how they were installed, listened on every network interface. In February 2015 researchers at Saarland University reported finding tens of thousands of MongoDB instances reachable from the internet with no access control, and later scans that year found similar numbers. MongoDB later made binding to localhost the default.

This reconstruction's config loader fills missing settings with the old defaults.

Fix load so a missing setting is the safe one and an exposed, unauthenticated server cannot start.

Bug report

BUG-MDB-1502 · Priority: Critical · Reported by: security

load(raw) returns { bindIp, port, auth }:

  • missing bindIp -> "127.0.0.1"; missing port -> 27017; missing auth -> true
  • explicitly given values are kept (raw may be undefined or {})
  • bindIp may be a comma-separated list (entries are trimmed). If ANY entry is not a loopback address (server.LOOPBACK: "127.0.0.1", "localhost", "::1") while auth is false, load throws — that server would be open to the network with no password
  • loopback-only with auth false is allowed (local development)

Observed: a config file with only a storage path started a server on 0.0.0.0:27017 that accepted unauthenticated clients from anywhere.

Logs

[mongod] waiting for connections on 0.0.0.0:27017
[mongod] access control is not enabled for the database
[mongod] connection accepted from 203.0.113.77:51882

The code as shipped

src/db/config.js (editable)

var DEFAULTS = { bindIp: "0.0.0.0", port: 27017, auth: false };

exports.load = function (raw) {
  raw = raw || {};
  return {
    bindIp: raw.bindIp !== undefined ? raw.bindIp : DEFAULTS.bindIp,
    port: raw.port !== undefined ? raw.port : DEFAULTS.port,
    auth: raw.auth !== undefined ? raw.auth : DEFAULTS.auth
  };
};

Read-only context: src/db/server.js.

Open the hunt to edit the files, run the visible tests and submit against the hidden ones. More JavaScript bug hunts.