CodeIgniter CSRF protection and page caching - codeigniter

I've searched around but couldn't find anything about this. Am I the only one who have experienced that CSRF protection in CodeIgniter doesn't work with page caching?
What do I have:
A webpage which will be cached trough this line:
$this->output->cache( 120 );
In the Javascript on that page I've got a Ajax call where the data contains the CSRF token too. Everything works fine when caching is disabled or when I disable CSRF protection.
Does somebody know a workaround or something so I can have caching and CSRF protection enabled?
Thanks!

I'm somewhat surprised that form_open() doesn't handle that for you, in a similar way that benchmarking functions' output aren't cached.
Here are two possible workarounds.
Use the caching driver (!= output->cache())
Instead of using Output class caching, which caches a completely rendered page, you could employ the caching driver's key-value cache to save rendered portions of your page.
If the form containing this problematic CSRF token is complex and contains a lot of dynamic content from an external data source, cache those database results (either with the caching driver or by enabling database result caching) and feed the cached values into a dynamic form.
Warning about file-based cache from the manual:
Unlike caching from the Output Class, the driver file-based caching
allows for pieces of view files to be cached. Use this with care, and
make sure to benchmark your application, as a point can come where
disk I/O will negate positive gains by caching.
Of course, if you have access to memcached or APC, use that instead.
Disable output caching for that page and profile.
Intercepting the output cache (fully-rendered page) and replacing the CSRF token value
I came across an interesting solution on Caching forms with CSRF tokens (in Symfony). To paraphrase the original author:
Before setting the cached response, find and replace CSRF tokens.
Store the position of the tokens with the response (so it gets cached as well).
Before returning a response from the cache inject fresh CSRF tokens.
In CodeIgniter, intercepting the cache seems to require use of the pre_system hook-point, though in your case, you may be able to use cache_override. Take a look at this excellent article on the way in which CodeIgniter implements CRSF tokens for inspiration. I don't think it would be trivial to implement, though.
Don't cache that page and don't worry about it
This is obviously the simplest solution. Test it. Depending on your page complexity, the negative performance impact of not caching that subset of pages may well outweigh the pain of implementing either of the above two solutions. (Since we don't know what your views or controller look like, whether or not this is an acceptable solution in your case isn't immediately obvious). If it's an isolated login form in an SPA, you can probbaly get away with it.

Related

WP Super Cache conflicts Contact Form 7

