For my last client engagement, I was tasked with adding an additional layer of authentication to a publicly accessible website without actually modifying the website’s application code or web server configuration. After doing a little research, I came upon the idea of using a HTTP reverse proxy to intercept requests to the website and perform additional authentication before letting end users access the target web application.
If you are not familiar with the concept of a HTTP reverse proxy, think of it as a specialized web server that inspects incoming HTTP requests, forwards them to another (usually internal) web server after any local processing is completed, and makes sure that HTTP responses sent back to the client contain proper host names. The following diagram illustrates the typical processing flow when using a SSL enabled reverse proxy server that is acting as a front end to an internal web server.
In this diagram, the reverse proxy server is performing 3 major tasks:
- Performing an additional level of authentication for client connections.
- Proxying HTTP requests and rewriting hostnames in HTTP responses.
- Terminating SSL connection requests from clients.
In addition to the tasks above, it is possible to use a reverse proxy server as a poor mans web application firewall by filtering HTTP requests that contain invalid characters that could be used for basic SQLi attacks. Reverse proxy functionality is provided by external modules such as mod_proxy for Apache and URL Rewrite/Application Request Routing for IIS.
To get clients to connect to the reverse proxy server instead of the internal application server, the reverse proxy server is usually configured with a public DNS hostname and publicly routable IP address. Thus, any links that are made available to users will resolve to the public IP address/DNS hostname of the reverse proxy server. The reverse proxy server will then perform the job of mapping the external HTTP requests to the proper internal web server.
With that introduction out of the way, let’s discuss how a HTTP reverse proxy can be used to add an additional layer of authentication to a web application. As pointed out earlier, a HTTP reverse proxy is really nothing more than a dedicated web server with additional modules that decide when and how to forward traffic to another web server. Thus, when a user connects to a HTTP reverse proxy server, any authentication method that is supported by the reverse proxy server’s web server platform can be used to authenticate users.
For my engagement, I used IIS 7.5 with URL Rewrite 2.0 as my reverse proxy server. To provide an additional layer of authentication, I used the RSA Web Authentication Agent 7.0 along with Authentication Manager Express. After installing the web authentication agent, I configured the agent to protect all resources on the reverse proxy server. This has the effect of forcing all HTTP requests that are accepted by the reverse proxy server to be intercepted and processed by the web authentication agent. Once the web authentication agent completed the authentication sequence with the client, a record of the authentication is stored in the client’s browser as a cookie. Immediately after the authentication sequence completes, the agent redirects the user back to their original destination which again points to the reverse proxy server. Since authentication is now complete, the web authentication agent will no longer intercept the request and will instead forward the request over to the URL rewrite module. The URL rewrite module will then simply forward requests to the internal web server per the rewrite rules that were configured.
As for the rewrite rules themselves, when using the RSA web authentication agent on the reverse proxy server I found it necessary to write 2 rules for incoming HTTP requests to ensure that the reverse proxy server did not forward requests for the web authentication agent to the internal web server. To handle requests that should be processed by the web authentication agent, I created an inbound URL rewrite rule that matched the URL path for requests to the web authentication agent. The action for this rule was to simply not process it, which permitted the request to drop out of the URL rewrite module and be handled by the web authentication agent. Any other request that did not match the agent’s URL path was forwarded to the internal web server. The following snippet from my web.config file illustrates the rules that were used:
<rules>
<rule name="ReverseProxyInboundRule1" enabled="true" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{CACHE_URL}" pattern="^(https?)://" />
<add input="{REQUEST_URI}" pattern="(.*IISWebAgentIF.dll.*)" />
</conditions>
<action type="None" />
</rule>
<rule name="ReverseProxyInboundRule2" enabled="true" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{CACHE_URL}" pattern="^(https?)://" />
</conditions>
<action type="Rewrite" url="http://www.example-internal.com:8080/{R:1}" logRewrittenUrl="true" />
</rule>
</rules>
For fans of open source solutions, the same functionality could easily be provided with Apache’s mod_proxy module using the ProxyPass and ProxyPassReverse directives. The virtual servers that contain these directives would then need to be configured to require authentication at which point any of the standard Apache user authentication methods such as mod_auth or mod_auth_ldap. Apache has the additional advantage of supporting the mod_security web application firewall, so the mod_proxy directives could be easily combined with mod_security to provide both additional client authentication and a transparent WAF.