Saturday, February 02, 2008

Web Cache Security Issues

Most of web applications are designed to use web caching for end user convenience. Web caching improves the user browsing experience by reducing the latency time (e.g. time to wait for a web page to be served) and allow for better bandwidth usage and reduction of the web server load. Web pages with web cache enabled can be cached in the client browser as well as in the server proxies and gateways (e.g. reverse proxies and web accelerators) that are part of the web traffic between the client and the web server. When a web page is not available, a web server and/or a web proxy can serve the browser with a cached web page. More details on web caching and the caching directives and how can be used are well documented herein http://www.mnot.net/cache_docs/

Web caching is good for performance and covenience but there is a flip side: security. Web caching is a typical example of "security=1/convenience" that is, there is a security cost for user convenience:exposing your web application to potential security threats. For example, since cache information can contain sensitive data has to be protected from unauthorized access. In the case of web applications, you would like to avoid caching confidential information on the user's browser so it could be made accessible outside the control of the web application. Web caching of login pages also expose the application to specific threats such as reply a cached page to re-log on on the application besides stealing user credentials with a web proxy. The countermeasure: set the HTTP Header caching directives in any web page (not just login) that store confidential information. In this way you tell browsers , proxies and gateways not to cache any confidential information. More in the details, when web caching is enabled you need to worry about the following threats and implement the following necessary countermeasures:

Threat#1: Unauthorized information disclosure via cached data access: Web pages that are cached in the browser might contain confidential and sensitive information such as authentication data, session tokens and customer confidential information (e.g. PII, Account Numbers, Tax data). Every web page with user sensitive information that is served to a browser with the HTTP Headers caching directives not explicitly set to "no-cache, no-store" is cached in the browser memory. If the browser is left unattended and another user get access to it (like for example in the case of a shared PC at work, internet cafe etc) such user could gain access to the previous user confidential information from the browser cache. For example, if the web page was previously used to view a pdf file that contained sensitive information (i.e. tax form) such file could still be viewed by accessing the browser memory cache. The web cache exploit is very simple, type "about: cache" on the browser address bar (if you are using Firebox for example).

How you know if you are vulnerable? You know if your web application is vulnerable by doing a simple scan of your application web pages for HTTP headers cache settings. You can use freely available web proxies such as paros proxy with enabled scan policy check for finding secure web cache settings. If the scanner finds cache headers not set securely in web pages serving confidential information (e.g. logins, account queries etc) you should fix these pages.

The countermeasure from the web application perspective is to enforce explicit no-cache and no-store via the HTTP Headers or META tags. The no-cache directive will force any browser, web proxy and gateway to submit the web request to the origin web server for validation before releasing a cached copy, every time. The "no-cache" can be set via HTTP headers HTTP1.1 Cache-Control and via HTTP1.0 Pragma. Meta tags can also be used such as META HTTP-EQUIVALENT. The no-cache settings are:
HTTP/1.1: Cache-Control: no-cache or HTTP/1.1: equiv="Cache-Control"
and
HTTP/1.0: Pragma: no-cache or HTTP/1.0: equiv="Pragma" content="no-cache"
But the most important cache directive is the "no-store" that will tell browsers, web proxies and web servers to not store anything on the cache. From the browser perspective, no-store and no-cache directives are enforced differently depending on the browser you are using (IE vs Firefox) and the HTTP or HTTPs connection. For example in IE even if you are using no-cache you will still cache the page by default.

To be safe with all browsers and version of HTTP protocol you need to enforce no-store, no-cache and expires caching directives as follows:

HTTP/1.1: Cache-Control: no-cache, no-store, private, must-revalidate
HTTP/1.0:Pragma: no-cache
Expires:-1
By specifying "must-revalidate" you’re telling the cache that you want it to strictly follow your rules while by specifying "private" you enforce the default setting of keeping the cache private (if you explicity set the cache-control public will be cached in a shared cache even if a no-cache directive is set). By setting the "Expires:-1" directive you will ensure that the web page is already expired and the browser always gets a fresh copy.

This is for the browser cache. Beware that every web proxy and web gateway will also cache your web pages if cache headers are not enforced. Therefore information disclosure is also possible for any user such as admins that have access to such web servers, web proxies and gateways. Typically enforcing no-caching via HTTP headers is just a minimum countermeasure: servers should be hardened to prevent information disclosure via web caches. The HTTP standard has a section on proxies and caching that requires admins to protect the web cache as sensitive information (http://www.w3.org/Protocols/rfc2616/rfc2616-sec15.html)
Unfortunately you web application alone does not have control on cache beyond the HTTP cache headers settings and the web application trust boundary (i.e. the user browser). For example, web servers and proxies will cache and log every HTTP GET request by default while will not cache POST request. Your web application should use POST and not using GET to prevent both caching and logging of sensitive information. Using HTTPs also helps with cache: most of web proxies and gateways do not cache SSL requests by default.
Threat#2:Information disclosure via HTTP POST reply: When the "no-cache", "no-store" HTTP directives are not enforced on web pages used for authentication such as for logon, the cached web page can be replied by another user that has access to the same PC to log back to the application and/or capture previous logged used credentials with a web proxy. This vulnerability is known as HTTP POST Replay 200 OK and is exposed by a web application as a result of both caching headers not set to no cache no store and by not redirecting a user to a web page different then 200 OK (e.g. 302, 307) after logging in.
How you know if you are vulnerable? You can easily test if the web cache allows you to reply the login page by logging into the application, logging out and by reply the web page cached by the browser by hitting the “back” browser button or by refreshing a previous URL from the browser history. If you are vulnerable, the browser will just issue a warning that the web page you are re-playing is a cached web page and if you proceed then you will log back to the application. A detailed description on how this kind of vulnerability can be used to attack authentication and how can be performed to steal user credentials is explained herein
To be noticed, failing to invalidate sessionIDs during the previous user session logout or/and by application idle logout is not actually necessary for exploiting this vulnerability since the cached web page is re-posted (replayed) from the browser and the credentials are captured via a web proxy before sending the request to the web server.
The countermeasure: enable no-cache, no-store and by following the HTTP POST with a HTTP 302 or 307 redirect response.

Threat#3: Escalation of privileges and user impersonation via cached sessionIDs and cookies: web pages that allow caching of sessionIDs provide a malicious user another avenue for session hijacking, breaking of user authentication and horizontal or vertical escalation of privileges.
How you know if you are vulnerable? If sessionIDs has not been invalidated by the previous web session and can be retrieved by the browser cache and re-used by another malicious user. Such user could use such sessionID to escalate his privileges (e.g. gain access to someone else data). Typically, the exposure of this vulnerability besides caching is also due to weak web applicaton session management (e.g. fail to invalidate sessionIDs and fail to properly in-validate session IDs on the server side). Besides from cached data, session IDs can be retrieved from server logs when used in HTTP GET parameters and through eavesdropping during transmission if SSL is not used.
The countermeasure: Use SSL will mitigate the risk of getting sessionIDs via cache (SSL pages are by default setting not cached by web servers) as well as eavesdropping (data is encrypted). If the cached information is a cookie that contain sensitive information such as un-encrypted password or PIN obviously it can be retrieved from the browser memory and/or disk and be used to authenticate by impersonating that user. Therefore, no sensitive information should be stored in a cookie, otherwise you should at minimum encrypt the cookie contents as well as the channel using SSL. More information on how to test if your session variables are unsecured can be found on the OWASP testing guide: http://www.owasp.org/index.php/Testing_for_Exposed_Session_Variables








No comments: