CSRF protections are disabled, HTTP400 with invalid origin
See original GitHub issueDescribe the bug I’m running the Docker version of the application. Because there’s a shared server running this, I’ve got nginx running as a reverse proxy to the Docker container which is hosting webanno. I get the following error after I log in:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Mon Mar 11 18:53:13 UTC 2019
There was an unexpected error (type=Bad Request, status=400).
Origin does not correspond to request
I think the problem here is that the CSRF protections have been disabled, cross-origin resource sharing isn’t configured correctly, and the app is vulnerable to XSS attacks by default.
I’ve made sure that the nginx proxy preserves the origin of all requests, and also forwards all request headers. Something internally is misconfigured and is either binding to an invalid domain, but I can’t be sure since there’s no way to configure this outside of modifying the source and recompiling the .jar file.
The CSRF token is clearly seen in the request headers.
To Reproduce Steps to reproduce the behavior:
- Follow the normal documentation, and put the Docker version of the tool online.
- Configure an nginx reverse proxy to forward requests to the container. Here is an example:
# If we receive X-Forwarded-Proto, pass it through; otherwise, pass along the
# scheme used to connect to this server
map $http_x_forwarded_proto $proxy_x_forwarded_proto {
default $http_x_forwarded_proto;
'' $scheme;
}
# If we receive X-Forwarded-Port, pass it through; otherwise, pass along the
# server port the client connected to
map $http_x_forwarded_port $proxy_x_forwarded_port {
default $http_x_forwarded_port;
'' $server_port;
}
# If we receive Upgrade, set Connection to "upgrade"; otherwise, delete any
# Connection header that may have been passed to this server
map $http_upgrade $proxy_connection {
default upgrade;
'' close;
}
# Apply fix for very long server names
server_names_hash_bucket_size 128;
# Default dhparam
# Set appropriate X-Forwarded-Ssl header
map $scheme $proxy_x_forwarded_ssl {
default off;
https on;
}
gzip_types text/plain text/css application/javascript application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
log_format vhost '$host $remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
access_log off;
# HTTP 1.1 support
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $proxy_connection;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl;
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
# Mitigate httpoxy attack (see README for details)
proxy_set_header Proxy "";
server {
server_name _; # This is just an invalid value which will never trigger on a real hostname.
listen 80;
access_log /var/log/nginx/access.log vhost;
return 503;
}
server {
server_name _; # This is just an invalid value which will never trigger on a real hostname.
listen 443 ssl http2;
access_log /var/log/nginx/access.log vhost;
return 503;
ssl_session_tickets off;
ssl_certificate /etc/nginx/certs/default.crt;
ssl_certificate_key /etc/nginx/certs/default.key;
}
# my server
upstream <censored domainname> {
## Can be connect with "nginx-proxy" network
# webanno-annotation-tool_webanno_1
server <censored docker internal IP>:80;
}
server {
server_name <censored domainname>;
listen 80 ;
access_log /var/log/nginx/access.log vhost;
return 301 https://$host$request_uri;
}
server {
server_name <censored>;
listen 443 ssl http2 ;
access_log /var/log/nginx/access.log vhost;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:!DSS';
ssl_prefer_server_ciphers on;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_certificate /etc/nginx/certs/<mycert>.crt;
ssl_certificate_key /etc/nginx/certs/<mycert>.key;
ssl_dhparam /etc/nginx/certs/<mycert>.pem;
add_header Strict-Transport-Security "max-age=31536000";
include /etc/nginx/vhost.d/default;
location / {
proxy_pass <censored domainname>;
}
}
Expected behavior I should be able to log in. I expected a HTTP403 not HTTP400 if there is an attempt to break the authentication system.
- Version and build ID: latest tag on Docker as of 3/11/2019
- OS: Ubuntu 16.04, running Docker version 18.09.3, build 774a1f4
- Browser: Doesn’t matter.
Issue Analytics
- State:
- Created 5 years ago
- Comments:26 (15 by maintainers)
Top GitHub Comments
@peterstory thanks for letting us know that it wasn’t a bug after all 😃
Adding this to the documentation: