VYPR
Unrated severityNVD Advisory· Published Jan 9, 2020· Updated Aug 5, 2024

CVE-2019-20372

CVE-2019-20372

Description

NGINX before 1.17.7, with certain error_page configurations, allows HTTP request smuggling, as demonstrated by the ability of an attacker to read unauthorized web pages in environments where NGINX is being fronted by a load balancer.

Affected products

8

Patches

3
e5595b37e3e7

nginx-1.17.7-RELEASE

https://github.com/nginx/nginxMaxim DouninDec 24, 2019via osv
1 file changed · +84 0
  • docs/xml/nginx/changes.xml+84 0 modified
    @@ -5,6 +5,90 @@
     <change_log title="nginx">
     
     
    +<changes ver="1.17.7" date="2019-12-24">
    +
    +<change type="bugfix">
    +<para lang="ru">
    +на старте или во время переконфигурации мог произойти segmentation fault,
    +если в конфигурации использовалась
    +директива rewrite с пустой строкой замены.
    +</para>
    +<para lang="en">
    +a segmentation fault might occur on start or during reconfiguration
    +if the "rewrite" directive with an empty replacement string
    +was used in the configuration.
    +</para>
    +</change>
    +
    +<change type="bugfix">
    +<para lang="ru">
    +в рабочем процессе мог произойти segmentation fault,
    +если директива break использовалась совместно с директивой alias
    +или директивой proxy_pass с URI.
    +</para>
    +<para lang="en">
    +a segmentation fault might occur in a worker process 
    +if the "break" directive was used with the "alias" directive
    +or with the "proxy_pass" directive with a URI.
    +</para>
    +</change>
    +
    +<change type="bugfix">
    +<para lang="ru">
    +строка Location заголовка ответа могла содержать мусор,
    +если URI запроса был изменён на URI, содержащий нулевой символ.
    +</para>
    +<para lang="en">
    +the "Location" response header line might contain garbage
    +if the request URI was rewritten to the one containing a null character.
    +</para>
    +</change>
    +
    +<change type="bugfix">
    +<para lang="ru">
    +при возврате перенаправлений с помощью директивы error_page
    +запросы с телом обрабатывались некорректно;
    +ошибка появилась в 0.7.12.
    +</para>
    +<para lang="en">
    +requests with bodies were handled incorrectly
    +when returning redirections with the "error_page" directive;
    +the bug had appeared in 0.7.12.
    +</para>
    +</change>
    +
    +<change type="bugfix">
    +<para lang="ru">
    +утечки сокетов при использовании HTTP/2.
    +</para>
    +<para lang="en">
    +socket leak when using HTTP/2.
    +</para>
    +</change>
    +
    +<change type="bugfix">
    +<para lang="ru">
    +при обработке pipelined-запросов по SSL-соединению мог произойти таймаут;
    +ошибка появилась в 1.17.5.
    +</para>
    +<para lang="en">
    +a timeout might occur while handling pipelined requests in an SSL connection;
    +the bug had appeared in 1.17.5.
    +</para>
    +</change>
    +
    +<change type="bugfix">
    +<para lang="ru">
    +в модуле ngx_http_dav_module.
    +</para>
    +<para lang="en">
    +in the ngx_http_dav_module.
    +</para>
    +</change>
    +
    +</changes>
    +
    +
     <changes ver="1.17.6" date="2019-11-19">
     
     <change type="feature">
    
c1be55f97211

Discard request body when redirecting to a URL via error_page.

