Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dealing with CloudFlare's: cf_chl_jschl_tk & cf_chl_captcha_tk?

The problem:

When my website is set to "I'm under attack" mode, once a user passes the CloudFlare screen they are redirected to my website with a large, and rather long query get parameter:

?__cf_chl_jschl_tk__=63c51316f61a63e46f1639d6cf43f9d9b536adea-1587754610-0-AV-peahelegQeMeSrc_4ZJBUq47gdkX_QiS2eERoRTEODUjwbib2MM_73nQDAhukLbkspNpj01mv-Z-JteR4MpY4LUMm-yLJrPQKTX74DGYbZIs2utbp3_q4uozgzKpqcax10YESVKDhZgaWQYHGqBL9koIoasVOzKyvU7VQuKT1Nieo-i8DdXrV0IQf-nyI8KgWnxhYSVBOc-4WNrZzHQlEXFOpV45AGs10aMJyrs376HLRhNdV05MCj8oqMrexuQDtY7B3p7riHByYdB7GIgc

enter image description here

Why this is bad:

  • Ugly link shared around online - (I have seen this happen a few times already)
  • I cannot redirect the get parameters away - (They are not accessible to check if set to redirect away)
  • Ugly urls - (We spend lots of time writing clean/pretty urls for our applications)
  • POST data is set on the page - (you cannot refresh without 'resubmitting' the CF authentication)

Proposed solution:

The way I see to avoid this would be to check if the get parameters are set and then redirect back to the same page with the parameters removed. (Making sure not to lose any other query parameters if set)

I have written a function to achieve this:

function checkAndRemoveCloudFlareParams() {
    if (isset($_GET['__cf_chl_jschl_tk__']) && ! empty($_GET['__cf_chl_jschl_tk__'])
     || isset($_GET['__cf_chl_captcha_tk__']) && ! empty($_GET['__cf_chl_captcha_tk__'])) {

        $new_uri = '?';
        $uri = explode('?', $_SERVER['REQUEST_URI']);
        $uri = $uri[0];

        // Get any other params to put back on later
        foreach ($_GET as $key => $var) {
            if ($key !== '__cf_chl_jschl_tk__' && $key !== '__cf_chl_captcha_tk__') {
                $new_uri .= $key . '=' . $var . '&';
            }
        }

        if ($new_uri !== '?') {
            $new_uri = rtrim($new_uri, '&');
            $uri .= $new_uri;
        }

        header('Location: ' . $uri);
        die;
    }
}

When I test this locally by manually entering the _GET parameters it works. However when deployed up to my live site, the _GET query parameters are not there or available to access when loaded directly from CloudFlare. I believe CloudFlare adds the parameters after the page has been loaded? Maybe through Javascript push states(?) Has anyone else dealt with this before?

I have spoken to CloudFlare about this already and they said this is how it will work from now on as there were problems with their old system. Unfortunately these query parameters are very ugly and are making me start to twitch from annoyance of seeing it all the time ;)

Any advice on how to deal with these params and get rid of them? Kind regards

like image 894
Jack Avatar asked Apr 24 '20 19:04

Jack


2 Answers

JS solution:

(function(){
    var reg = /[\?&](__cf_chl_jschl_tk__|__cf_chl_captcha_tk__|__cf_chl_managed_tk__|__cf_chl_tk)=[^&]+/
    history.replaceState && reg.test(location.search) && history.replaceState(
      null, '', location.pathname + location.search.replace(reg, '').replace(/^&/, '?') + location.hash
    );
})();

Updated in 2022 to deal with What exactly is the `#:~:text=` location hash in an URL? because it is not present in location.hash

like image 166
M-A-X Avatar answered Nov 18 '22 14:11

M-A-X


Cloudflare is a distributed reverse proxy. All your requests and responses are transmitted through the Cloudflare's reverse proxy in cleartext. The __cf_chl_jschl_tk__ (Cloudflare challenge / Javascript challenge token) is added to the redirect location URLs at the proxy and would be stripped at the proxy before it gets to your website.

You may try to get rid of the token with Javascript, however, it's important to understand the consequences. If a token is missing in a request, Cloudflare would be more likely to run your users through anti-bot challenges again and again, leading to poor user experience.

How exactly likely it would be to do that remains a mystery though, because DDoS mitigation services do not typically openly document those details.

like image 33
ximaera Avatar answered Nov 18 '22 15:11

ximaera