Git Happens

The intro to Git Happens is pretty vague, but we at least know that we're looking to exploit version control in some way, shape or form.

This was a really fun CTF. Involves exploiting a poorly set up Git. Took me a couple of hours to do it, but rewarding in the end.

Task #1 Capture the Flag

Lets start out by finding what services are open on the deployed box.


kali@kali:~$ nmap -A
Starting Nmap 7.80 ( ) at 2020-09-02 20:44 EDT
Nmap scan report for
Host is up (0.032s latency).
Not shown: 999 closed ports
80/tcp open  http    nginx 1.14.0 (Ubuntu)
| http-git: 
|     Git repository found!
|_    Repository description: Unnamed repository; edit this file 'description' to name the...
|_http-server-header: nginx/1.14.0 (Ubuntu)
|_http-title: Super Awesome Site!
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at .
Nmap done: 1 IP address (1 host up) scanned in 8.73 seconds

nmap gives us two interesting things:

  • Port 80 is open
  • .. and there's an open git repo

Lets check out whats on port 80 first

There's a basic login screen.

image 108

With a Javascript function that's run onclick, called login().

image 109

The function is likely nestled in the obfuscated JS code in the script tags.

Even when "prettifying" the script, there's little to glean from it, immediately at least.

image 110

However, I did notice a reference to admin as an element in the obfuscated const array. Perhaps a potential username?

Lets skip over to the .git repo we found in the nmap scan earlier.

Browse to the http-git repo

image 107

There's a bunch of files here, lets attempt to clone the repo to our machine.

kali@kali:~/Desktop/TryHackMe/git-happens$ git clone git-happens-clone
Cloning into 'git-happens-clone'...
fatal: repository '' not found

Turns out we've found out what's wrong with the git repo...

Lets dig into the repository and see if we can recover anything interesting.

image 111

In the logs folder you'll find refs and then heads, master. I downloaded this file, then found a git repo tucked away in it.

image 113

I attempted to clone this.

kali@kali:~/Desktop/TryHackMe/git-happens$ git clone hydragum
Cloning into 'hydragum'...
remote: HTTP Basic: Access denied
fatal: Authentication failed for ''

And HTTP basic failed..

It was at this point I realised this was the wrong path, after I saw this was the username of the person that made the room -.-

image 114

However, I did check out some more files. And /.git/refs/heads/master turned some type of hash.

image 115

Ran this through hashid and found out it's a SHA1 hash.

kali@kali:~$ hashid d0b3578a628889f38c0affb1b75457146a4678e5
Analyzing 'd0b3578a628889f38c0affb1b75457146a4678e5'
[+] SHA-1 
[+] Double SHA-1 
[+] RIPEMD-160 
[+] Haval-160 
[+] Tiger-160 
[+] HAS-160 
[+] LinkedIn 
[+] Skein-256(160) 
[+] Skein-512(160) 

Let's run it through hashcat and see if there's anything that popups against the /usr/share/wordlists/rockyou.txt wordlist on kali.

kali@kali:~$ hashcat -m 100 d0b3578a628889f38c0affb1b75457146a4678e5 /usr/share/wordlists/rockyou.txt 
hashcat (v6.1.1) starting...

And this, unfortunately, failed.

