Bug: CF Captcha randomly changes file upload POST to GET

Problem

I have simple HTML file upload form using enctype=“multipart/form-data” that uses POST to submit the form to an URL end point that only accepts POST requests.

But the form is very often (but not always) intercepted by CF Captcha. After solving the Captcha, CF randomly modifies the original request to a GET request instead of POST requests, which causes an error at the end point. So sometimes CF keeps it as a POST request, and sometimes it modifies it to a GET request. This unexpected modification behavior happens about maybe 50% to 70% of the time and probably only happens after the Captcha is intercepting the request.

I could ofcourse work around this by disabling the captcha, but it is a bug in CF that should be fixed anyway, so I decided to report it here.

Example

The HTML upload form located at /uploadtest6/get/123 is only available to GET requests. (123 is just an id replaceble by other integers, like an ID of a product.)
The HTML content is simple:

<!DOCTYPE html>
<html>
  <body>
    <form method="post" action="/uploadtest6/post/123" enctype="multipart/form-data">
      <div><input type="file" name="file"></div>
      <div><input type="submit" value="upload"></div>
    </form>
  </body>
</html>

The form is submitted by POST to /uploadtest6/post/123, which only accepts POST requests, which will then return a HTTP 200. It will return a HTTP 405 (Method Not Allowed) when a GET request is received.

When the form is submitted with a random small binary file (<500kb), it will show the CF captcha page depending on the availability of CF cookies. After solving the CF captcha, in about 50% to 70% cases, CF will cause a GET to be send to /uploadtest6/post/123 where a POST is located in the FORM and a POST is expected by the end point. This is demonstrated with the web developer tools in Firefox shown below:


Notice that the last request (which happens automatically after the captcha is solved) is an unexpected GET instead of a POST, which causes the end point to return a HTTP 405 (Method Not Allowed).

On 30% to 50% of the cases, CF will use the expected POST after a CF captcha, as shown below, so no problem occurs for these cases:

Had to remove this part, because new users can only embed one single image per post. So I'll add them as replies below.

In cases where CF doesn’t show a captcha, it will immediately sends the POST as expected:

Had to remove this part, because new users can only embed one single image per post. So I'll add them as replies below.

I’ve tested multiple variants of the form. It also happens when the POST and GET end point use the same URL. (In that case, no error is shown, but it will simply request the form again, without anything being uploaded to the POST end point.)

The problem doesn’t seem to occur when I create an end point without file upload field (maybe because that doesn’t trigger the CF captcha page).

You guys are probably thinking that I’m doing something wrong, because if it would happen to me, it should be happening to a lot of customers. But I checked it using web developers tools, which shows that it does happen somehow.

I also tried this in a clean fresh Firefox browser profile (latest version), but the problem still persists.

If you want to try this, make sure you clean the CF cookies after each upload test, otherwise the success rate will increase, causing the captcha (and the problem) not to show up.

On 30% to 50% of the cases, CF will use the expected POST after a CF captcha, as shown below:

In cases where CF doesn’t show a captcha, it will immediately send the POST as expected:

no captcha-edit

If you keep getting the error, can you create an Account ticket and share your ticket number here? You can open an Account ticket here, https://dash.cloudflare.com/?to=/:account/support

The Ticket ID is 3146849.
The problem exists since at least the start that we implemented our code. It occurs every day, for at least a couple of months.

Since today, the problem does seem to behave a bit differently. Now it does send POST requests, but with incorrect form data, which almost causes 100% failure. The HTTP POST body data differs from the original request send by the browser. Now it contains large encrypted value parameters, with encrypted values. Only the last value contains a bit of a plain string part |{"managed_clearance":"i"}

1 Like

I did some further analysis. The random POST to GET problem still exists, but there is another closely related problem with the POST requests modified by Cloudflare: it changes the Content-Type HTTP header which is a problem for binary data and violates the HTML specification.

What happens is this:
The original POST request send by the browser uses HTTP header Content-Type set to multipart/form-data, as is also defined in HTML code of the form using enctype="multipart/form-data", which is expected behavior. But after the request is processed by Cloudflare, the Content-Type header is modified to application/x-www-form-urlencoded (where is was multipart/form-data). This is unexpected behavior and can cause problems for binary posted data above a certain small size.

This unexpected behavior sequence is captured in the screenshots below. First the original request with expected behavior:


The selected POST request shows Content-Type set to multipart/form-data, as expected.

But after this request is processed by Cloudflare, it is unexpectedly modified to application/x-www-form-urlencoded:


In this case, this final request itself does succeed because the amount of binary data is small, but it does show unexpected behavior that causes problems for just a bit larger binary files (like just 23kb more).

The HTML specification says about this:

The content type “application/x-www-form-urlencoded” is inefficient for sending large quantities of binary data or text containing non-ASCII characters. The content type “multipart/form-data” should be used for submitting forms that contain files, non-ASCII data, and binary data.

I did some testing on the binary file size. The “application/x-www-form-urlencoded” starts to cause problems for binary files with sizes above about 23kbyte. So when testing, make sure that the binary files are large enough.

So the solution would be for Cloudflare to leave the Content-Type HTTP header and HTTP POST body data intact.

1 Like

Hello all,
I got the same problem.

Someone find the solution ?

Regards

Mirko Ugolini

The only real solution is for Cloudflare to fix this bug.

But you can work around the bug by disabling the rule that causes a captcha to be triggered on a POST request, if you security model allows this.

a32x,

but has anyone from Cloudflare responded to your Ticket?

Regards

Mirko

Hello,

I have same problem. At some point, POST request to upload a file started returning a 404 request after completing a CAPTCHA.

We’re waiting the solution.

Regards,