Bug #61664

Error "&cHash comparison failed" in case of POST forms

Added by Dirk Wildt over 7 years ago. Updated almost 7 years ago.

Status:
Rejected
Priority:
Should have
Assignee:
-
Category:
Caching
Target version:
Start date:
2014-09-16
Due date:
% Done:

0%

Estimated time:
TYPO3 Version:
6.2
PHP Version:
Tags:
Complexity:
easy
Is Regression:
No
Sprint Focus:

Description

The cHash calculation fails in TYPO3 6.2.1 - 6.2.4, if params are sent by a POST form.

The cause is, that the method
  • typo3_src-6.2.4/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php::makeCacheHash
    respects GET params only and ignores POST params.

This can fix by moving from _GET to _GP in the method. See (nearby line 2270):

...
public function makeCacheHash() {
// No need to test anything if caching was already disabled.
if ($this->no_cache && !$this->TYPO3_CONF_VARS['FE']['pageNotFoundOnCHashError']) {
return;
}
// dwildt, 1-
//$GET = GeneralUtility::_GET();
// dwildt, 1+
$GET = GeneralUtility::_GP();
if ($this->cHash && is_array($GET)) {
...

#1

Updated by Helmut Hummel over 7 years ago

  • Status changed from New to Needs Feedback

Dirk Wildt wrote:

The cHash calculation fails in TYPO3 6.2.1 - 6.2.4, if params are sent by a POST form.

Please give an example what exactly fails for you.

#2

Updated by Dirk Wildt over 7 years ago

Dear Helmut,
If I send params including a proper cHash value by a POST form, TYPO3 throws this error:

Page Not Found
Reason: Request parameters could not be validated (&cHash empty)

If I move the form method from POST to GET the TYPO3 cHash comparison is proper.

It seems, that there is a bug in the code of the TypoScriptFrontendController class (see above).
The code evaluates GET params only.

If I change the code like in the snippet above (from _GET to _GP), both cHash comparisons are proper:
  • with form method GET
  • and with form method POST

I would be happy, if my report is clear :)

Thanks for your quick response.

Dirk

#3

Updated by Xavier Perseguers over 7 years ago

Is it possible for you to show us a minimal code sample (controller/view/special TS configuration/...) on how to reproduce the problem?

#4

Updated by Dirk Wildt over 7 years ago

Dear Helmut,
I read your post at

Does it mean, I must send a form with the method GET and method POST is unpossible, because cHash comparison failed?
And if yes, would it be nice, to add a tip to the error message of the TypoScriptFrontendController class like

Page Not Found
Reason: Request parameters could not be validated (&cHash empty)
Be aware: Parameters must be send by the form method GET

Kind regards
Dirk

#5

Updated by Stefan Neufeind over 7 years ago

You have the form-tag auto-generated by Extbase I guess? Or do you generate that yourself?

#6

Updated by Dirk Wildt over 7 years ago

Dear Helmut, dear Xaviar,
this is a code snippet for rreproducing the problem:

Form with method GET works proper:

  <form name="form_confirm" method="GET">
    <fieldset>
      <legend>
        Start the Installation
      </legend>
      <input type="hidden" name="tx_orginstaller_pi1[confirm]" value="1" />
      <input type="hidden" name="cHash"                        value="5416c8c16f8ea7d9823472d0ff373d39" />
      <input type="submit" name="submit" value=" Install it! " />
    </fieldset>
  </form>

Form with method POST throws the error "...could not be validated (&cHash empty)" from above:

  <form name="form_confirm" method="POST">
    <fieldset>
      <legend>
        Start the Installation
      </legend>
      <input type="hidden" name="tx_orginstaller_pi1[confirm]" value="1" />
      <input type="hidden" name="cHash"                        value="5416c8c16f8ea7d9823472d0ff373d39" />
      <input type="submit" name="submit" value=" Install it! " />
    </fieldset>
  </form>

The cHash value is calculated in both samples (GET and POST):

  $cacheHash = t3lib_div::makeInstance('t3lib_cacheHash');
  $cHash     = $cacheHash->generateForParameters('&tx_orginstaller_pi1[confirm]=1&submit= Install it! ');

Kind regards
Dirk

#7

Updated by Dirk Wildt over 7 years ago

Be ware, the generated cHash value depends on the encryption key of your TYPO3 installation.
If you like to reproduce the error, you have to generate your cHash value first an replace my given value with yours.

#8

Updated by Xavier Perseguers over 7 years ago

  • POST action should not get cached since POST means a change is going on, do you experience a problem if you don't have a cHash?
  • cHash is meant to validate the parameters and prevent caching problems, thus when using a GET request

As such there should be no need to provide a cHash with POST requests and as you see it makes no sense to validate POST parameters.

And do not forget that best practices redirect (as GET) to some "confirmation page" or alike and do not output HTML response right away when doing a POST request.

#9

Updated by Stefan Neufeind over 7 years ago

For the form you mentioned: I guess for now you'd need to put the cHash into the URL (as part of the "action") for it to be recognised, instead of sending it as part of the POST.

I agree that using POST and caching is usually a strange combination. Should we maybe consider avoiding to cache POST-requests? Or give a warning of some sort if some plugin tries to use POST with something that involves caching? Maybe that helps more than complaining about a wrong/missing cHash in that case.

#10

Updated by Marc Bastian Heinrichs over 7 years ago

Stefan Neufeind wrote:

For the form you mentioned: I guess for now you'd need to put the cHash into the URL (as part of the "action") for it to be recognised, instead of sending it as part of the POST.

Yeah, but only, if you have get vars in your action url. If you send by POST without getvars in the url, simple remove the cHash!

#11

Updated by Marc Bastian Heinrichs over 7 years ago

I agree that using POST and caching is usually a strange combination. Should we maybe consider avoiding to cache POST-requests?

In general? Why that? Should be enough to be aware of not caching the content the POST is sent for.

#12

Updated by Dirk Wildt over 7 years ago

I agree that using POST and caching is usually a strange combination.

I agree too.

But maybe there is a problem in principle:
  1. $TYPO3_CONF_VARS['FE']['pageNotFoundOnCHashError'] is true by default.
  2. typo3_src-6.2.4/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php::makeCacheHash doesn't respect the no_cache parameter, if pageNotFoundOnCHashError is true
  3. Effect is, you can't use a POST form without any caching but you disable pageNotFoundOnCHashError.

Code snippet from TypoScriptFrontendController.php::makeCacheHash

    public function makeCacheHash() {
        // No need to test anything if caching was already disabled.
        if ($this->no_cache && !$this->TYPO3_CONF_VARS['FE']['pageNotFoundOnCHashError']) {
            return;
        }

I want be able to use both:
  • pageNotFoundOnCHashError = true
  • A POST form without any caching

Why it isn't possible?
Or do I have a knot in my brain?

#13

Updated by Dirk Wildt over 7 years ago

If a request should not cached in case of the POST method, would be this a possible improvement
in typo3_src-6.2.4/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php::makeCacheHash?

Current code:

    public function makeCacheHash() {
        // No need to test anything if caching was already disabled.
        if ($this->no_cache && !$this->TYPO3_CONF_VARS['FE']['pageNotFoundOnCHashError']) {
            return;
        }
        ...

Improved code:

    public function makeCacheHash() {
        // #61664, 140917, dwildt, 5+
        // No need to test anything if params are sent by POST method.
        $POST = GeneralUtility::_POST();
        if (is_array($POST)) {
            return;      
                }
        // No need to test anything if caching was already disabled.
        if ($this->no_cache && !$this->TYPO3_CONF_VARS['FE']['pageNotFoundOnCHashError']) {
            return;
        }
        ...

#14

Updated by Helmut Hummel over 7 years ago

  • Status changed from Needs Feedback to Rejected

Dirk Wildt wrote:

I want be able to use both:
  • pageNotFoundOnCHashError = true
  • A POST form without any caching
    Why it isn't possible?

It is possible.

Or do I have a knot in my brain?

Yes.

  • TYPO3 only knows a page cache, where the complete rendered output of a page is cached.
  • You can only have on cache entry per page id.
    • There are some exceptions to this rule, one is: a valid cHash parameter is provided as GET parameter. This triggers a different cache entry.
  • There is also a concept of cached and not cached plugins (USER vs. USER_INT). A USER_INT is never cached, although the surrounding page HTML is cached.

You can achieve what you want likewise (in Extbase terms):

indexAction -> is cached and renders form. The form action attribute has a URI to the update action with a valid cHash. The URI contains only one argument that triggers the updateAction in your plugin
updateAction -> is not cached (USER_INT) It can recieve arbitrary arguments via POST

So what you want to achieve is possible and nothing needs to be done in the TYPO3 core

#15

Updated by Helmut Hummel over 7 years ago

One additional note here:

If you have question on the topics cHash or USER_INT, feel free to ask on the dev list.

#16

Updated by Dirk Wildt over 7 years ago

Dear Helmut,
Thanks a lot for your engagement.

Kind regards
Dirk

#17

Updated by Stefan Neufeind about 7 years ago

Had the same issue. Setting the plugin, the whole page or whatever to non-cached didn't help as well. I wonder if CoolUri might be part of the problem here in my installation. But if you look up the internal URL, there is just the id=... in the URL here. I wonder if the additional POST-data make any difference or not.

Workaround: Disable "pageNotFoundOnCacheHasherror" sigh

#18

Updated by Christof Hagedorn about 7 years ago

same issue here.
i had to Disable "pageNotFoundOnCacheHasherror" .

How can we use fluid forms (which are generated with method="post") which act as a filter form
without disabling pageNotFoundOnCacheHasherror ?

f.e.:

form in searchAction makes a post to listAction
should listAction be listed in the list "non-cacheable actions" in ext_localconf.php ?
Could this be an issue?

#19

Updated by Sven Burkert almost 7 years ago

I have this issue with tt_news when using the search. Many others, too, I've found more than 600 results in google.

I do not understand the problem with cHash here:
I have a news search on a cached page, e.g.: news/search.html
Now, I execute the search, so this cached page is called again (the url stays exactly the same!), with POST vars.
The tt_news plugin is USER_INT, so it should display the search results. But after submitting the search form I get this "cHash comparison failed" error.

Also available in: Atom PDF