Skip to content

Instantly share code, notes, and snippets.

@manciuszz
Created February 17, 2020 23:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save manciuszz/ddddf1b19a2be781d60406c132f92ddc to your computer and use it in GitHub Desktop.
Save manciuszz/ddddf1b19a2be781d60406c132f92ddc to your computer and use it in GitHub Desktop.
The new CloudFlare JS Challenge via POST request minimal solution.
// Before executing, make a break point on "#jschl_answer" element so when it gets a value, debugger kicks in...
(function() {
let form = document.querySelector("#challenge-form");
if (!form)
return console.log("No JS Challenge detected!");
let request = function(params, callbackFn) {
fetch(params.requestURL, {
"method": "POST",
"headers": {
"content-type": "application/x-www-form-urlencoded",
},
"body": `r=${params.r}&jschl_vc=${params.jschl_vc}&pass=${params.pass}&jschl_answer=${params.jschl_answer}`,
}).then(res => res.text()).then(res => {
callbackFn(res);
});
};
let solveChallenge = function(htmlResponse) {
let doc = new DOMParser().parseFromString(htmlResponse, 'text/html');
let operation = doc.head.innerHTML.match(new RegExp("setTimeout\\(function\\(\\)\\{\\s+(var (?:\\w,)+f.+?\\r?\\n[\\s\\S]+?a\\.value =.+?)\\r?\\n"));
operation = operation[1]
.replace(new RegExp("a\\.value = (.+ \\+ t\\.length.+?)\'?;.+", "g"), "$1")
.replace(new RegExp("(e\\s=\\sfunction\\(s\\)\\s\\{.*?};)", "gms"), "")
.replace(new RegExp("\\s{3,}[a-z](?: = |\\.).+", "g"), "")
.replace("t.length", (location.host.length + 1).toString())
.replace("\\n", "");
return {
"requestURL": doc.querySelector("#challenge-form").action,
"r": doc.querySelector("input[name=r]").value,
"jschl_vc": doc.querySelector("input[name=jschl_vc]").value,
"pass": doc.querySelector("input[name=pass]").value,
"jschl_answer": eval(operation.toString()),
};
};
// Disable form submit functions, so it doesn't automatically redirect the browser page (since we want do confirm everything works manually)
form.submit = function() {};
let bypass = function(currentHTML) {
request(solveChallenge(currentHTML), function(responseHTML) {
setTimeout(() => {
bypass(responseHTML);
}, 5000);
});
};
// Function that takes a document HTML string as input and calculates the solution which is then used for comparison to see if both solutions are identical
// This was mainly used for confirming cloudflare bypass implementation calculations on other languages (like Kotlin)...
let testSolution = function(testHTML) {
let current = {
"requestURL": document.querySelector("#challenge-form").action,
"r": document.querySelector("input[name=r]").value,
"jschl_vc": document.querySelector("input[name=jschl_vc]").value,
"pass": document.querySelector("input[name=pass]").value,
"jschl_answer": document.querySelector("#jschl-answer").value,
};
let solved = solveChallenge(testHTML || document.documentElement.innerHTML);
return [current, solved];
};
bypass(document.documentElement.innerHTML);
})();
@manciuszz
Copy link
Author

The gist of how CF challenge works in pretty details - https://stackoverflow.com/a/60131975

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment