Challenge Info
Spoiler
Artifacts Provided
- Illumination.JS/ — a Discord bot’s project folder, including a
.gitdirectory.
No remote instance, no interaction — just a git repository to dig through.
Analysis
Recon — the bot’s source
ls -la on the artifact immediately shows a .git folder — this is a git repository, not just a bare source dump, so its history is fair game.
bot.js is a small Discord bot built on discord.js and the Philips Hue API — it logs in by base64-decoding a token pulled straight from config.json:
| |
But the current config.json on disk doesn’t hold a real token:
| |
That placeholder string obviously isn’t valid base64 either — so the real token has to be sitting somewhere in the project’s history instead.
Solution — walking the git log
| |
commit edc5aabf933f6bb161ceca6cf7d0d2160ce333ec (HEAD -> master)
Added some whitespace for readability!
commit 47241a47f62ada864ec74bd6dedc4d33f4374699
Thanks to contributors, I removed the unique token as it was a security risk. Thanks for reporting responsibly!
commit ddc606f8fa05c363ea4de20f31834e97dd527381
Added some more comments for the lovely contributors! Thanks for helping out!
commit 335d6cfe3cdc25b89cae81c50ffb957b86bf5a4a
Moving to Git, first time using it. First Commit!
The commit message on 47241a47f62ada864ec74bd6dedc4d33f4374699 gives it away — that’s the one that swapped the real token out for the placeholder. git show on it prints the diff directly:
| |
| |
Same value shows up just as easily by going straight to the repo’s root instead — git show 335d6cfe3cdc25b89cae81c50ffb957b86bf5a4a (the very first commit) dumps the original config.json in full, token included, since that’s the commit that added the file before anyone thought to strip it.
Either way, the recovered string is SFRCe3YzcnNpMG5fYzBudHIwbF9hbV9JX3JpZ2h0P30= — base64-decode it and it is the flag:
| |
Spoiler
HTB{v3rsi0n_c0ntr0l_am_I_right?}Full chain
Illumination.JS/ (git repo)
└─ bot.js — logs in via base64(config.token)
└─ config.json (HEAD) — token replaced with a placeholder string
└─ git log — flags the commit that removed it
└─ git show <commit> — diff/full-file reveals the original base64 token
└─ base64-decode → FLAG
git commit/push doesn’t unsend anything — deleting a secret from the working tree just adds a new commit on top of it; the blob is still sitting in .git/objects, reachable from any earlier ref. Anyone who clones the repo (or just runs git log/git show against it) can walk straight back to it. The only real fix once a secret lands in history is revocation, not a follow-up commit.