We are currently in the process of updating a large (i.e. several hundreds of thousands of non-framework lines of code) and heavily-visited production website from CakePHP 3.2 to CakePHP 4.3.
The website makes extensive use of CakePHP’s form protection functionality. One change that occurred between versions 3.2 and 4.3 is that the form protector now uses the session ID to generate the token hash which is included as a hidden field in forms (see e.g. this commit). The commit message indicates that user-specific data was added to the token hash “to avoid privilege escalation”. I presume that this is intended to address the issue where two users share a computer: if the first user logs out but accidentally leaves a tab open with a form, a second user could submit that form, since the form protection hash was not unique to the first user.
A side effect of is is that, if a user is required to reauthenticate as a result of a session timeout (or an explicit logout), all existing forms now become invalid, unlike in Cake 3. This causes major headaches for us because we wish to continue to allow users to submit existing forms (in the both the current tab and other tabs) following a reauthentication (in order not to lose work) and, to this end, the project also has JavaScript component to automatically resubmit failed Ajax post requests following reauthentication. All of this functionality is now broken.
We have considered a number of possible solutions, the simplest of which seems to be reverting the hash logic to the CakePHP 3 position and handling the possibility of privilege escalation via explicit privilege checks on all actions (which have already been in place for a long time). However, it seems that even this approach is not possible, as CakePHP does not provide any way to override or modify the behaviour of the generateHash()
method in the FormProtector class (which is explicitly instantiated via the ‘new’ keyword in the FormHelper and FormProtectionComponent (NB: link not added owing to 2-link per-post limit) classes.
Does anyone have any suggestions as to handle this issue so as to (i) achieve the goal of incorporating form protection while (ii) allowing users to be able to submit existing forms following reauthentication?
If there is no way to do so, would the CakePHP team consider a future change to allow more flexibility in the logic used to generate the form protection hash?