Skip to content

Commit 11e07bb

Browse files
simonpasquierslashpai
authored andcommitted
fix: disable HTTP2 connections by default
This change mitigates CVE-2023-44487 by disabling HTTP2 by default and forcing HTTP/1.1 until the Go standard library and golang.org/x/net are fully fixed. Right now, it is possible for authenticated and unauthenticated users to hold open HTTP2 connections and consume huge amounts of memory. It is possible to revert back the change by using the `--web.enable-http2` argument. Before this change: ``` curl -kv https://localhost:8443/metrics * Trying 127.0.0.1:8443... * Connected to localhost (127.0.0.1) port 8443 (#0) * ALPN: offers h2,http/1.1 [...] * ALPN: server accepted h2 [...] * using HTTP/2 * h2h3 [:method: GET] * h2h3 [:path: /metrics] * h2h3 [:scheme: https] * h2h3 [:authority: localhost:8443] * h2h3 [user-agent: curl/8.0.1] * h2h3 [accept: */*] * Using Stream ID: 1 (easy handle 0x5594d4614b10) [...] > GET /metrics HTTP/2 [...] ``` After this change: ``` curl -kv https://localhost:8443/metrics * Trying 127.0.0.1:8443... * Connected to localhost (127.0.0.1) port 8443 (#0) * ALPN: offers h2,http/1.1 [...] * ALPN: server accepted http/1.1 [...] * using HTTP/1.1 > GET /metrics HTTP/1.1 > Host: localhost:8443 > User-Agent: curl/8.0.1 > Accept: */* [...] < HTTP/1.1 200 OK [...] ``` See also: * kubernetes/kubernetes#121120 * kubernetes/kubernetes#121197 * golang/go#63417 (comment) Signed-off-by: Simon Pasquier <[email protected]> (cherry picked from commit a62e814)
1 parent 3de5e6d commit 11e07bb

File tree

3 files changed

+42
-12
lines changed

3 files changed

+42
-12
lines changed

Documentation/operator.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ Usage of ./operator:
8787
Cert file to be used for operator web server endpoints. (default "/etc/tls/private/tls.crt")
8888
-web.client-ca-file string
8989
Client CA certificate file to be used for operator web server endpoints. (default "/etc/tls/private/tls-ca.crt")
90+
-web.enable-http2
91+
Enable HTTP2 connections.
9092
-web.enable-tls
9193
Activate prometheus operator web server TLS. This is useful for example when using the rule validation webhook.
9294
-web.key-file string

cmd/admission-webhook/main.go

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,22 @@ var (
5353
cfg = config{}
5454
flagset = flag.CommandLine
5555

56+
enableHTTP2 bool
5657
serverTLS bool
5758
rawTLSCipherSuites string
5859
)
5960

