HIGH dns rebindingfiber

Dns Rebinding in Fiber

How Dns Rebinding Manifests in Fiber

DNS rebinding attacks exploit the trust relationship between a web application and its backend services by manipulating DNS resolution to make the browser believe it's communicating with a trusted domain while actually connecting to a local or internal service.

In Fiber applications, this vulnerability often appears in API endpoints that accept URLs or hostnames from untrusted sources and then make HTTP requests to those destinations. The classic pattern involves an endpoint like:

app := fiber.New()

app.Post("/proxy", func(c *fiber.Ctx) error {
    url := c.FormValue("url")
    resp, err := http.Get(url)
    if err != nil {
        return c.Status(500).SendString(err.Error())
    }
    defer resp.Body.Close()
    return c.SendString(resp.Status)
})

This proxy endpoint is vulnerable because it blindly follows any URL provided by the client. An attacker can host a malicious page that sets a short TTL DNS record for their domain, then quickly changes it to point to internal services like 192.168.1.1 or localhost. When the victim's browser accesses the malicious page, it makes requests to what it believes is the attacker's domain, but the requests actually reach internal services.

Fiber's default middleware stack doesn't provide any protection against this. The vulnerability becomes particularly dangerous when combined with:

  • Database administration interfaces exposed on internal networks
  • Development servers running on non-standard ports
  • API endpoints that accept arbitrary URLs for processing
  • Webhook receivers that make outbound HTTP requests
  • File upload handlers that process remote files

A concrete Fiber-specific example might involve an endpoint that processes OpenAPI specifications:

app.Post("/upload-spec", func(c *fiber.Ctx) error {
    file, err := c.FormFile("spec")
    if err != nil {
        return c.Status(400).SendString("No file uploaded")
    }
    
    // Vulnerable: processes remote files without validation
    if strings.HasPrefix(file.Filename, "http") {
        resp, err := http.Get(file.Filename)
        if err != nil {
            return c.Status(500).SendString(err.Error())
        }
        defer resp.Body.Close()
        
        // Process the remote OpenAPI spec
        spec, err := ioutil.ReadAll(resp.Body)
        if err != nil {
            return c.Status(500).SendString("Failed to read spec")
        }
        
        return c.JSON(analyzeSpec(spec))
    }
    
    return c.Status(400).SendString("Invalid file type")
})

This endpoint would allow an attacker to submit a URL pointing to internal services, potentially exposing sensitive data or triggering actions on internal systems.

Fiber-Specific Detection

Detecting DNS rebinding vulnerabilities in Fiber applications requires both static code analysis and dynamic testing. For static analysis, look for patterns where Fiber endpoints accept URLs or hostnames and make outbound requests without proper validation.

Using middleBrick's API scanning capabilities, you can identify these vulnerabilities without modifying your application code. middleBrick's black-box scanning approach tests the unauthenticated attack surface by:

  • Analyzing endpoint parameters that accept URLs or hostnames
  • Testing for SSRF-like behavior that could be exploited via DNS rebinding
  • Checking for missing input validation on URL parameters
  • Scanning for endpoints that make outbound HTTP requests
  • Testing LLM/AI security endpoints that might be vulnerable to prompt injection via rebinding

The scanning process takes 5-15 seconds and provides a security risk score with specific findings. For Fiber applications, middleBrick would flag endpoints similar to the proxy example above and provide remediation guidance.

Manual detection in Fiber code involves searching for these patterns:

# Look for HTTP client usage with user-controlled URLs
grep -r "http\.Get\|http\.Post\|http\.Client" . | grep -E "(c\.FormValue|c\.Query|c\.Params)"

# Find file upload handlers that process URLs
grep -r "FormFile" . | grep -E "(http|https)"

# Check for webhook receivers
grep -r "webhook\|callback" . | grep -E "(http\.Get|http\.Post)"

During runtime testing, you can simulate basic DNS rebinding scenarios by:

app.Use(func(c *fiber.Ctx) error {
    // Basic URL validation - prevent DNS rebinding
    url := c.FormValue("url")
    if url != "" {
        u, err := url.Parse(url)
        if err != nil {
            return c.Status(400).SendString("Invalid URL")
        }
        
        // Block internal IP ranges
        if isInternalIP(u.Hostname()) {
            return c.Status(403).SendString("Internal URLs not allowed")
        }
        
        // Block private domains
        if isPrivateDomain(u.Hostname()) {
            return c.Status(403).SendString("Private domains not allowed")
        }
    }
    return c.Next()
})

func isInternalIP(host string) bool {
    ip := net.ParseIP(host)
    if ip == nil {
        return false
    }
    return ip.IsPrivate() || ip.IsLoopback() || ip.IsUnspecified()
}

func isPrivateDomain(host string) bool {
    privateSuffixes := []string{".local", ".internal", ".corp", ".lan"}
    for _, suffix := range privateSuffixes {
        if strings.HasSuffix(host, suffix) {
            return true
        }
    }
    return false
}

middleBrick's continuous monitoring in the Pro plan would automatically re-scan your APIs on a schedule, alerting you if new endpoints are added that might be vulnerable to these attacks.

Fiber-Specific Remediation

Remediating DNS rebinding vulnerabilities in Fiber applications requires a defense-in-depth approach. The most effective strategy combines input validation, allowlisting, and safe HTTP client configurations.

First, implement strict URL validation using Go's net/url package combined with allowlisting:

