Dns Rebinding in Fiber with Hmac Signatures
Dns Rebinding in Fiber with Hmac Signatures — how this specific combination creates or exposes the vulnerability
DNS Rebinding is an attack that manipulates DNS responses to make a victim’s browser believe a remote host is accessible at an attacker-controlled IP address. When an application uses HMAC signatures for request authentication but does not adequately guard the evaluation context, this technique can bypass origin checks and lead to unauthorized internal interaction. In Fiber, a Go HTTP framework, this risk arises when endpoints rely solely on HMAC signatures without validating the request origin or binding the signature evaluation to a strict network context.
Consider a protected endpoint that accepts an HMAC-signed payload and verifies it using a shared secret. If the application uses a permissive CORS policy or serves responses with broad origins, an attacker can craft a page that triggers cross-origin requests to that endpoint. Through DNS Rebinding, the attacker can alternate DNS records so that a hostname initially resolves to a benign IP and later to a private IP such as 127.0.0.1. Because the HMAC verification in Fiber may not enforce strict host or referer checks, the signed request appears valid, allowing the attacker to execute actions on the server’s local network or management interfaces.
For example, suppose a Fiber route validates an HMAC header but does not confirm the request’s source IP or enforce strict same-origin policies. An attacker can use an HTML page with JavaScript to send requests that the server interprets as legitimate due to the valid HMAC. This is especially dangerous when the endpoint performs sensitive operations like configuration changes or exposes an unauthenticated admin interface. The combination of a weak origin policy and HMAC verification that does not account for rebinding vectors means the signature’s integrity is insufficient to prevent unauthorized access.
In a real scenario, an attacker might target a Fiber-based service that exposes an internal metrics or health endpoint protected only by HMAC. By rebinding the domain to localhost, the attacker can invoke these endpoints from a malicious site, leveraging the trusted HMAC signature to bypass network-level restrictions. This demonstrates why HMAC-based authentication in Fiber must be augmented with host validation, strict referer checks, and anti-rebinding protections to ensure that signed requests are tied to a specific, expected network origin.
Hmac Signatures-Specific Remediation in Fiber — concrete code fixes
To mitigate DNS Rebinding when using HMAC signatures in Fiber, you must bind signature verification to the request’s network origin and enforce strict host and referer validation. Below are concrete, working examples that demonstrate how to implement HMAC verification in Fiber while incorporating these protections.
First, ensure your HMAC verification checks not only the signature but also the request’s host and origin. Here is a secure Fiber handler that validates the HMAC and enforces host and origin constraints:
// secure_handler.go
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"net/http"
"strings"
"github.com/gofiber/fiber/v2"
)
func verifyHMAC(next fiber.Handler) fiber.Handler {
return func(c *fiber.Ctx) error {
// Expected host and origin — adjust to your service’s canonical values
const expectedHost = "api.example.com"
const expectedOrigin = "https://api.example.com"
// Validate Host header to prevent DNS rebinding via mismatched host
if c.Host() != expectedHost {
return c.Status(http.StatusForbidden).SendString("invalid host")
}
// Validate Origin header to ensure request comes from expected source
origin := c.Get("Origin")
if origin != expectedOrigin {
return c.Status(http.StatusForbidden).SendString("invalid origin")
}
// Extract signature from header
signature := c.Get("X-Hmac-Signature")
if signature == "" {
return c.Status(http.StatusUnauthorized).SendString("missing signature")
}
// Read body for HMAC computation
body := c.Body()
secret := []byte("your-256-bit-secret")
mac := hmac.New(sha256.New, secret)
mac.Write(body)
expectedMAC := hex.EncodeToString(mac.Sum(nil))
// Use constant-time comparison to avoid timing attacks
if !hmac.Equal([]byte(signature), []byte(expectedMAC)) {
return c.Status(http.StatusForbidden).SendString("invalid signature")
}
return next(c)
}
}
func main() {
app := fiber.New()
app.Post("/secure-endpoint", verifyHMAC(func(c *fiber.Ctx) error {
return c.SendString("Request processed securely")
}))
app.Listen(":3000")
}
This code validates the Host and Origin headers before verifying the HMAC, reducing the risk that a DNS Rebinding attack can bypass checks by altering the perceived origin. In production, you should derive the expected host and origin from configuration and ensure they match your service’s public endpoints.
For broader protection across your Fiber application, you can integrate this verification as middleware. The following example shows how to apply the HMAC check globally while allowing exceptions for public routes:
// middleware_setup.go
package main
import (
"net/http"
"github.com/gofiber/fiber/v2"
)
func main() {
app := fiber.New()
// Apply HMAC verification to routes that require it
app.Use("/secure/*", verifyHMAC)
// Public route that does not require HMAC
app.Get("/public", func(c *fiber.Ctx) error {
return c.SendString("Public endpoint")
})
app.Listen(":3000")
}
By combining HMAC validation with explicit host and origin checks, you reduce the attack surface for DNS Rebinding. This approach ensures that even if an attacker can manipulate DNS resolution, the request will be rejected unless it originates from the expected network context.