6061
func main() {
6162
flagset.StringVar(&cfg.ListenAddress, "web.listen-address", ":8443", "Address on which the admission webhook service listens")
63+
// Mitigate CVE-2023-44487 by disabling HTTP2 by default until the Go
64+
// standard library and golang.org/x/net are fully fixed.
65+
// Right now, it is possible for authenticated and unauthenticated users to
66+
// hold open HTTP2 connections and consume huge amounts of memory.
67+
// See:
68+
// * https://github.com/kubernetes/kubernetes/pull/121120
69+
// * https://github.com/kubernetes/kubernetes/issues/121197
70+
// * https://github.com/golang/go/issues/63417#issuecomment-1758858612
71+
flagset.BoolVar(&enableHTTP2, "web.enable-http2", false, "Enable HTTP2 connections.")
6272
flagset.BoolVar(&serverTLS, "web.enable-tls", true, "Enable TLS web server")
6373

6474
flagset.StringVar(&cfg.ServerTLSConfig.CertFile, "web.cert-file", defaultCrtFile, "Certificate file to be used for the web server.")
@@ -127,7 +137,7 @@ func (s *srv) run(listener net.Listener) error {
127137
log := log.With(s.logger, "address", listener.Addr().String())
128138

129139
if s.s.TLSConfig != nil {
130-
level.Info(log).Log("msg", "Starting TLS enabled server")
140+
level.Info(log).Log("msg", "Starting TLS enabled server", "http2", enableHTTP2)
131141
if err := s.s.ServeTLS(listener, "", ""); err != http.ErrServerClosed {
132142
return err
133143
}
@@ -163,18 +173,23 @@ func newSrv(logger log.Logger, tlsConf *tls.Config) *srv {
163173
w.WriteHeader(http.StatusOK)
164174
})
165175

176+
httpServer := http.Server{
177+
Handler: mux,
178+
TLSConfig: tlsConf,
179+
ReadHeaderTimeout: 30 * time.Second,
180+
ReadTimeout: 30 * time.Second,
181+
// use flags on standard logger to align with base logger and get consistent parsed fields form adapter:
182+
// use shortfile flag to get proper 'caller' field (avoid being wrongly parsed/extracted from message)
183+
// and no datetime related flag to keep 'ts' field from base logger (with controlled format)
184+
ErrorLog: stdlog.New(log.NewStdlibAdapter(logger), "", stdlog.Lshortfile),
185+
}
186+
if !enableHTTP2 {
187+
httpServer.TLSNextProto = make(map[string]func(*http.Server, *tls.Conn, http.Handler))
188+
}
189+
166190
return &srv{
167191
logger: logger,
168-
s: &http.Server{
169-
Handler: mux,
170-
TLSConfig: tlsConf,
171-
ReadHeaderTimeout: 30 * time.Second,
172-
ReadTimeout: 30 * time.Second,
173-
// use flags on standard logger to align with base logger and get consistent parsed fields form adapter:
174-
// use shortfile flag to get proper 'caller' field (avoid being wrongly parsed/extracted from message)
175-
// and no datetime related flag to keep 'ts' field from base logger (with controlled format)
176-
ErrorLog: stdlog.New(log.NewStdlibAdapter(logger), "", stdlog.Lshortfile),
177-
},
192+
s: &httpServer,
178193
}
179194
}
180195

cmd/operator/main.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ func serve(srv *http.Server, listener net.Listener, logger log.Logger) func() er
126126

127127
func serveTLS(srv *http.Server, listener net.Listener, logger log.Logger) func() error {
128128
return func() error {
129-
level.Info(logger).Log("msg", "Starting secure server on "+listener.Addr().String())
129+
level.Info(logger).Log("msg", "Starting secure server on "+listener.Addr().String(), "http2", enableHTTP2)
130130
if err := srv.ServeTLS(listener, "", ""); err != http.ErrServerClosed {
131131
return err
132132
}
@@ -138,6 +138,7 @@ var (
138138
cfg = operator.Config{}
139139

140140
rawTLSCipherSuites string
141+
enableHTTP2 bool
141142
serverTLS bool
142143

143144
flagset = flag.CommandLine
@@ -146,6 +147,15 @@ var (
146147
func init() {
147148
// With migration to klog-gokit, calling klogv2.InitFlags(flagset) is not applicable.
148149
flagset.StringVar(&cfg.ListenAddress, "web.listen-address", ":8080", "Address on which to expose metrics and web interface.")
150+
// Mitigate CVE-2023-44487 by disabling HTTP2 by default until the Go
151+
// standard library and golang.org/x/net are fully fixed.
152+
// Right now, it is possible for authenticated and unauthenticated users to
153+
// hold open HTTP2 connections and consume huge amounts of memory.
154+
// See:
155+
// * https://github.com/kubernetes/kubernetes/pull/121120
156+
// * https://github.com/kubernetes/kubernetes/issues/121197
157+
// * https://github.com/golang/go/issues/63417#issuecomment-1758858612
158+
flagset.BoolVar(&enableHTTP2, "web.enable-http2", false, "Enable HTTP2 connections.")
149159
flagset.BoolVar(&serverTLS, "web.enable-tls", false, "Activate prometheus operator web server TLS. "+
150160
" This is useful for example when using the rule validation webhook.")
151161
flagset.StringVar(&cfg.ServerTLSConfig.CertFile, "web.cert-file", defaultOperatorTLSDir+"/tls.crt", "Cert file to be used for operator web server endpoints.")
@@ -467,6 +477,9 @@ func Main() int {
467477
// and no datetime related flag to keep 'ts' field from base logger (with controlled format)
468478
ErrorLog: stdlog.New(log.NewStdlibAdapter(logger), "", stdlog.Lshortfile),
469479
}
480+
if !enableHTTP2 {
481+
srv.TLSNextProto = make(map[string]func(*http.Server, *tls.Conn, http.Handler))
482+
}
470483
if srv.TLSConfig == nil {
471484
wg.Go(serve(srv, l, logger))
472485
} else {

0 commit comments

Comments
 (0)