https://github.com/nginx/nginxRuslan ErmilovDec 23, 2019via osv
1 file changed · +6 0
  • src/http/ngx_http_special_response.c+6 0 modified
    @@ -623,6 +623,12 @@ ngx_http_send_error_page(ngx_http_request_t *r, ngx_http_err_page_t *err_page)
             return ngx_http_named_location(r, &uri);
         }
     
    +    r->expect_tested = 1;
    +
    +    if (ngx_http_discard_request_body(r) != NGX_OK) {
    +        r->keepalive = 0;
    +    }
    +
         location = ngx_list_push(&r->headers_out.headers);
     
         if (location == NULL) {
    
a0523c3c8a81

Use a named location for authSignURL (#4859)

https://github.com/kubernetes/ingress-nginxManuel Alejandro de Brito FontesDec 25, 2019via osv
6 files changed · +126 22
  • internal/ingress/controller/template/template.go+15 11 modified
    @@ -18,7 +18,9 @@ package template
     
     import (
     	"bytes"
    +	"crypto/sha1"
     	"encoding/base64"
    +	"encoding/hex"
     	"encoding/json"
     	"fmt"
     	"io/ioutil"
    @@ -164,6 +166,7 @@ var (
     		"isValidByteSize":                    isValidByteSize,
     		"buildForwardedFor":                  buildForwardedFor,
     		"buildAuthSignURL":                   buildAuthSignURL,
    +		"buildAuthSignURLLocation":           buildAuthSignURLLocation,
     		"buildOpentracing":                   buildOpentracing,
     		"proxySetHeader":                     proxySetHeader,
     		"buildInfluxDB":                      buildInfluxDB,
    @@ -883,24 +886,25 @@ func buildForwardedFor(input interface{}) string {
     	return fmt.Sprintf("$http_%v", ffh)
     }
     
    -func buildAuthSignURL(input interface{}) string {
    -	s, ok := input.(string)
    -	if !ok {
    -		klog.Errorf("expected an 'string' type but %T was returned", input)
    -		return ""
    -	}
    -
    -	u, _ := url.Parse(s)
    +func buildAuthSignURL(authSignURL string) string {
    +	u, _ := url.Parse(authSignURL)
     	q := u.Query()
     	if len(q) == 0 {
    -		return fmt.Sprintf("%v?rd=$pass_access_scheme://$http_host$escaped_request_uri", s)
    +		return fmt.Sprintf("%v?rd=$pass_access_scheme://$http_host$escaped_request_uri", authSignURL)
     	}
     
     	if q.Get("rd") != "" {
    -		return s
    +		return authSignURL
     	}
     
    -	return fmt.Sprintf("%v&rd=$pass_access_scheme://$http_host$escaped_request_uri", s)
    +	return fmt.Sprintf("%v&rd=$pass_access_scheme://$http_host$escaped_request_uri", authSignURL)
    +}
    +
    +func buildAuthSignURLLocation(location, authSignURL string) string {
    +	hasher := sha1.New()
    +	hasher.Write([]byte(location))
    +	hasher.Write([]byte(authSignURL))
    +	return "@" + hex.EncodeToString(hasher.Sum(nil))
     }
     
     var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
    
  • internal/ingress/controller/template/template_test.go+0 8 modified
    @@ -763,14 +763,6 @@ func TestFilterRateLimits(t *testing.T) {
     }
     
     func TestBuildAuthSignURL(t *testing.T) {
    -	invalidType := &ingress.Ingress{}
    -	expected := ""
    -	actual := buildAuthSignURL(invalidType)
    -
    -	if expected != actual {
    -		t.Errorf("Expected '%v' but returned '%v'", expected, actual)
    -	}
    -
     	cases := map[string]struct {
     		Input, Output string
     	}{
    
  • Makefile+2 2 modified
    @@ -16,7 +16,7 @@
     all: all-container
     
     # Use the 0.0 tag for testing, it shouldn't clobber any release builds
    -TAG ?= 0.26.1
    +TAG ?= 0.26.2
     REGISTRY ?= quay.io/kubernetes-ingress-controller
     DOCKER ?= docker
     SED_I ?= sed -i
    @@ -77,7 +77,7 @@ export E2E_CHECK_LEAKS
     export SLOW_E2E_THRESHOLD
     
     # Set default base image dynamically for each arch
    -BASEIMAGE?=quay.io/kubernetes-ingress-controller/nginx-$(ARCH):870be3bcd88c267f14fd82da82303472f383cd14
    +BASEIMAGE?=quay.io/kubernetes-ingress-controller/nginx-$(ARCH):daf8634acf839708722cffc67a62e9316a2771c6
     
     ifeq ($(ARCH),arm)
     	QEMUARCH=arm
    
  • rootfs/etc/nginx/template/nginx.tmpl+9 1 modified
    @@ -952,6 +952,14 @@ stream {
             {{ end }}
     
     
    +        {{ if $externalAuth.SigninURL }}
    +        location {{ buildAuthSignURLLocation $location.Path $externalAuth.SigninURL }} {
    +            internal;
    +
    +            return 302 {{ buildAuthSignURL $externalAuth.SigninURL }};
    +        }
    +        {{ end }}
    +
             location {{ $path }} {
                 {{ $ing := (getIngressInformation $location.Ingress $server.Hostname $location.Path) }}
                 set $namespace      {{ $ing.Namespace | quote}};
    @@ -1071,7 +1079,7 @@ stream {
     
                 {{ if $externalAuth.SigninURL }}
                 set_escape_uri $escaped_request_uri $request_uri;
    -            error_page 401 = {{ buildAuthSignURL $externalAuth.SigninURL }};
    +            error_page 401 = {{ buildAuthSignURLLocation $location.Path $externalAuth.SigninURL }};
                 {{ end }}
     
                 {{ if $location.BasicDigestAuth.Secured }}
    
  • test/e2e/e2e.go+1 0 modified
    @@ -38,6 +38,7 @@ import (
     	_ "k8s.io/ingress-nginx/test/e2e/leaks"
     	_ "k8s.io/ingress-nginx/test/e2e/loadbalance"
     	_ "k8s.io/ingress-nginx/test/e2e/lua"
    +	_ "k8s.io/ingress-nginx/test/e2e/security"
     	_ "k8s.io/ingress-nginx/test/e2e/servicebackend"
     	_ "k8s.io/ingress-nginx/test/e2e/settings"
     	_ "k8s.io/ingress-nginx/test/e2e/ssl"
    
  • test/e2e/security/request_smuggling.go+99 0 added
    @@ -0,0 +1,99 @@
    +/*
    +Copyright 2019 The Kubernetes Authors.
    +
    +Licensed under the Apache License, Version 2.0 (the "License");
    +you may not use this file except in compliance with the License.
    +You may obtain a copy of the License at
    +
    +    http://www.apache.org/licenses/LICENSE-2.0
    +
    +Unless required by applicable law or agreed to in writing, software
    +distributed under the License is distributed on an "AS IS" BASIS,
    +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +See the License for the specific language governing permissions and
    +limitations under the License.
    +*/
    +
    +package security
    +
    +import (
    +	"bufio"
    +	"fmt"
    +	"net"
    +	"strings"
    +	"time"
    +
    +	. "github.com/onsi/ginkgo"
    +	. "github.com/onsi/gomega"
    +
    +	"k8s.io/ingress-nginx/test/e2e/framework"
    +)
    +
    +var _ = framework.IngressNginxDescribe("Request smuggling", func() {
    +	f := framework.NewDefaultFramework("request-smuggling")
    +
    +	BeforeEach(func() {
    +		f.NewEchoDeployment()
    +	})
    +
    +	AfterEach(func() {
    +	})
    +
    +	It("should not return body content from error_page", func() {
    +		host := "foo.bar.com"
    +
    +		snippet := `
    +server {
    +	listen 80;
    +	server_name notlocalhost;
    +	location /_hidden/index.html {
    +	return 200 'This should be hidden!';
    +	}
    +}`
    +
    +		f.UpdateNginxConfigMapData("http-snippet", snippet)
    +
    +		ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, map[string]string{
    +			"nginx.ingress.kubernetes.io/auth-signin": "https://httpbin.org/uuid",
    +			"nginx.ingress.kubernetes.io/auth-url":    "https://httpbin.org/basic-auth/user/passwd",
    +		})
    +		f.EnsureIngress(ing)
    +
    +		f.WaitForNginxServer(host,
    +			func(server string) bool {
    +				return strings.Contains(server, fmt.Sprintf("server_name %v", host))
    +			})
    +
    +		out, err := smugglingRequest(host, f.GetNginxIP(), 80)
    +		Expect(err).NotTo(HaveOccurred(), "obtaining response of request smuggling check")
    +		Expect(out).ShouldNot(ContainSubstring("This should be hidden!"))
    +	})
    +})
    +
    +func smugglingRequest(host, addr string, port int) (string, error) {
    +	conn, err := net.Dial("tcp", fmt.Sprintf("%v:%v", addr, port))
    +	if err != nil {
    +		return "", err
    +	}
    +
    +	defer conn.Close()
    +
    +	conn.SetDeadline(time.Now().Add(time.Second * 10))
    +
    +	_, err = fmt.Fprintf(conn, "GET /echo HTTP/1.1\r\nHost: %v\r\nContent-Length: 56\r\n\r\nGET /_hidden/index.html HTTP/1.1\r\nHost: notlocalhost\r\n\r\n", host)
    +	if err != nil {
    +		return "", err
    +	}
    +
    +	// wait for /_hidden/index.html response
    +	time.Sleep(1 * time.Second)
    +
    +	var buf = make([]byte, 1024)
    +	r := bufio.NewReader(conn)
    +	_, err = r.Read(buf)
    +	if err != nil {
    +		return "", err
    +	}
    +
    +	return string(buf), nil
    +}
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

11

News mentions

0

No linked articles in our index yet.