HIGH ssrf server sidefeathersjs

Ssrf Server Side in Feathersjs

How SSRF Manifests in FeathersJS

Server-Side Request Forgery (SSRF) in FeathersJS occurs when an application accepts user-controlled URLs and makes internal requests without proper validation. In FeathersJS, this vulnerability often emerges through service hooks, external API integrations, or custom endpoints that process user input for HTTP requests.

A common pattern in FeathersJS applications involves using hooks to enrich data by fetching external resources. Consider this vulnerable pattern:

app.service('users').hooks({
  before: {
    get: [
      async context => {
        const profileUrl = context.params.query.profileUrl;
        const response = await fetch(profileUrl);
        const profileData = await response.json();
        context.result.profile = profileData;
      }
    ]
  }
});

This hook fetches a user profile from a URL provided in the query parameters. An attacker could supply http://localhost:3306 to access the database, http://169.254.169.254 to access AWS metadata, or file:///etc/passwd to read local files.

FeathersJS's flexible service architecture makes SSRF particularly dangerous. Services can be configured to proxy requests, and hooks can execute arbitrary code before service methods. The app.configure() method allows loading plugins that might introduce SSRF vulnerabilities if they accept user input for URLs.

Cloud metadata services are a prime SSRF target. AWS, GCP, and Azure expose sensitive instance metadata at predictable internal URLs. A FeathersJS application running on AWS might inadvertently expose:

app.service('metadata').hooks({
  before: {
    find: [
      async context => {
        const metadataUrl = 'http://169.254.169.254/latest/metaadata/';
        const response = await fetch(metadataUrl + context.params.query.path);
        context.result = await response.json();
      }
    ]
  }
});

An attacker could traverse the metadata service to extract IAM credentials, SSH keys, or instance configuration.

FeathersJS-Specific Detection

Detecting SSRF in FeathersJS requires examining both the application code and runtime behavior. middleBrick's black-box scanning approach is particularly effective for FeathersJS applications because it tests the actual running API without requiring source code access.

middleBrick scans for SSRF by sending crafted payloads to endpoints that might accept URLs. For FeathersJS applications, it tests common patterns including:

  • Query parameters named url, callback, proxy, or similar
  • Request bodies containing URL fields
  • Headers that might control request destinations
  • Configuration endpoints that might accept service URLs

The scanner attempts connections to internal network ranges, cloud metadata services, and common internal ports. For FeathersJS specifically, middleBrick recognizes the framework's service hook patterns and tests endpoints that follow typical Feathers naming conventions.

Beyond automated scanning, manual detection in FeathersJS involves:

const vulnerableHooks = [
  // Hooks that fetch from user-controlled URLs
  'before:get:fetchProfile',
  'before:create:validateExternalData',
  'after:find:enrichWithExternalResources'
];

Code review should flag any use of fetch(), axios, or HTTP clients where the URL comes from user input. The context.params object in FeathersJS hooks is particularly dangerous as it can contain arbitrary query parameters.

middleBrick's SSRF detection includes testing for blind SSRF vulnerabilities where the application might make requests without returning the content. It uses out-of-band techniques to detect when internal requests are made, even when responses aren't directly returned to the user.

FeathersJS-Specific Remediation

Remediating SSRF in FeathersJS requires a defense-in-depth approach. The most effective strategy combines input validation, allowlisting, and architectural controls.

Input validation should be the first line of defense. For URL inputs in FeathersJS hooks:

const validateUrl = (url) => {
  try {
    const parsed = new URL(url);
    
    // Block private IP ranges
    const privateRanges = [
      /^10\./,
      /^172\.(1[6-9]|2[0-9]|3[0-1])\./,
      /^192\.168\./,
      /^127\./,
      /^169\.254\./,
      /^0\.0\.0\.0/,
      /^255\.255\.255\.255/
    ];
    
    if (privateRanges.some(regex => regex.test(parsed.host))) {
      throw new Error('Private IP address not allowed');
    }
    
    // Allow only specific protocols
    if (!['http:', 'https:'].includes(parsed.protocol)) {
      throw new Error('Only HTTP/HTTPS allowed');
    }
    
    return true;
  } catch (error) {
    return false;
  }
};

Implement this validation in a reusable hook:

const validateExternalUrl = async context => {
  const urlParam = context.params.query.url || 
                   context.data?.url || 
                   context.params.url;
  
  if (urlParam && !validateUrl(urlParam)) {
    throw new errors.BadRequest('Invalid or blocked URL');
  }
};

// Apply to all services that might process URLs
app.service('users').hooks({
  before: {
    all: [validateExternalUrl]
  }
});

For FeathersJS applications that must access external resources, use a proxy service with strict controls:

const proxyService = {
  async get(url) {
    // Validate URL
    if (!validateUrl(url)) {
      throw new Error('Invalid URL');
    }
    
    // Set timeout to prevent slowloris attacks
    const controller = new AbortController();
    const timeout = setTimeout(() => controller.abort(), 5000);
    
    try {
      const response = await fetch(url, {
        signal: controller.signal,
        headers: {
          'User-Agent': 'middleBrick-Proxy/1.0'
        }
      });
      
      return await response.text();
    } finally {
      clearTimeout(timeout);
    }
  }
};

Architectural remediation involves redesigning the application to eliminate URL parameters entirely. Instead of accepting URLs from users, maintain an allowlist of approved external services:

const APPROVED_SERVICES = {
  'github-profile': 'https://api.github.com/users/',
  'twitter-profile': 'https://api.twitter.com/2/users/',
  'openai-api': 'https://api.openai.com/v1/'
};

middleBrick's continuous monitoring in the Pro tier can verify that SSRF mitigations remain effective as the codebase evolves. The scanner runs on a schedule you configure, alerting you if new SSRF vulnerabilities are introduced.

Frequently Asked Questions

How does middleBrick detect SSRF in FeathersJS applications?
middleBrick performs black-box scanning by sending crafted URL payloads to your FeathersJS API endpoints. It tests for SSRF by attempting connections to internal network ranges, cloud metadata services (like 169.254.169.254), and common internal ports. The scanner identifies endpoints that might accept URLs by analyzing parameter names and testing typical FeathersJS service patterns. It can detect both direct SSRF where responses are returned and blind SSRF where requests are made without returning content, using out-of-band detection techniques.
Can middleBrick scan my FeathersJS API if it's behind authentication?
middleBrick's standard scanning works on unauthenticated endpoints, but you can configure authentication for authenticated APIs. The free tier allows 3 scans per month with basic functionality. For continuous monitoring of authenticated FeathersJS APIs, the Pro plan ($499/mo) includes scheduled scanning with authentication support, GitHub Action integration for CI/CD pipelines, and alerts when SSRF vulnerabilities are detected. The scanner tests the actual running API, so it works regardless of whether you're using FeathersJS's built-in authentication or custom auth systems.