I need to change the way we authenticate a django application.
Currently we authenticate by an apache module which sets the REMOTE_USER header and passes it to the python app in the environment of mod_wsgi.
The new approach will be to use an app gateway. The gateway works like a reverse proxy and intercept requests to the application. The app gateway authenticates the user and if succesful forwards the request to our application with the REMOTE_USER header set.
The problem with this approach is that mod_wsgi will drop that header.
This isn’t a problem if apache is doing the authentication as it will copy in the authenticated value. But mod_wsgi won’t accept an existing header being passed. mod_wsgi does this to prevent spoofing as this comment in mod_wsgi explains:
/* * Apache 2.2 when converting headers for CGI variables, doesn't * ignore headers with invalid names. That is, any which use any * characters besides alphanumerics and the '-' character. This * opens us up to header spoofing whereby something can inject * multiple headers which differ by using non alphanumeric * characters in the same position, which would then encode to same * value. Since not easy to cleanup after the fact, as a workaround, * is easier to simply remove the invalid headers. This will make * things end up being the same as Apache 2.4. Doing this could * annoy some users of Apache 2.2 who were using invalid headers, * but things will break for them under Apache 2.4 anyway. */
CVE-2015-0219 for Django illustrates how this vulnerability works some more.
However, we have a trusted environment, mTLS between the application and app gateway and network policies restrincting anyone accessing the application directly. We just want to use REMOTE_USER…
The solution is to create a new header based on REMOTE_USER that will be acceptable to mod_wsgi in the apache config e.g.
RequestHeader set REMOTE-USER "expr=%{req:REMOTE_USER}"
RequestHeader tells apache to take the value of REMOTE_USER and set it to REMOTE-USER. That’s a valid name that will not be dropped and will appear in mod_wsgis environment as HTTP_REMOTE_USER. The HTTP_ prefix ensures that it won’t conflict with any REMOTE_USER header that apache authorisation might set.