HIGH ssrfecho go

Ssrf in Echo Go

How SSRF Manifests in Echo Go

Server-Side Request Forgery (SSRF) in Echo Go typically occurs when the framework processes user-controlled URLs that get fetched internally. In Echo Go applications, SSRF vulnerabilities often appear in middleware that processes webhook callbacks, external API integrations, or proxy endpoints. The most common pattern involves using Go's http.Get() or http.Client with unsanitized user input.

func handleWebhook(c echo.Context) error {
    url := c.QueryParam("callback_url")
    resp, err := http.Get(url) // SSRF vulnerability
    if err != nil {
        return err
    }
    defer resp.Body.Close()
    return c.JSON(http.StatusOK, echo.Map{"status": "processed"})
}

This code is vulnerable because an attacker can supply localhost, 127.0.0.1, or internal service URLs like http://metadata.google.internal/computeMetadata/v1/instance/. Echo Go's default HTTP client doesn't restrict outbound requests, making internal network reconnaissance trivial.

Another Echo Go-specific SSRF pattern appears in file upload handlers that process external URLs:

func uploadFromURL(c echo.Context) error {
    url := c.FormValue("file_url")
    resp, err := http.Get(url) // SSRF here
    if err != nil {
        return err
    }
    defer resp.Body.Close()
    
    // Process file...
    return c.JSON(http.StatusOK, echo.Map{"uploaded": true})
}

Echo Go's middleware ecosystem can also introduce SSRF risks. Custom middleware that fetches external resources based on request headers or query parameters creates attack surfaces. The framework's flexibility means SSRF can hide in unexpected places like custom validator implementations or business logic that fetches pricing data from external services.

Cloud-specific SSRF in Echo Go is particularly dangerous. Applications running on AWS, GCP, or Azure often have access to metadata services. An attacker might supply:

http://169.254.169.254/latest/meta-data/
http://metadata.google.internal/computeMetadata/v1/
http://169.254.169.254/latest/meta-data/iam/security-credentials/

These requests can expose cloud credentials, instance metadata, and service account tokens. Echo Go applications in containerized environments face additional risks from Docker daemon APIs (unix:///var/run/docker.sock) and Kubernetes service discovery.

Echo Go-Specific Detection

Detecting SSRF in Echo Go requires both static analysis and runtime scanning. Static analysis should focus on HTTP client usage patterns. Look for:

// Vulnerable patterns
go func() {
    url := getUserInput()
    http.Get(url) // UNSAFE
}

client := &http.Client{}
client.Get(unsafeURL) // UNSAFE

// Safe patterns
client := &http.Client{
    CheckRedirect: func(req *http.Request, via []*http.Request) error {
        return http.ErrUseLastResponse
    },
}

middleBrick's SSRF detection for Echo Go specifically identifies these patterns by scanning the runtime behavior of your API endpoints. It tests for SSRF by attempting to access restricted resources like:

http://127.0.0.1:80
http://localhost:22
http://169.254.169.254/latest/meta-data/
http://[::1]:80

The scanner analyzes Echo Go's routing structure to identify endpoints that accept URL parameters, then systematically tests each for SSRF vulnerabilities. It checks if the application properly validates hostnames, blocks private IP ranges, and restricts outbound requests.

For Echo Go applications, middleBrick provides specific findings like:

SSRF Vulnerability: /api/webhook?url=... (Critical)
- Allows outbound requests to internal networks
- No hostname validation or IP restriction
- Could access metadata services and internal APIs

Echo Go's middleware architecture means SSRF can be introduced through third-party middleware. middleBrick scans all registered middleware to identify potential SSRF vectors, including custom middleware that processes external URLs.

Runtime detection should include network monitoring for unexpected outbound requests. Echo Go applications should log all external requests with their originating endpoints. Tools like httplog middleware can track outbound connections:

func SSRFLoggingMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
    return func(c echo.Context) error {
        // Log outbound requests
        return next(c)
    }
}

Echo Go-Specific Remediation

Remediating SSRF in Echo Go requires a defense-in-depth approach. The most effective solution is a URL allowlist combined with strict validation. Here's a comprehensive Echo Go SSRF prevention middleware:

type SSRFMiddleware struct {
    allowedDomains map[string]bool
    client         *http.Client
}

