HIGH dns cache poisoninghanamimutual tls

Dns Cache Poisoning in Hanami with Mutual Tls

Dns Cache Poisoning in Hanami with Mutual Tls — how this specific combination creates or exposes the vulnerability

DNS cache poisoning (also known as DNS spoofing) occurs when an attacker injects a malicious DNS response into a resolver’s cache, causing a domain to resolve to an attacker-controlled IP. In Hanami, this can affect applications that resolve service hostnames at runtime, for example when making outbound HTTP requests to microservices or external APIs. When mutual TLS (mTLS) is used, the client presents a certificate during the TLS handshake, but mTLS does not prevent a poisoned DNS record from redirecting traffic to a rogue server that also presents a valid certificate for the target domain.

Specifically, if Hanami resolves a hostname (e.g., payments.internal.example.com) via a system or library DNS resolver that is cacheable and not strictly validating DNS origin, an attacker on the network path can poison the cache with an IP that belongs to a malicious server possessing a certificate for payments.internal.example.com. Because mTLS requires the server to present a certificate trusted by the client, the client may complete the handshake with the rogue server, assuming identity assurance. The combination therefore exposes the application to man-in-the-middle (MitM) despite mTLS, because mTLS provides server authentication only if the resolved IP corresponds to the intended host.

Moreover, if Hanami applications embed hostnames in outbound requests without additional verification (for example, using Net::HTTP or a HTTP client that does not enforce strict hostname-to-certificate matching), a poisoned cache can direct traffic to an IP where TLS is offloaded or where the server does not enforce SNI-based hostname checks. This can lead to authentication bypass or data exposure when the client trusts the rogue server’s certificate. Runtime configuration such as DNS TTL settings and whether the application uses a custom DNS resolver (e.g., via resolv or an external service) further influences exposure.

Mutual Tls-Specific Remediation in Hanami — concrete code fixes

Remediation focuses on ensuring that DNS resolution and TLS verification are tightly coupled and that mTLS is correctly configured to reduce the window for successful poisoning. Below are concrete steps and Hanami-compatible code examples.

  • Pin hostnames to IPs via application-level configuration for critical internal services and avoid runtime DNS lookups for sensitive endpoints. When dynamic resolution is necessary, use DNSSEC-validating resolvers and enforce DNSSEC validation in the resolver configuration.
  • Enforce strict hostname verification in the TLS layer so that the server certificate’s subject alternative names (SAN) or common name (CN) must match the expected hostname, even when mTLS is used.
  • Use a trusted CA store that includes only the specific CAs that issue server certificates, and require client certificates that are similarly constrained.

Example Hanami configuration and client code with mTLS and hostname verification

Ruby’s Net::HTTP can be configured to verify both the server certificate and hostname. The following example shows a Hanami service object that performs mTLS with strict hostname checks.

require "net/https"
require "openssl"

class SecureApiClient
  def initialize(base_url, cert_path, key_path, ca_path)
    @base_url = base_url
    uri = URI(@base_url)
    @http = Net::HTTP.new(uri.host, uri.port)
    @http.use_ssl = true

    # Enforce TLS 1.2+ and strong ciphers
    @http.min_version = "TLSv1.2"
    @http.ciphers = ["ECDHE-RSA-AES256-GCM-SHA384", "ECDHE-ECDSA-AES256-GCM-SHA384"]

    # Client certificate for mTLS
    @http.cert = OpenSSL::X509::Certificate.new(File.read(cert_path))
    @http.key = OpenSSL::PKey::RSA.new(File.read(key_path))

    # Trusted CA for server verification
    @http.ca_file = ca_path
    @http.verify_mode = OpenSSL::SSL::VERIFY_PEER

    # Strict hostname verification (prevents poisoning by ensuring cert matches expected host)
    @http.hostname_verifier = proc do |cert, host|
      ssl_cert = OpenSSL::X509::Certificate.new(cert)
      extensions = ssl_cert.extensions.map(&:to_s)
      san = extensions.grep(/subjectAltName/).first
      if san
        names = san.split(":").last.split(",").map(&:strip).map(&:sub(/^DNS:/, ""))
        names.any? { |name| File.fnmatch?(name, host, File::FNM_DOTMATCH) }
      else
        # Fallback to CN if SAN is absent (not recommended)
        cn = ssl_cert.subject.to_s.match(/CN=([^,\s]+)/)&.[](1)
        cn == host
      end
    end
  rescue Errno::ENOENT => e
    raise "Certificate file missing: #{e.message}"
  end

  def get(path)
    request = Net::HTTP::Get.new(path)
    response = @http.request(request)
    # Inspect response to detect unexpected redirects or mismatched hosts
    if response.is_a?(Net::HTTPRedirection)
      raise "Unexpected redirect to #{response["location"]}"
    end
    response
  end
end

# Usage
client = SecureApiClient.new(
  "https://payments.internal.example.com/api/v1/charge",
  "/path/to/client.crt",
  "/path/to/client.key",
  "/path/to/ca-bundle.crt"
)
resp = client.get("/charge")
puts resp.code

In Hanami applications that use a custom HTTP client, wrap the client with the same verification logic and ensure that DNS resolution is performed using a validating resolver or that hostnames are pinned. For containerized deployments, configure the pod’s dnsPolicy and dnsConfig in Kubernetes to use DNSSEC-capable resolvers where possible and avoid exposing unnecessary wildcard DNS entries that could be poisoned.

Frequently Asked Questions

Does mutual TLS prevent DNS cache poisoning in Hanami?
No. Mutual TLS provides server authentication via client certificates, but it does not prevent a DNS cache poisoning attack. A poisoned DNS entry can redirect traffic to a rogue server that presents a valid certificate for the target hostname, so DNS integrity and strict hostname verification remain essential.
What additional steps should Hanami apps take to harden against DNS poisoning when using mTLS?
Pin hostnames to IPs where possible, use DNSSEC-validating resolvers, enforce strict hostname verification in TLS, avoid wildcard DNS, and monitor for unexpected redirects or certificate anomalies at runtime.