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()。
拉取主页面与外部脚本:
$ curl -s -b "$HTS_COOKIE" \ -H "Referer: https://www.hackthissite.org/missions/javascript/6/" \ "https://www.hackthissite.org/missions/javascript/6/" -o lvl6.html$ curl -s -b "$HTS_COOKIE" \ -H "Referer: https://www.hackthissite.org/missions/javascript/6/" \ "https://www.hackthissite.org/missions/javascript/6/checkpass.js" -o checkpass.jsRawrRawr = "moo";function check(x) { "+RawrRawr+" == "hack_this_site"; if (x == "" + RawrRawr + "") { alert("Rawr! win!"); window.location = "about:blank"; } else { alert("Rawr, nope, try again!"); }}
function checkpassw(moo) { RawrRawr = moo; checkpass(RawrRawr);}check() 里那条 "+RawrRawr+" == "hack_this_site" 是一条无副作用的裸表达式语句,about:blank 分支也永远不会给站点送出密码:表单并不调用 check()。真正的入口是 checkpassw(moo) → checkpass(RawrRawr),而 checkpass 定义在外部文件里。这正是题面说的忘了删掉没用的代码。
dairycow = "moo";moo = "pwns";rawr = "moo";
function checkpass(pass) { if (pass == rawr + " " + moo) { alert("How did you do that??? Good job!"); window.location = "../../../missions/javascript/6/?lvl_password=" + pass; } else { alert("Nope, try again"); }}决定性的比较是 pass == rawr+" "+moo:rawr="moo"、moo="pwns",中间夹一个空格字面量 " "。dairycow="moo" 在本文件里没被使用
从抓下来的 checkpass.js 里把变量逐个读出来再按比较式拼接:
#!/usr/bin/env python3"""Recover the JavaScript Mission 6 password from the external script.
index.php loads /missions/javascript/6/checkpass.js; the winning comparisonthere is pass == rawr+" "+moo with dairycow="moo", rawr="moo", moo="pwns".
The inline check() (RawrRawr / "hack_this_site" / about:blank) is dead code;the form calls checkpassw() which forwards to the external checkpass().The password is exactly "rawr + ' ' + moo" -- the single space included."""import reimport urllib.parse
def main(): js = open("checkpass.js", encoding="utf-8", errors="replace").read() vals = dict(re.findall(r'(\w+)\s*=\s*"([^"]*)"', js)) missing = {name for name in ("rawr", "moo") if name not in vals} if missing: raise SystemExit("missing required assignment(s): " + ", ".join(sorted(missing))) password = "%s %s" % (vals["rawr"], vals["moo"]) print("rawr :", vals["rawr"]) print("moo :", vals["moo"]) print("password :", repr(password)) print("query : lvl_password=" + urllib.parse.quote(password))
if __name__ == "__main__": main()$ uv run python decode6.pyrawr : moomoo : pwnspassword : 'moo pwns'query : lvl_password=moo%20pwns