Dns Rebinding in Feathersjs (Javascript)
Dns Rebinding in Feathersjs with Javascript — how this specific combination creates or exposes the vulnerability
DNS Rebinding is a client-side network attack that manipulates DNS responses to make a victim’s browser believe a malicious domain resolves to an internal IP address. When a Feathers.js service is reachable from the network and lacks proper host-header validation or IP binding, this can expose internal endpoints to external attackers. Feathers applications are often built with JavaScript and may run on Node.js servers without careful network configuration, increasing the risk.
In a Feathers.js + JavaScript setup, the server may listen on all interfaces (0.0.0.0) and rely on framework defaults rather than explicit hostname or IP restrictions. If the application exposes REST or Socket.io endpoints without enforcing strict origin checks or access controls, a browser-based attacker can use a two-stage DNS sequence to bypass same-origin policies. For example, an attacker crafts a page that first resolves a domain to a public IP, then rebinds it to 127.0.0.1 or an internal service IP, tricking the victim’s browser into sending authenticated requests to the Feathers server as if it were a local resource.
Feathers services commonly use hooks and transports that do not inherently validate the request origin or enforce strict host headers. If the Feathers app is also used in an unauthenticated scan context (as supported by middleBrick’s black-box methodology), an exposed endpoint might be probed for IDOR or BOLA issues, which can compound risks when combined with DNS Rebinding to reach internal management interfaces or unlisted transports. Because Feathers apps often integrate with databases or microservices via direct connections, rebinding to internal services can expose sensitive operations or administrative routes.
middleBrick’s unauthenticated scan can detect indicators of such exposure by testing host-header handling and network reachability, but it does not exploit or remediate. The scanner checks for missing host-based access controls and unsafe endpoint exposure patterns that may facilitate rebinding attacks in JavaScript-based Feathers deployments.
Javascript-Specific Remediation in Feathersjs — concrete code fixes
Remediation in Feathers with JavaScript focuses on explicit network binding, strict host-header validation, and transport-level access controls. Below are concrete, working examples that reduce the feasibility of DNS Rebinding attacks.
1. Bind to localhost or a specific interface
Avoid binding to all interfaces unless necessary. Use a specific IP or localhost in production to prevent external network exposure.
// src/index.js
const { createApp } = require('@feathersjs/feathers');
const express = require('@feathersjs/express');
const app = express(createApp());
// Explicitly bind to 127.0.0.1 instead of 0.0.0.0
const HOST = '127.0.0.1';
const PORT = 3030;
app.listen(PORT, HOST, () => {
console.log(`Feathers server listening on http://${HOST}:${PORT}`);
});
2. Enforce host-header validation
Validate the Host header to ensure requests target the expected domain. This mitigates DNS rebinding by discending requests with unexpected host values.
// src/index.js
const { createApp } = require('@feathersjs/feathers');
const express = require('@feathersjs/express');
const app = express(createApp());
app.use((req, res, next) => {
const allowedHost = 'api.example.com';
if (req.headers.host !== allowedHost) {
return res.status(403).send('Host header mismatch');
}
next();
});
app.use('/api', require('./services'));
app.listen(3030, '0.0.0.0', () => {
console.log('Server running on port 3030');
});
3. Secure Socket.io transports
If using Socket.io transports, restrict origins and avoid wildcard CORS settings. Feathers uses transports that can be scoped to known origins.
// src/index.js
const { createApp } = require('@feathersjs/feathers');
const express = require('@feathersjs/express');
const app = express(createApp());
const socketio = require('@feathersjs/socketio');
const httpServer = app.listen(3030);
// Configure Socket.io with strict origins
socketio(app, {
origins: ['https://app.example.com:1'], // strict origin: protocol + host + optional port
allowRequest: (req, callback) => {
const allowedOrigin = 'https://app.example.com';
callback(null, req.headers.origin === allowedOrigin);
}
});
4. Use framework-level hooks to validate requests
Leverage Feathers hooks to check connection transport and enforce stricter policies for REST and sockets.
// src/hooks/validate-origin.js
module.exports = function validateOrigin(options = {}) {
return context => {
const allowedOrigin = 'https://app.example.com';
const requestOrigin = context.params.headers?.origin;
if (requestOrigin && requestOrigin !== allowedOrigin) {
throw new Error('Invalid origin');
}
return context;
};
};
// In src/services/index.js
const validateOrigin = require('./hooks/validate-origin');
app.use('messages', require('./messages'));
app.service('messages').hooks({
before: {
all: [validateOrigin()]
}
});
These JavaScript-specific adjustments reduce the attack surface for DNS Rebinding by limiting how services are reachable and how hosts are validated. When combined with periodic scans using tools such as middleBrick, teams can detect misconfigurations that might otherwise enable rebinding in unauthenticated scenarios.