Fixes #6305 - CSRF token verification failure during login after updating to Zammad 7.1
Approved-by: Florian Liebe <fl@zammad.com>
This commit is contained in:
@@ -73,6 +73,34 @@ instead.
|
||||
|
||||
## 7.2
|
||||
|
||||
### Zammad's reverse proxy configuration is authoritative for the request scheme
|
||||
|
||||
**Who is affected?** Admins running the Docker images or a newly installed nginx behind a proxy
|
||||
that reports the request scheme via the `Forwarded` or `X-Forwarded-Ssl` header, and admins of a
|
||||
newly installed Apache behind any TLS-terminating proxy.
|
||||
|
||||
Rack evaluates `X-Forwarded-Ssl` and `Forwarded` with a higher priority than `X-Forwarded-Proto`, so
|
||||
an outer proxy could silently override the scheme that Zammad's own web server configuration had set.
|
||||
The nginx and Apache configurations shipped with Zammad therefore now clear `Forwarded`,
|
||||
`X-Forwarded-Scheme` and `X-Forwarded-Ssl`, which leaves `X-Forwarded-Proto` as the only place where
|
||||
the scheme is decided.
|
||||
|
||||
The Apache configurations did not set `X-Forwarded-Proto` at all before, so an instance behind an
|
||||
SSL-terminating Apache was never seen as HTTPS. They now set it explicitly, to `http` in the non-SSL
|
||||
and to `https` in the SSL virtual host, which also means an outer proxy's value is no longer passed
|
||||
through.
|
||||
|
||||
The Docker images rebuild their nginx configuration from the shipped one on every start, so the change
|
||||
applies to them automatically. Package installations keep the web server configuration they already
|
||||
have; only newly installed ones receive the updated files.
|
||||
|
||||
⚠️ If Zammad was reachable over HTTPS only because the proxy in front of it sent `Forwarded` or
|
||||
`X-Forwarded-Ssl` — or, on Apache, `X-Forwarded-Proto` — configure the scheme in Zammad's own web
|
||||
server instead: set `NGINX_SERVER_SCHEME=https` for the Docker images, or the `X-Forwarded-Proto` line
|
||||
in the nginx respectively Apache configuration file.
|
||||
|
||||
**Related issue:** [#6305](https://github.com/zammad/zammad/issues/6305)
|
||||
|
||||
### Links between an object and itself are rejected, and failed link creations answer `422`
|
||||
|
||||
**Who is affected?** Integrations that create links via `POST /api/v1/links/add`.
|
||||
@@ -202,6 +230,29 @@ reverse proxy are blocked again by it.
|
||||
|
||||
## 7.1
|
||||
|
||||
### `X-Forwarded-Proto` takes precedence over `X-Forwarded-Scheme`
|
||||
|
||||
**Who is affected?** Admins running Zammad behind a reverse proxy that terminates TLS and reports the
|
||||
request scheme via the `X-Forwarded-Scheme` header only, such as Nginx Proxy Manager.
|
||||
|
||||
Zammad was updated from Rack 2 to Rack 3, which changed which header decides whether a request is
|
||||
seen as HTTPS: Rack 2 evaluated `X-Forwarded-Scheme` first, Rack 3 evaluates `X-Forwarded-Proto`
|
||||
first. Zammad's own nginx configuration sets `X-Forwarded-Proto` from the scheme of the connection it
|
||||
receives, in the Docker images via the `NGINX_SERVER_SCHEME` variable, which defaults to `$scheme`.
|
||||
Behind a proxy that terminates TLS and forwards plain HTTP, that value is `http`, so such requests
|
||||
are now seen as plain HTTP even though the proxy reported `X-Forwarded-Scheme: https`.
|
||||
|
||||
With the `http_type` setting set to `https`, the session cookie is marked `Secure`, and a `Secure`
|
||||
cookie is not written on a request that is seen as plain HTTP. No session is created at all, and
|
||||
logging in fails with "CSRF token verification failed!". Sessions that already hold a cookie keep
|
||||
working, so the problem only surfaces after a logout.
|
||||
|
||||
⚠️ Configure the scheme in Zammad's own web server rather than in the proxy in front of it, whose
|
||||
`X-Forwarded-Proto` header is overwritten: set `NGINX_SERVER_SCHEME=https` for the Docker images, or
|
||||
the `X-Forwarded-Proto` line in the nginx configuration file.
|
||||
|
||||
**Related issue:** [#6305](https://github.com/zammad/zammad/issues/6305)
|
||||
|
||||
### Elasticsearch 7 was deprecated
|
||||
|
||||
**Who is affected?** Admins of systems that run Elasticsearch 7.
|
||||
|
||||
@@ -41,6 +41,14 @@ ServerTokens Prod
|
||||
ProxyPass /cable ws://127.0.0.1:3000/cable
|
||||
ProxyPass / http://127.0.0.1:3000/
|
||||
|
||||
# Tell Zammad which scheme the request arrived with, and prevent an outer
|
||||
# proxy from overriding it.
|
||||
# change the value below if a proxy in front of Apache terminates TLS
|
||||
RequestHeader set X-Forwarded-Proto "http"
|
||||
RequestHeader unset Forwarded
|
||||
RequestHeader unset X-Forwarded-Scheme
|
||||
RequestHeader unset X-Forwarded-Ssl
|
||||
|
||||
# change this line in an SSO setup
|
||||
RequestHeader unset X-Forwarded-User
|
||||
|
||||
|
||||
@@ -55,6 +55,13 @@ ServerTokens Prod
|
||||
ProxyPass /cable ws://127.0.0.1:3000/cable
|
||||
ProxyPass / http://127.0.0.1:3000/
|
||||
|
||||
# Tell Zammad which scheme the request arrived with, and prevent an outer
|
||||
# proxy from overriding it.
|
||||
RequestHeader set X-Forwarded-Proto "https"
|
||||
RequestHeader unset Forwarded
|
||||
RequestHeader unset X-Forwarded-Scheme
|
||||
RequestHeader unset X-Forwarded-Ssl
|
||||
|
||||
# change this line in an SSO setup
|
||||
RequestHeader unset X-Forwarded-User
|
||||
|
||||
|
||||
@@ -44,6 +44,10 @@ server {
|
||||
proxy_set_header CLIENT_IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
# Prevent an outer proxy from overriding the scheme set above.
|
||||
proxy_set_header Forwarded "";
|
||||
proxy_set_header X-Forwarded-Scheme "";
|
||||
proxy_set_header X-Forwarded-Ssl "";
|
||||
proxy_read_timeout 86400;
|
||||
proxy_pass http://zammad-websocket;
|
||||
}
|
||||
@@ -57,6 +61,10 @@ server {
|
||||
proxy_set_header CLIENT_IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
# Prevent an outer proxy from overriding the scheme set above.
|
||||
proxy_set_header Forwarded "";
|
||||
proxy_set_header X-Forwarded-Scheme "";
|
||||
proxy_set_header X-Forwarded-Ssl "";
|
||||
proxy_read_timeout 86400;
|
||||
proxy_pass http://zammad-railsserver;
|
||||
}
|
||||
@@ -67,6 +75,10 @@ server {
|
||||
proxy_set_header CLIENT_IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
# Prevent an outer proxy from overriding the scheme set above.
|
||||
proxy_set_header Forwarded "";
|
||||
proxy_set_header X-Forwarded-Scheme "";
|
||||
proxy_set_header X-Forwarded-Ssl "";
|
||||
|
||||
# Change this line in an SSO setup
|
||||
proxy_set_header X-Forwarded-User "";
|
||||
|
||||
@@ -88,6 +88,10 @@ server {
|
||||
proxy_set_header CLIENT_IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
# Prevent an outer proxy from overriding the scheme set above.
|
||||
proxy_set_header Forwarded "";
|
||||
proxy_set_header X-Forwarded-Scheme "";
|
||||
proxy_set_header X-Forwarded-Ssl "";
|
||||
proxy_read_timeout 86400;
|
||||
proxy_pass http://zammad-websocket;
|
||||
}
|
||||
@@ -101,6 +105,10 @@ server {
|
||||
proxy_set_header CLIENT_IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
# Prevent an outer proxy from overriding the scheme set above.
|
||||
proxy_set_header Forwarded "";
|
||||
proxy_set_header X-Forwarded-Scheme "";
|
||||
proxy_set_header X-Forwarded-Ssl "";
|
||||
proxy_read_timeout 86400;
|
||||
proxy_pass http://zammad-railsserver;
|
||||
}
|
||||
@@ -111,6 +119,10 @@ server {
|
||||
proxy_set_header CLIENT_IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
# Prevent an outer proxy from overriding the scheme set above.
|
||||
proxy_set_header Forwarded "";
|
||||
proxy_set_header X-Forwarded-Scheme "";
|
||||
proxy_set_header X-Forwarded-Ssl "";
|
||||
|
||||
# change this line in an SSO setup
|
||||
proxy_set_header X-Forwarded-User "";
|
||||
|
||||
@@ -121,6 +121,50 @@ RSpec.describe 'Sessions endpoints', type: :request do
|
||||
expect(response.header['Set-Cookie']).to include(session_key).and include('; secure;')
|
||||
end
|
||||
end
|
||||
|
||||
# Rack decides which forwarded header wins; these examples pin that order down, because
|
||||
# our proxy configuration relies on it (see https://github.com/zammad/zammad/issues/6305).
|
||||
context "when a proxy sends contradicting 'X-Forwarded-Proto' and 'X-Forwarded-Scheme' headers" do
|
||||
|
||||
let(:headers) do
|
||||
{
|
||||
'X-Forwarded-Proto' => 'http',
|
||||
'X-Forwarded-Scheme' => 'https'
|
||||
}
|
||||
end
|
||||
|
||||
it "sets no Cookie, because 'X-Forwarded-Proto' takes precedence" do
|
||||
expect(response.header['Set-Cookie']).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context "when a proxy sends an 'X-Forwarded-Ssl' header" do
|
||||
|
||||
let(:headers) do
|
||||
{
|
||||
'X-Forwarded-Proto' => 'http',
|
||||
'X-Forwarded-Ssl' => 'on'
|
||||
}
|
||||
end
|
||||
|
||||
it "sets Cookie with 'secure' flag, because 'X-Forwarded-Ssl' takes precedence" do
|
||||
expect(response.header['Set-Cookie']).to include(session_key).and include('; secure;')
|
||||
end
|
||||
end
|
||||
|
||||
context "when a proxy sends a 'Forwarded' header" do
|
||||
|
||||
let(:headers) do
|
||||
{
|
||||
'X-Forwarded-Proto' => 'http',
|
||||
'Forwarded' => 'proto=https'
|
||||
}
|
||||
end
|
||||
|
||||
it "sets Cookie with 'secure' flag, because 'Forwarded' takes precedence" do
|
||||
expect(response.header['Set-Cookie']).to include(session_key).and include('; secure;')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when Setting 'http_type' is set to 'http'" do
|
||||
|
||||
Reference in New Issue
Block a user