func NewSSRFMiddleware(allowedDomains []string) *SSRFMiddleware {
    domains := make(map[string]bool)
    for _, domain := range allowedDomains {
        domains[domain] = true
    }
    return &SSRFMiddleware{
        allowedDomains: domains,
        client: &http.Client{
            Timeout: 10 * time.Second,
            CheckRedirect: func(req *http.Request, via []*http.Request) error {
                return http.ErrUseLastResponse
            },
        },
    }
}

func (m *SSRFMiddleware) ValidateURL(rawURL string) error {
    parsed, err := url.Parse(rawURL)
    if err != nil {
        return errors.New("invalid URL format")
    }
    
    // Block private IP ranges
    ip := net.ParseIP(parsed.Hostname())
    if ip != nil {
        if ip.IsLoopback() || ip.IsPrivate() || ip.IsLinkLocalUnicast() {
            return errors.New("private IP addresses not allowed")
        }
    }
    
    // Block metadata services
    if strings.Contains(parsed.Hostname(), "metadata") ||
       strings.Contains(parsed.Hostname(), "169.254") ||
       strings.Contains(parsed.Hostname(), "[::1]") {
        return errors.New("metadata services blocked")
    }
    
    // Check allowlist
    if !m.allowedDomains[parsed.Hostname()] {
        return errors.New("domain not in allowlist")
    }
    
    return nil
}

func (m *SSRFMiddleware) SecureGet(rawURL string) (*http.Response, error) {
    if err := m.ValidateURL(rawURL); err != nil {
        return nil, err
    }
    return m.client.Get(rawURL)
}

Integrate this middleware into your Echo Go application:

allowed := []string{"api.example.com", "webhook.example.com"}
middleware := NewSSRFMiddleware(allowed)

func handleWebhook(c echo.Context) error {
    url := c.QueryParam("callback_url")
    
    resp, err := middleware.SecureGet(url)
    if err != nil {
        return c.JSON(http.StatusBadRequest, echo.Map{"error": err.Error()})
    }
    defer resp.Body.Close()
    
    return c.JSON(http.StatusOK, echo.Map{"status": "processed"})
}

For Echo Go applications that must process arbitrary URLs, implement a proxy with strict controls:

func proxyRequest(c echo.Context) error {
    targetURL := c.QueryParam("url")
    
    // Validate using the middleware
    if err := middleware.ValidateURL(targetURL); err != nil {
        return c.JSON(http.StatusBadRequest, echo.Map{"error": err.Error()})
    }
    
    // Create request with timeout
    req, err := http.NewRequest("GET", targetURL, nil)
    if err != nil {
        return err
    }
    
    client := &http.Client{
        Timeout: 10 * time.Second,
        CheckRedirect: func(req *http.Request, via []*http.Request) error {
            return http.ErrUseLastResponse
        },
    }
    
    resp, err := client.Do(req)
    if err != nil {
        return err
    }
    defer resp.Body.Close()
    
    // Proxy the response
    c.Response().Header().Set("Content-Type", resp.Header.Get("Content-Type"))
    return c.Stream(resp.StatusCode, resp.Header.Get("Content-Type"), resp.Body)
}

Echo Go's context system can help track SSRF-related requests:

func SSRFContextMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
    return func(c echo.Context) error {
        c.Set("ssrf_allowed", false)
        
        // Check if this request should allow SSRF
        // This could be based on auth, endpoint, or other criteria
        
        return next(c)
    }
}

Related CWEs: ssrf

CWE IDNameSeverity
CWE-918Server-Side Request Forgery (SSRF) CRITICAL
CWE-441Unintended Proxy or Intermediary (Confused Deputy) HIGH

Frequently Asked Questions

How does SSRF in Echo Go differ from other Go frameworks?
Echo Go's minimalist design means SSRF vulnerabilities often appear in custom middleware rather than framework defaults. Unlike Gin or Fiber, Echo Go doesn't include built-in request validation middleware, so developers must implement SSRF protection themselves. The framework's context-based approach also means SSRF checks need to be explicitly added to each handler or as global middleware.
Can middleBrick detect SSRF in my Echo Go application without access to the source code?
Yes, middleBrick performs black-box scanning that tests your running Echo Go API endpoints. It identifies SSRF vulnerabilities by attempting to access restricted resources like localhost, metadata services, and internal networks. The scanner analyzes the runtime behavior of your API without requiring source code, credentials, or configuration changes.