https://bz.apache.org/bugzilla/show_bug.cgi?id=70029

            Bug ID: 70029
           Summary: mod_cache should canonicalize Host/URI hostname
                    consistently when constructing cache keys
           Product: Apache httpd-2
           Version: 2.4.66
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: mod_cache
          Assignee: [email protected]
          Reporter: [email protected]
  Target Milestone: ---

I found a cache-key consistency issue in Apache httpd mod_cache/mod_cache_disk
when used in a reverse-proxy configuration.

This was originally reported to [email protected]. Joe Orton reviewed it and
suggested filing it as a normal Bugzilla issue, noting that it is reasonable to
argue that the URI hostname should be canonicalised when constructing the cache
key.

In a configuration with mod_cache enabled on a proxied path, Apache appears to
fold/canonicalize some Host/authority variants for cache lookup, such as:

- example.com.
- EXAMPLE.COM
- example.com:80

to the canonical host example.com.

However, the backend can still receive the original raw Host/authority variant
through Host or X-Forwarded-Host, depending on ProxyPreserveHost and backend
behavior.

This means a backend response generated using the raw Host/X-Forwarded-Host
value can be stored under a cache key that is later reused for the canonical
host.

This is not HTTP/2-specific. I reproduced the same behavior using HTTP/1.1 Host
headers.

Minimal configuration:

CacheRoot /var/cache/apache2/h2cache
CacheDirLevels 2
CacheDirLength 2
CacheQuickHandler On
CacheHeader on
CacheLock On
CacheLockPath /tmp/mod_cache-lock

<VirtualHost 127.0.0.1:18080>
    ServerName localhost
    Protocols h2c http/1.1

    ProxyPreserveHost On
    CacheEnable disk "/proxy/"

    RewriteEngine On
    RewriteRule ^/proxy/(.*)$ http://127.0.0.1:9001/proxy/$1 [P,L]
</VirtualHost>

Backend behavior used for reproduction:

The backend generates a cacheable 302 redirect using the received Host header:

Location: http://<Host>/poisoned-by-<Host>/...
Cache-Control: public, max-age=600

Reproduction:

1. Clear mod_cache.

2. Seed cache using Host variant:

GET /proxy/redirect-test HTTP/1.1
Host: localhost.
Connection: close

Observed:

HTTP/1.1 302 Found
Location: http://localhost./poisoned-by-localhost./...
X-Cache: MISS from localhost

Backend received:

HOST=localhost.
XFH=localhost.

3. Request the same URI using canonical Host:

GET /proxy/redirect-test HTTP/1.1
Host: localhost
Connection: close

Observed:

HTTP/1.1 302 Found
Location: http://localhost./poisoned-by-localhost./...
X-Cache: HIT from localhost

The canonical Host request received the cached response generated for Host
localhost.

Observed result:

A response generated by the backend using Host localhost. is reused for Host
localhost.

Expected result:

Either:

- mod_cache should not fold Host variants that are forwarded raw to the
backend, or
- the cache key should reflect the raw Host/authority value that the backend
sees, or
- this behavior should be clearly documented as requiring Vary: Host for any
Host-dependent backend response.

Additional controls:

- The behavior is not HTTP/2-specific. The same issue was reproduced with
HTTP/1.1 Host headers.
- With Vary: Host returned by the backend, mod_cache correctly separates
localhost. and localhost:
  - localhost. -> MISS
  - localhost -> MISS
  - localhost again -> HIT for localhost
- With ProxyPreserveHost Off, the backend may still receive the raw authority
through X-Forwarded-Host. If the backend uses X-Forwarded-Host to generate
public URLs, the same issue can occur.

Practical consequence:

In reverse-proxy deployments where backend responses are cacheable and depend
on Host or X-Forwarded-Host, this may cause cached response confusion across
Host variants, for example cached redirects or absolute links generated using a
trailing-dot, uppercase, or default-port Host variant.

I understand this may be configuration-dependent, but it seems the cache-key
construction and backend-visible authority normalization are inconsistent.

Environment:

Apache/2.4.66 (Debian)

Relevant modules:

- mod_cache
- mod_cache_disk
- mod_proxy
- mod_proxy_http
- mod_rewrite
- mod_headers
- mod_http2

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to