HackThisSite - JavaScript Mission 4

Challenge

Faith is trying to trick you.... The checker has a dead comparison that looks like the answer; the real password is a one-line variable.

第四关页面开头写着 Faith is trying to trick you...(Faith 意在误导)。校验函数里有一行看似答案的废弃比较,真正的密码只是一个变量。

Solution

用带登录态的会话取关卡页:

1
2
$ curl -s -b 'HackThisSite=<mission-cookie>' \
'https://www.hackthissite.org/missions/javascript/4/'

页面里的校验函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
RawrRawr = "moo";
function check(x)
{
""+RawrRawr+"" == "hack_this_site";
if (x == ""+RawrRawr+"")
{
alert("Rawr! win!");
window.location = "../../../missions/javascript/4/?lvl_password="+x;
}
else
{
alert("Rawr, fail.");
}
}

为什么这段 JS 能被绕过

  • RawrRawr = "moo" 是全局赋值,值就写在源码里。
  • ""+RawrRawr+"" == "hack_this_site";干扰语句。它确实计算了一个字符串拼接("" + "moo" + "" 得到 "moo"),也确实拿它和 "hack_this_site" 做了比较,但这个比较的布尔结果被直接丢弃、没有赋给任何变量、也没有参与后面的 if。用 Node 单独跑这一行就能看到它恒为 false
1
2
$ node -e 'var RawrRawr = "moo"; console.log(""+RawrRawr+"" == "hack_this_site")'
false
  • 真正生效的条件是下一行的 if (x == ""+RawrRawr+"")"" + RawrRawr + "" 只是把变量转成字符串,结果还是 "moo",所以比较等价于 x == "moo"。与空串拼接不会改变值:这是题目用来混淆视觉的,不是用来加密的。
1
2
$ node -e 'var RawrRawr = "moo"; function check(x){ return x == ""+RawrRawr+""; } console.log(check("moo"))'
true
  • 放行动作是把 x 拼进 URL 回跳:window.location = "../../../missions/javascript/4/?lvl_password="+x。和前面几关一样,客户端只负责拼 URL,拼接结果完全可以手工构造。

Submit

1
2
3
$ curl -s -b 'HackThisSite=<mission-cookie>' \
-e 'https://www.hackthissite.org/missions/javascript/4/' \
'https://www.hackthissite.org/missions/javascript/4/?lvl_password=moo'

服务端靠 Referer 判断请求来自关卡页:不带 Referer 时不计完成,带上关卡页地址后即计入完成。提交后 profile 的 Javascript 列表出现本关完成标记,账号积分 6501 → 6669(七关合计)。

moo