2 popular Wordpress plugins, Super Cache and Contact Form 7 - there are still some issues expected around _nonce AJAX calls.. How it is possible to make them work together smoothly? Definitely, there are some situations you want to keep ALL your posts (pages) super-cached, and not to be served dinamically without caching while preserving and providing contact form functionality.
When not checking the "Cache rebuild" in the settings, Super Cache will function:
standard pages will NOT enforce a new cache file to be generated (e.g. it REALLY serves an (if) existing supercache file whithout triggering a new cache file to be generated
pages with a wpcf7-form included WILL enforce/trigger the re-generation of supercache file while serving the initial on the request. I think that is the point when things go wrong.
Question: How to stop unwanted re-generation of pages with a wpcf7-form included? Based on wpcf7 plugin homepage Docs by the author, my expectation is that the wpcf7 form has evolved and been developing to meet this ajax-call requirements such _nonce calls. Any idea how to resolve this?
to be hard-coded (e.g. exclude _nonce call and/or URL parameter..) within wpcf7 form (this is against WP standards) or
settings in Super cache?
any other idea, solution or alternatives?
In this thread wpcf7 author says:
Contact Form 7 uses WP nonce as secret key. As nonce life is 24 hours by default, if cache clears less than 24 hours, the two plugins should work without problem, even if the page is cached.

Drupal 6 caching and blocks

I've read all over the place and I'm trying to figure out if I am understanding the way caching happens in Drupal 6. We have a site that has a real time stock ticker in it. We have Drupal caching enabled so the stock price ends up getting cached and frozen at a specific spot. I figured a way I could handle it would be to put the ticker in a block I make in a custom module and set BLOCK_NO_CACHE, but if I'm understanding this correctly, if you have site caching enabled, then the ENTIRE page gets cached including any and all blocks on it regardless of their individual cache settings. Is this correct? So am I unable to take advantage of site caching then if I have certain spots that should not cache? Does anyone know of another solution I might be able to use to have the best of both worlds? To be able to have site caching, but also have a real time stock ticker? By the way, the stock ticker is making a JSON request to the Yahoo finance API to get the quote.
You are correct, the directive BLOCK_NO_CACHE is only applicable to block level. However when page caching is enabled then Drupal will cache the entire page (which includes the block as well). But this is only applicable to anonymous users. Drupal's philosophy is that the content for anonymous users is always the same so they get served the cached page. But this is not applicable to authenticated users. Since different users might have different access to certain parts of the page (e.g. the links block will look different for an admin than a regular user).
You might want to have a look at this discussion: BLOCK_NO_CACHE not working for anonymous users
And there is a solution, which you'll stumble upon this discussion. It's this module: Ajax Blocks. Extract from the module description:
Permits to load some blocks by additional AJAX request after loading
the whole cached page when the page is viewed by anonymous user. It is
suitable for sites which are mostly static, and the page caching for
anonymous users is a great benefit, but there are some pieces of
information that have to be dynamic.

Suggestions on how to handle a static response with dynamic session data

Imagine a website that is highly cached where the output of almost every GET action is cached into a html file that is accessible directly from the HTTP server without having to perform a server-side CGI operation. Now imagine that in addition to that, JavaScript is used to filter the response of the HTML request using AJAX. The AJAX response contains only the appropriate response of the page (so for standard HTML pages it will contain everything except for the surrounding layout, for modals it will contain only the modal box HTML, etc...).
Now lets imagine that the HTML content may be cached neutrally (when nobody is logged in) or cached for someone who is logged in. There are certain areas of the page that are tied to session data (like the welcome message, the profile link, etc...) and that data is specific to the session. But since we're using JavaScript, we can buffer the AJAX response, change the session element values, and then stick it into the DOM all the while the user is unaware of any session hot swapping. This relies ofcoarse only on GET requests and pages where the actual content is not 100% session dependent.
Now here is my question. If I were to implement this (and trust me I will) then how might I actually keep track of the session activity while the user is browsing the page? With a traditional server-side operation, whenever the user accesses a page then the server-side framework will update the session and keep tabs on the session-related variables. With a static HTTP request operation then all server-side involvement is avoided. So I will need to figure out some way of keeping track of what's going on with the session; here are my approaches:
1) Perform two AJAX requests (or an additional one when needed):
Once the user queries a page then the contents will be downloaded as static HTML. But at the same time that page is queried then another AJAX request will be serviced to a session-specific URL/server updating/querying the status of the session. This can be done side by side or can be performed after every few requests are made.
Pros = HTML files are left unchanged, HTML files can be set to have a ETag or future expires header, JavaScript can cache only the static HTML and use it for offline browsing, a session-server can be dedicated, optimized and configured for session activity.
Cons = Two AJAX requests are performed, excessive polling for potentially redundant data, session handling made be separated from content server.
2) Use a midway proxy that appends the session-data as a trailing session JSON
A request is made to the server. There is a proxy in between that locally accesses the session data and then performs another HTTP request (either locally or remotely) which is then concatenated with the session data findings fetched just before. The browser is responded with a clean copy of HTML code where has JavaScript-specific session content and then everything is updated at the same moment.
Pros = Everything is downloaded at once, only one connection required, works like a normal HTTP request would
Cons = Caching gets difficult when a dynamic content proxy is used, content-length may need to be search and replaced with to append additional data, may not work with some browsers?
3) Use Comet for session data
A persistant, reverse-AJAX comet connection could be established at the start of the website connection. Then, all static-HTML requests could be accessed normally. All session-related requests could be accessed from the comet connection.
Pros = Separation of static content and dynamic content.
Cons = Comet isn't supported very well and doesn't work very well, server latency, may conflict with same origin policy.
How do you guys think this problem should be solved? Do you think its doable?
The solution I've found is to use templated data and dynamic data separate from each other. It's too much work and too messy to implement this on your own so you can go as far as using a MVC framework to provide JSON requests with templating (AngularJS, KnockoutJS, EmbedJS, etc...) or you can just stick to using templates in general. Keep in mind that this destroys SEO.

Clear all website cache?

Is it possible to clear all site cache? I would like to do this when the user logs out or the session expires instead of instructing the browser not to cache on each request.
As far as I know, there is no way to instruct the browser to clear all the pages it has cached for your site. The only control that you, as a website author, have over caching of a page occurs when the browser tries to access that page. You can specify that cached versions of your pages should expire at a certain time using the Expires header, but even then the browser won't actually clear the page from its cache at that time.
i certainly hope not - that would give the web site destructive powers over the client machine!
If security is your main concern here, why not use HTTPS? Browsers don't cache content received via HTTPS (or cache it only in memory).
One tricky way to mimic this would be to include the session-id as a parameter when referencing any static piece of content on the site. When the user establishes the session, the browser will recognize all the pieces of content as new due to the inclusion of this parameter. For the duration of the session the browser will used the static content in its cache. After the user logs out and logs back in again, the session-id parameter for the static contents will be different, so the browser will recognize this is as completely new content and will download everything again.
That being said... this is a hack and I wouldn't recommend pursuing it.. For what reason do you want the user's cache to be cleared after their session expires? There's probably a better solution that can fit your situation as opposed to what you are currently asking for.
If you are talking about asp.net cache objects, you can use this:
For Each elem As DictionaryEntry In Cache
Cache.Remove(elem.Key)
Next
to remove items from the cache, but that may not be the full-extent of what you are trying to accomplish.

Do fancy MVC URLs affect how caching is done?

When reading some answers to aquestion on clearing cache for JS files, somebody pointed to this part of the http spec. It basically says that URLS containing a ? should not be pulled from the cache, unless a specific expiry date is given. How do query string absent URLs which are so common with MVC websites (RoR, ASP.Net MVC, etc.) get cached, and is the behaviour different then with more traditional query string based urls?
AFAIK there is no difference on the part of browsers as both Firefox and IE will (incorrectly) cache the response from a url with a querystring, in the same way they cache the response from a url without a querystring. In the case of Safari it respects the spec and doesn't cache urls with querystrings. HTTP proxies tend to be a tad errectic with what they consider cacheable.
It pays to have the headers set correctly and it's worth investigating ETags.
I believe you manage caching in ASP.NET MVC using the OutputCache attribute (on your controller methods).

Resources