HIGH ssrf server sidegrape

Ssrf Server Side in Grape

How SSRF Manifests in Grape Applications

Server-Side Request Forgery (SSRF) in Grape applications occurs when user-controlled input is used to construct URLs for internal API calls or external requests. Grape's DSL for building REST-like APIs makes it particularly susceptible to SSRF when endpoints accept URLs as parameters for downstream service calls.

The most common Grape SSRF pattern involves accepting a URL parameter and using it to make HTTP requests within the API endpoint. For example:

class ExternalServiceAPI < Grape::API
  params do
    requires :url, type: String
  end
  
  get :fetch_content do
    response = HTTParty.get(params[:url])
    { content: response.body }
  end
end

This endpoint is vulnerable because an attacker can supply any URL, including internal network addresses, localhost, or cloud metadata endpoints. Common targets include:

  • Cloud metadata services (AWS EC2 metadata: http://169.254.169.254/latest/meta-data/)
  • Database admin interfaces (Redis: redis://localhost:6379, MongoDB: mongodb://localhost:27017)
  • Internal APIs and microservices
  • Container orchestration APIs
  • Cloud provider APIs (GCP metadata: http://metadata.google.internal)

Grape's flexible parameter handling can mask SSRF vulnerabilities. The DSL allows complex parameter types and validation, but URL validation is often insufficient. A seemingly safe endpoint like:

class ProtectedAPI < Grape::API
  params do
    requires :endpoint, type: String, regexp: %r{\Ahttps?://}

still allows SSRF because the regex only checks for http/https scheme but doesn't prevent internal network access or metadata endpoints.

Another Grape-specific SSRF pattern occurs with dynamic routing. When URL segments are used to construct downstream requests:

class DynamicRouteAPI < Grape::API
  get 'proxy/:service/:path' do
    base_url = case params[:service]
              when 'internal' then 'http://internal-service:8080/'
              when 'external' then 'https://api.example.com/'
              end
    
    target_url = base_url + params[:path]
    HTTParty.get(target_url)
  end
end

Here, params[:path] can contain '../' sequences or be crafted to escape the intended base URL, leading to SSRF against internal services.

Grape-Specific Detection Methods

Detecting SSRF in Grape applications requires both static analysis and runtime testing. For static analysis, look for these Grape-specific patterns:

  • URL parameters that are passed directly to HTTP clients (HTTParty, Faraday, Net::HTTP)
  • Dynamic route segments used in URL construction
  • Parameters validated only by scheme regex (http/https) without host restrictions
  • Open redirects that could be chained with SSRF

Runtime detection with middleBrick provides comprehensive SSRF testing for Grape APIs. The scanner automatically tests for SSRF by:

  1. Attempting requests to localhost and 127.0.0.1
  2. Probing cloud metadata endpoints (AWS, GCP, Azure)
  3. Testing internal network ranges (10.x, 172.16-31.x, 192.168.x)
  4. Checking for SSRF via common protocols (file://, gopher://, ftp://)
  5. Scanning for vulnerable parameter names (url, uri, endpoint, proxy, callback)

For Grape applications, middleBrick's scanning process includes:

npm install -g middlebrick
middlebrick scan https://your-grape-api.com --tests ssrf

The scanner provides specific findings for Grape APIs, including:

  • Parameter names and locations where SSRF was detected
  • Success/failure of SSRF attempts with specific payloads
  • Network access results (internal service reachable, metadata accessible)
  • Risk score impact and remediation guidance

middleBrick's LLM/AI security features also detect if your Grape API has unauthenticated AI endpoints that could be exploited for SSRF via prompt injection, a unique capability not found in other scanners.

Grape-Specific Remediation Techniques

Securing Grape APIs against SSRF requires multiple layers of defense. The most effective approach combines input validation, network controls, and safe request patterns.

Input validation is the first line of defense. Instead of simple scheme validation, implement comprehensive URL filtering:

class ExternalServiceAPI < Grape::API
  params do
    requires :url, type: String
  end
  
  get :fetch_content do
    parsed_url = URI.parse(params[:url])
    
    # Block internal networks and metadata services
    forbidden_hosts = [
      'localhost', '127.0.0.1', '0.0.0.0',
      '169.254.169.254', 'metadata.google.internal',
      '169.254.169.254', '169.254.169.254'
    ]
    
    if forbidden_hosts.include?(parsed_url.host) || 
       parsed_url.host =~ /^(10|172\.(1[6-9]|2[0-9]|31[0-9])|192\.168)\./
      error!('URL not allowed', 403)
    end
    
    response = HTTParty.get(params[:url])
    { content: response.body }
  end
end

For dynamic routing patterns, use path sanitization and validation:

class DynamicRouteAPI < Grape::API
  get 'proxy/:service/:path' do
    service_map = {
      'internal' => 'http://internal-service:8080/',
      'external' => 'https://api.example.com/'
    }
    
    unless service_map.key?(params[:service])
      error!('Invalid service', 400)
    end
    
    # Sanitize path to prevent directory traversal
    sanitized_path = params[:path].gsub(/\.\./, '')
    sanitized_path = sanitized_path.gsub(/[^a-zA-Z0-9\/\-_.]/, '')
    
    target_url = service_map[params[:service]] + sanitized_path
    response = HTTParty.get(target_url)
    { content: response.body }
  end
end

Network-layer controls provide defense in depth. Configure your application server to restrict outbound connections:

# In your Grape API initializer
class RestrictedHTTPClient
  def self.get(url)
    uri = URI.parse(url)
    
    # Only allow specific domains
    allowed_domains = %w[api.example.com trusted-service.com]
    unless allowed_domains.include?(uri.host)
      raise "URL not in allowed domains: #{url}"
    end
    
    # Additional network restrictions
    Net::HTTP.start(uri.host, uri.port, open_timeout: 5, read_timeout: 10) do |http|
      request = Net::HTTP::Get.new(uri)
      http.request(request)
    end
  end
end

For comprehensive protection, integrate middleBrick's continuous monitoring into your CI/CD pipeline:

# .github/workflows/security.yml
name: API Security Scan
on: [push, pull_request]

jobs:
  security-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Run middleBrick scan
        run: |
          npm install -g middlebrick
          middlebrick scan ${{ secrets.API_URL }} --fail-below B
        env:
          MIDDLEBRICK_TOKEN: ${{ secrets.MIDDLEBRICK_TOKEN }}

This ensures SSRF vulnerabilities are caught before deployment. The Pro plan's continuous monitoring can also scan your staging environment on a schedule, alerting you to any new SSRF risks introduced by code changes.

Frequently Asked Questions

How can I test my Grape API for SSRF vulnerabilities?
Use middleBrick's self-service scanner which tests for SSRF by attempting requests to localhost, cloud metadata endpoints, and internal network ranges. The scanner provides specific findings about which parameters are vulnerable and what network access was achieved, with actionable remediation guidance.
Does middleBrick detect SSRF in AI endpoints within my Grape API?
Yes, middleBrick uniquely includes LLM/AI security scanning that detects unauthenticated AI endpoints and tests for SSRF via prompt injection. This includes checking for system prompt leakage, active prompt injection attempts, and excessive agency patterns that could lead to SSRF in AI-powered Grape APIs.