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
endThis 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
endHere, 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:
- Attempting requests to localhost and 127.0.0.1
- Probing cloud metadata endpoints (AWS, GCP, Azure)
- Testing internal network ranges (10.x, 172.16-31.x, 192.168.x)
- Checking for SSRF via common protocols (file://, gopher://, ftp://)
- 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 ssrfThe 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
endFor 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
endNetwork-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
endFor 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.