Home Bitlab - Hack The Box
Post
Cancel

Bitlab - Hack The Box

I solved this gitlab box the unintended way by exploiting the git pull command running as root and using git post-merge hooks to execute code as root. I was able to get a root shell using this method but I still had to get an initial shell by finding the gitlab credentials in some obfuscated javascript and modifying PHP code in the repo to get RCE.

Summary

  • Find javascript obfuscated credentials in bookmarks.html
  • Use creds to gain access to the profile repo and modify it to get PHP RCE
  • Get root access using the unintended method of git post-merge hooks

Portscan

The portscan shows SSH and HTTP ports open along with entries from robots.txt indicating this is a Gitlab service. Iโ€™ll check out a couple of the URIs mentioned below in the next section.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
root@kali:~/htb/bitlab# nmap -sC -sV -T4 10.10.10.114
Starting Nmap 7.80 ( https://nmap.org ) at 2019-09-08 09:49 EDT
Nmap scan report for bitlab.htb (10.10.10.114)
Host is up (0.022s latency).
Not shown: 998 filtered ports
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 \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 https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 13.33 seconds

Gitlab enumeration

I already knew that the box was going to contain a Gitlab service based on the box name and the logo. The box was originally submitted as Gitlab but was renamed to Bitlab before launch.

I clicked the Explore link at the bottom of the page to look for repos but I didnโ€™t see any repositories that are publicly accessible.

I checked a few links from the robots.txt file and found a profile page for Clave:

Thatโ€™s not a default page in Gitlab so Iโ€™ll keep that in mind for later.

Hardcoded Gitlab credentials

I initially skipped the Help section but when I went back and clicked on the link, I got the following page:

The Gitlab Login link doesnโ€™t link to an HTTP URL but contains obfuscated javascript:

1
javascript:(function(){ var _0x4b18=["\x76\x61\x6C\x75\x65","\x75\x73\x65\x72\x5F\x6C\x6F\x67\x69\x6E","\x67\x65\x74\x45\x6C\x65\x6D\x65\x6E\x74\x42\x79\x49\x64","\x63\x6C\x61\x76\x65","\x75\x73\x65\x72\x5F\x70\x61\x73\x73\x77\x6F\x72\x64","\x31\x31\x64\x65\x73\x30\x30\x38\x31\x78"];document[_0x4b18[2]](_0x4b18[1])[_0x4b18[0]]= _0x4b18[3];document[_0x4b18[2]](_0x4b18[4])[_0x4b18[0]]= _0x4b18[5]; })()

I executed the Javascript in NodeJS and found credentials for Clave:

Credentials: clave / 11des0081x

Also, if you copy/paste the entire Javascript code snippet in the Firefox dev console when youโ€™re on the Gitlab login page itโ€™ll auto populate both username and password field.

I can now log in to the Gitlab portal and I see two repositories that I have access to:

I have read/write access to the Profile repo but only read access to Deployer.

As per Gitlabโ€™s documentation, these are the permissions available:

Guest - No access to code Reporter - Read the repository Developer - Read/Write to the repository Maintainer - Read/Write to the repository + partial administrative capabilities Owner - Read/Write to the repository + full administrative capabilities

Getting RCE through the Profile page

The Profile repository contains the webpage for the Profile page I found earlier. I see that itโ€™s running PHP so if I can modify this page I should be able to gain remote code execution by adding a reverse shell on the page.

The Deployer repo code is a simple PHP script that expects a specific JSON message then does a git pull. I assume thisโ€™ll be used to deploy the Profile page when I commit changes to the repo.

The repo is deployed in the root of the directory and I can access it with /deployer:

Iโ€™ll add a PHP reverse shell in the Profile index.php page that triggers when I have a shell parameter present. Then I submit the merge request and merge it after.

Iโ€™ll craft the proper POST request with the Repeater function in Burp Suite. The JSON message has to match the exact format from the code I found in the repo.

Now that the profile page has been updated, I can trigger the reverse shell by sending a request with the shell parameter:

Unintended privilege escalation to root

The www-data user can execute git pull as root:

1
2
3
4
5
6
7
$ sudo -l
Matching Defaults entries for www-data on bitlab:
    env_reset, exempt_group=sudo, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User www-data may run the following commands on bitlab:
    (root) NOPASSWD: /usr/bin/git pull
$

Git has hooks that can be used to execute code after commit, push, merge, etc. Iโ€™ll use that to get remote execution as root through the git pull command. The https://www.git-scm.com/docs/githooks#_post_merge documentation says:

This hook is invoked by git-merge[1], which happens when a git pull is done on a local repository.

First, Iโ€™ll create two local repos: foo will be merged into the bar repo. Iโ€™ll add a reverse shell in the post-merge hook of the bar repo where bar will be merged into.

Then Iโ€™ll do an initial commit in the foo repo and set up bar to pull from the foo repo:

And finally Iโ€™ll do a new commit in foo so I can initiate a merge from foo and trigger the reverse shell:

This post is licensed under CC BY 4.0 by the author.