func validateURL(rawURL string) (string, error) {
    if rawURL == "" {
        return "", errors.New("URL cannot be empty")
    }
    
    u, err := url.Parse(rawURL)
    if err != nil {
        return "", fmt.Errorf("invalid URL format: %w", err)
    }
    
    // Reject non-HTTP schemes
    if u.Scheme != "http" && u.Scheme != "https" {
        return "", errors.New("only HTTP/HTTPS URLs are allowed")
    }
    
    // Block internal IP addresses
    host := u.Hostname()
    if isInternalIP(host) {
        return "", errors.New("internal IP addresses are not allowed")
    }
    
    // Allowlist specific domains
    allowedDomains := map[string]bool{
        "api.example.com": true,
        "cdn.example.net": true,
    }
    
    if !allowedDomains[host] && !isPublicDomain(host) {
        return "", errors.New("domain not in allowlist")
    }
    
    return u.String(), nil
}

func isInternalIP(host string) bool {
    ip := net.ParseIP(host)
    if ip == nil {
        return false
    }
    return ip.IsPrivate() || ip.IsLoopback() || ip.IsUnspecified()
}

func isPublicDomain(host string) bool {
    // Simple check - in production use a proper public suffix list
    publicSuffixes := []string{".com", ".net", ".org", ".io"}
    for _, suffix := range publicSuffixes {
        if strings.HasSuffix(host, suffix) {
            return true
        }
    }
    return false
}

Apply this validation in your Fiber endpoints:

app.Post("/safe-proxy", func(c *fiber.Ctx) error {
    rawURL := c.FormValue("url")
    validatedURL, err := validateURL(rawURL)
    if err != nil {
        return c.Status(400).SendString(err.Error())
    }
    
    // Use a safe HTTP client with timeouts
    client := &http.Client{
        Timeout: 10 * time.Second,
        CheckRedirect: func(req *http.Request, via []*http.Request) error {
            // Prevent redirect loops
            if len(via) >= 5 {
                return http.ErrUseLastResponse
            }
            return nil
        },
    }
    
    resp, err := client.Get(validatedURL)
    if err != nil {
        return c.Status(502).SendString("Failed to fetch URL")
    }
    defer resp.Body.Close()
    
    return c.SendString(resp.Status)
})

For webhook receivers and callback handlers, implement additional safeguards:

app.Post("/webhook", func(c *fiber.Ctx) error {
    type webhookPayload struct {
        CallbackURL string `json:"callback_url"`
        Data        string `json:"data"`
    }
    
    var payload webhookPayload
    if err := c.BodyParser(&payload); err != nil {
        return c.Status(400).SendString("Invalid payload")
    }
    
    // Validate callback URL
    callbackURL, err := validateURL(payload.CallbackURL)
    if err != nil {
        return c.Status(400).SendString("Invalid callback URL")
    }
    
    // Process data
    processed := processData(payload.Data)
    
    // Make callback with safe client
    client := &http.Client{
        Timeout: 5 * time.Second,
        Transport: &http.Transport{
            DisableKeepAlives: true,
            MaxIdleConns:      0,
        },
    }
    
    callbackPayload := map[string]string{"result": processed}
    resp, err := client.Post(callbackURL, "application/json", 
        strings.NewReader(jsonMarshal(callbackPayload)))
    if err != nil {
        return c.Status(502).SendString("Callback failed")
    }
    defer resp.Body.Close()
    
    return c.JSON(fiber.Map{"status": "processed"})
})

For OpenAPI/Swagger processing endpoints, implement strict file handling:

app.Post("/upload-spec", func(c *fiber.Ctx) error {
    file, err := c.FormFile("spec")
    if err != nil {
        return c.Status(400).SendString("No file uploaded")
    }
    
    // Only allow local file uploads, reject URLs
    if strings.HasPrefix(file.Filename, "http") {
        return c.Status(400).SendString("Remote files not allowed")
    }
    
    // Save to temporary location
    tempPath := filepath.Join(os.TempDir(), file.Filename)
    if err := c.SaveFile(file, tempPath); err != nil {
        return c.Status(500).SendString("Failed to save file")
    }
    defer os.Remove(tempPath)
    
    // Process the local file
    specData, err := ioutil.ReadFile(tempPath)
    if err != nil {
        return c.Status(500).SendString("Failed to read spec")
    }
    
    return c.JSON(analyzeSpec(specData))
})

middleBrick's Pro plan includes continuous monitoring that would automatically detect if any of these patterns are introduced in new code, providing alerts before vulnerabilities reach production.

Frequently Asked Questions

How does middleBrick detect DNS rebinding vulnerabilities in Fiber applications?
middleBrick performs black-box scanning of your API endpoints, testing for SSRF-like behavior that could be exploited via DNS rebinding. It analyzes parameters that accept URLs or hostnames, checks for missing input validation, and scans for endpoints that make outbound HTTP requests. The scanner tests the unauthenticated attack surface without requiring credentials or access to your source code, providing a security risk score with specific findings and remediation guidance.
Can middleBrick scan Fiber applications running on localhost or internal networks?
Yes, middleBrick can scan APIs accessible via network URLs, including localhost and internal network addresses. For local development, you can expose your Fiber application on a network interface (e.g., 0.0.0.0:3000) and provide middleBrick with the accessible URL. The scanner will test the endpoints from its cloud infrastructure, identifying vulnerabilities like DNS rebinding that might not be apparent during local testing.