HackThisSite - JavaScript Mission 6
Challenge
Fiftysixer decided to try his hand at javascript! All was going well until he realized that he forgot to remove the unused code, which resulted in a confusing mess. He didn't mind, in fact, he did his best to make it even MORE confusing!
Find the password:
索引名
go go away .js,难度 Weird。主页面只留一段自相矛盾的误导脚本,真正的比较藏在外部文件checkpass.js里。
Solution
- 关卡页
https://www.hackthissite.org/missions/javascript/6/通过<script src="/missions/javascript/6/checkpass.js"></script>引入外部脚本。 - 页面内联脚本故意留下大量未使用且自相矛盾的代码:
check()里出现"hack_this_site"字面量和跳向about:blank的分支,这些都被真链路旁置。 - 表单真正调用的是内联的
checkpassw(this.value),它把输入写进RawrRawr再调用外部脚本里的checkpass()。
拉取主页面与外部脚本:
1 | $ curl -s -b "$HTS_COOKIE" \ |
1 | RawrRawr = "moo"; |
check() 里那条
"+RawrRawr+" == "hack_this_site"
是一条无副作用的裸表达式语句,about:blank
分支也永远不会给站点送出密码:表单并不调用
check()。真正的入口是 checkpassw(moo) →
checkpass(RawrRawr),而 checkpass
定义在外部文件里。这正是题面说的忘了删掉没用的代码。
1 | dairycow="moo"; |
决定性的比较是
pass == rawr+" "+moo:rawr="moo"、moo="pwns",中间夹一个空格字面量
" "。dairycow="moo"
在本文件里没被使用,和主页面的 check() 一样是烟雾弹。
从抓下来的 checkpass.js
里把变量逐个读出来再按比较式拼接:
1 | #!/usr/bin/env python3 |
1 | $ uv run python decode6.py |
密码里带一个空格,所以回跳 URL 中它会被编码成
moo%20pwns(window.location
赋值时浏览器也会自动做这一步)。
机制与第 5 关一致:客户端比较通过后
window.location = ".../6/?lvl_password="+pass
回跳,由服务端在这一次请求上记账。curl 复现必须带关卡 Referer,URL
里的空格写成 %20:
1 | $ curl -s -o /dev/null -w '%{http_code}\n' -b "$HTS_COOKIE" \ |
接受证据:个人资料列出
Javascript: (1) (2) (3) (4) (5) (6) (7),积分为通关前的
6501 升到 Master (6669 Points)。
1 | $ curl -s -b "$HTS_COOKIE" "https://www.hackthissite.org/user/view/<account>/" -o prof.html |
状态:verified(live 通关并已计入 profile)。
Vulnerabilities
密码逻辑分散在主页面的内联脚本和外部 checkpass.js
两处,但两处都在客户端、都无条件下发。把校验拆到多个脚本、再掺入大量死代码和自相矛盾的语句,只是混淆而不是保护:只要能读到全部脚本(它们本来就是交给浏览器的),把执行路径顺着
<script>
标签走一遍就能还原真比较。修复方向依旧是服务端校验:客户端脚本可以被任意读取、改写和重放,任何留在里面的常量都等于公开。