Approaching final keyspace - workload adjusted.  
Session..........: hashcat                       
Status...........: Exhausted
Hash.Name........: SHA1
Hash.Target......: d0b3578a628889f38c0affb1b75457146a4678e5
Time.Started.....: Wed Sep  2 21:35:14 2020 (10 secs)
Time.Estimated...: Wed Sep  2 21:35:24 2020 (0 secs)
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........:  1384.9 kH/s (0.60ms) @ Accel:1024 Loops:1 Thr:1 Vec:8
Recovered........: 0/1 (0.00%) Digests
Progress.........: 14344385/14344385 (100.00%)
Rejected.........: 0/14344385 (0.00%)
Restore.Point....: 14344385/14344385 (100.00%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1
Candidates.#1....: $HEX[206b72697374656e616e6e65] -> $HEX[042a0337c2a156616d6f732103]
Started: Wed Sep  2 21:34:44 2020
Stopped: Wed Sep  2 21:35:26 2020

Download the .git folder

I used wget -r to recursively download the files on the site.

Then, I try to git checkout the master branch.

kali@kali:~/Desktop/TryHackMe/git-happens/test/$ git checkout master
D       .gitlab-ci.yml
D       Dockerfile
D       dashboard.html
D       default.conf
Already on 'master'

This leaked some information about some files in the directory. So I browser to each of the files in firefox.

The file kinda signalled this was the right track.

image 118
image 119

I also saw there's a dashboard.html file.

At first, I didn't notice the quick redirect, but, there is one... I'll try screenshot it before it redirects us to the index.html page...

image 120

I want to see the page, so I ran it through wget. There may be some un-obfuscated check for some cookie set when the user passes in the correct password.

kali@kali:~/Desktop/TryHackMe/git-happens/test/$ wget -r
--2020-09-02 22:30:01--
Connecting to connected.
HTTP request sent, awaiting response... 200 OK
Length: 3775 (3.7K) [text/html]
Saving to: ‘’      100%[====================================================>]   3.69K  --.-KB/s    in 0s      
2020-09-02 22:30:01 (19.6 MB/s) - ‘’ saved [3775/3775]

But unfortunately it's just as obfuscated on this dashboard side..

image 121

Some of the files aren't accessible. And have the status code D when we run git checkout master.

Lets try rollback these actions with the git restore command.

This, did get the files back, but no flag, yet.

So I ran git log to look at the history of the commits.

kali@kali:~/Desktop/TryHackMe/git-happens/test/$ git log                                                                                                            
commit d0b3578a628889f38c0affb1b75457146a4678e5 (HEAD -> master, tag: v1.0)                                                                                                    
Author: Adam Bertrand <>                                                                                                                                   
Date:   Thu Jul 23 22:22:16 2020 +0000                                                                                                                                         
    Update .gitlab-ci.yml                                                                                                                                                      
commit 77aab78e2624ec9400f9ed3f43a6f0c942eeb82d                                                                                                                                
Author: Hydragyrum <>
Date:   Fri Jul 24 00:21:25 2020 +0200
    add gitlab-ci config to build docker file.
commit 2eb93ac3534155069a8ef59cb25b9c1971d5d199
Author: Hydragyrum <>
Date:   Fri Jul 24 00:08:38 2020 +0200
    setup dockerfile and setup defaults.
commit d6df4000639981d032f628af2b4d03b8eff31213
Author: Hydragyrum <>
Date:   Thu Jul 23 23:42:30 2020 +0200
    Make sure the css is standard-ish!
commit d954a99b96ff11c37a558a5d93ce52d0f3702a7d
Author: Hydragyrum <>
Date:   Thu Jul 23 23:41:12 2020 +0200
    re-obfuscating the code to be really secure!
commit bc8054d9d95854d278359a432b6d97c27e24061d
Author: Hydragyrum <>
Date:   Thu Jul 23 23:37:32 2020 +0200
    Security says obfuscation isn't enough.
    They want me to use something called 'SHA-512'
commit e56eaa8e29b589976f33d76bc58a0c4dfb9315b1
Author: Hydragyrum <>
Date:   Thu Jul 23 23:25:52 2020 +0200
    Obfuscated the source code.
    Hopefully security will be happy!
commit 395e087334d613d5e423cdf8f7be27196a360459
Author: Hydragyrum <>
Date:   Thu Jul 23 23:17:43 2020 +0200
    Made the login page, boss!
commit 2f423697bf81fe5956684f66fb6fc6596a1903cc
Author: Adam Bertrand <>
Date:   Mon Jul 20 20:46:28 2020 +0000
    Initial commit

Perhaps we can rollback to a commit before the obfuscation? This might be possible, but, one of the commits also states the hash is SHA-512. In a previous step, we'd only tested SHA-1..

Rolling back git

Lets stick with the rollbacks.

We can use the command git revert, and fingers crossed, we might be able to roll back to before the obfuscation. Thank god I'm not debugging the obfuscated code..

At first the revert command didn't work.

kali@kali:~/Desktop/TryHackMe/git-happens/test/$ git revert bc8054d9d95854d278359a432b6d97c27e24061d
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
error: could not revert bc8054d... Security says obfuscation isn't enough.
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'

But thankfully, there are other options. I used git reset --hard instead.

kali@kali:~/Desktop/TryHackMe/git-happens/test/$ git reset --hard bc8054d9d95854d278359a432b6d97c27e24061d
HEAD is now at bc8054d Security says obfuscation isn't enough.

And when cat is ran on index.html, we can see the unobfuscated script. But, with a hashed password.

kali@kali:~/Desktop/TryHackMe/git-happens/test/$ cat index.html 


      async function login() {
        let form = document.getElementById("login-form");
        let username = form.elements["username"].value;
        let passwordHash = await digest(form.elements["password"].value);
        if (
          username === 'admin' &&
          passwordHash === '4004c23a71fd6ba9b03ec9cb7eed08471197d84319a865c5442a9d6a7c7cbea070f3cb6aa5106ef80f679a88dbbaf89ff64cb351a151a5f29819a3c094ecebbb'
        ) {
          document.cookie = "login=1";
          window.location.href = "/dashboard.html";
        } else {
          document.getElementById("error").innerHTML =

      async function digest(password) {
          const encoder = new TextEncoder();
          const data = encoder.encode(`${password}SaltyBob`);
          const hashBuffer = await crypto.subtle.digest('SHA-512', data);
          const hashArray = Array.from(new Uint8Array(hashBuffer));                     // convert buffer to byte array
          const hashHex = => b.toString(16).padStart(2, '0')).join('');
          return hashHex;

I'd purposely not gone to far back. incase there was something important. And there are some things into this commit that are of interest. Namely:

username === 'admin'
passwordHash === '4004c23a71fd6ba9b03ec9cb7eed08471197d84319a865c5442a9d6a7c7cbea070f3cb6aa5106ef80f679a88dbbaf89ff64cb351a151a5f29819a3c094ecebbb'

The cookie for login..

document.cookie = "login=1";
window.location.href = "/dashboard.html";

And the salt?

const data = encoder.encode(`${password}SaltyBob`);

But lets rollback a little further. To commit e56eaa8e29b589976f33d76bc58a0c4dfb9315b1

kali@kali:~/Desktop/TryHackMe/git-happens/test/$ git reset --hard e56eaa8e29b589976f33d76bc58a0c4dfb9315b1
HEAD is now at e56eaa8 Obfuscated the source code.

Feels like we're getting closer to a clear text answer.

image 122
image 123
Zoomed in because can't see.

With some instinctive brain pattern spotting, these words popped out to me as a potential answer.

But, I'm committed to seeing it in cleartext. Lets goto the commit where the login page was first put together.

kali@kali:~/Desktop/TryHackMe/git-happens/test/$ git reset --hard 395e087334d613d5e423cdf8f7be27196a360459
HEAD is now at 395e087 Made the login page, boss!

And there it was, in all its glory.

image 124


image 125

Leave a Comment

Your email address will not be published. Required fields are marked *