A possible host header injection attack have been identified in Invenio-App. For an attack to be possible, all conditions below must be met:
APP_ALLOWED_HOSTS
configuration variable to whitelist allowed host headers.request.host
must not have been evaluated during request handling.An example of a view which does not evalute request.host
is a simple view using just url_for
to generate an external URL (similar is possible when rendering just a Jinja template):
@app.route('/')
def index():
return url_for('index_url', _external=True)
This happens, because Werkzeug's trusted host feature, which APP_ALLOWED_HOSTS
rely on, does not check the the list of trusted hosts in it's routing system that url_for
is relying on.
Invenio-App v1.0.6 and v1.1.1 fully fix the issue.
Note, we strongly recommend (see Securing your instance) that you never route requests to your application with a wrong host header. The APP_ALLOWED_HOSTS
configuration variable exists as an extra protective measure because it is easy to misconfigure your web server to allow requests with any host header.
You should ensure that you never route requests with a wrong host header to your application. The workaround depends on which web server you are using to proxy requests to your application. In general it involves ensuring that the web server has two virtual hosts defined:
Note, for instance in Nginx if you only configure the application virtual host, by default, it will also act as the default virtual host despite you having configured a whitelist of host headers.
Below is an example for Nginx. Note for clarity we have only included the virtual host for port 443, but this also extends to virtual hosts running on any other port.
# etc/nginx/nginx.conf
http {
# ...
include /etc/nginx/conf.d/*.conf;
}
Default virtual host
Notice, the server_name
is _
and the listen
directive has it marked as default_server
.
# etc/nginx/conf.d/default.conf
server {
listen 443 default_server;
listen [::]:443 default_server;
server_name _;
# ...
return 301 https://www.example.com;
}
Application virtual host
Notice, the server_name
is set to the host header whitelist.
# etc/nginx/conf.d/app.conf
server {
listen 443;
listen [::]:443;
server_name www.example.com;
# ...
}
We strongly recommend that you use the method described in Workaround 1.
If you are not able to upgrade to the patched versions of Invenio-App, you can include the following code snippet in your application to force evaluation of request.hosts
.
@app.before_request
def before_request():
request.host
If you have any questions or comments about this advisory: * Email us at info@inveniosoftware.org