Commitment Issues

Published: April 3, 2024

Description

I accidentally wrote the flag down. Good thing I deleted it!

Download the challenge zip, unzip it locally, then change into the drop-in directory.

wget https://artifacts.picoctf.net/c_titan/77/challenge.zip && \
unzip challenge.zip && \
cd drop-in/

Solution

This is a successor to the Time Machine challenge. If you use `ls -a` in drop-in directory you can see the .git file which allows you to see the commits. Before looking at prior commits in the log there is a file called "message.txt" with the file contents of "TOP SECRET".
  1. Step 1List commits
    git log shows a commit labeled "create flag" with ID 3d5ec8a26ee7b092a1760fea18f384c35e435139.
    git log
    Learn more

    This challenge hinges on a fundamental misunderstanding many people have: deleting a file in git does not erase it from history. Git is a content-addressable store - every version of every file ever committed is permanently recorded in the .git/objects/ folder, even after you delete the file and make a new commit on top.

    When you run git log, git walks the chain of commits backwards from HEAD and prints each one. A commit labeled "create flag" followed by one that removes it is a classic pattern - the data lives in the earlier snapshot indefinitely.

    This is why you should never commit secrets to a repository, even "temporarily." Removing a secret in a follow-up commit does not protect it - anyone with access to the repo can checkout the earlier commit and read it. The only safe remediation is to rotate the secret and use git filter-repo to rewrite history (which requires force-pushing and coordinating with everyone who has a clone).

  2. Step 2Check out the flag commit
    Switch to that commit with checkout functionality and cat message.txt to see the flag.
    git checkout 3d5ec8a26ee7b092a1760fea18f384c35e435139 && \
    cat message.txt
    Learn more

    git checkout <hash> moves your working tree to the exact state the repository was in at that commit - all files present at that point are restored, and files added after it disappear. This puts you in "detached HEAD" state, meaning HEAD points directly to a commit rather than a branch name.

    You can explore freely in this state. To get back to the latest commit on your branch, just run git checkout main (or master).

    Beyond CTFs, this technique is used in real debugging: if you know a bug was introduced somewhere in the last 50 commits, git bisect automates binary-searching through history by doing exactly this - checking out midpoints until it isolates the culprit commit.

Flag

picoCTF{s@n1t1z3_30e86...}

Want more picoCTF 2024 writeups?

Useful tools for General Skills

Related reading

What to try next