# 4T$ CTF Writeup: Homelab ? More like Pwnlab !

In this Capture The Flag (CTF) challenge, we were given access to two main targets: `an SSH server running on a GoTTY shell` and `a NAS interface that allowed file uploads`. My initial analysis revealed two key pieces of information. First, the SSH server had two primary users, one of whom, the admin, had a flag in their home directory that they could only read.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1731339644298/b06404b7-086a-4f85-a319-f03d2f772562.png align="center")

Second, the NAS interface was vulnerable to insecure file uploads, which allowed us to replace existing templates with our files and execute commands through template injection, as the application was running with root privileges.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1731339983192/2eefc9c5-025a-4361-8e88-47c36e83fc60.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1731339564552/243e57de-e294-4f75-8b77-75d77e2afa82.png align="center")

With the plan to exploit the file upload vulnerability and perform template injection, our first step was to copy `/bin/bash` to a location accessible through the NAS server, specifically `/home/user/nas_storage` from the SSH shell and this would have been reachable form `/app/public/uploads` in NAS, where we could later manipulate it to execute commands with elevated privileges.

We executed the following command to place the binary in the nas\_storage directory:

```bash
cp /bin/bash /home/user/nas_storage
```

Since we have the file upload allowing us to write to arbitrary location, I crafted a template with JavaScript code that invoked child\_process to execute shell commands. The injected template contained the following payload:

```javascript
<%=import('child_process').then(c=>{console.log(c.execSync('chown+1000:1000+/app/public/uploads/bash').toString())})%>
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1731339732329/42116011-e6cb-44c2-855c-87273c174d16.png align="center")

We uploaded this template as `/app/views/index.ejs`, replacing the main template on the NAS interface, and then accessing the / route to trigger its execution. This action successfully executed the chown command, changing the ownership of bash to 1000:1000.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1731339778782/7b33e4f3-7e83-4fe2-aa8f-4e67cfea30bf.png align="center")

Verifying through SSH, we confirmed that the ownership change was applied as intended.

With ownership transferred to our target user, we proceeded to escalate privileges by setting the SUID bit on the bash binary, enabling it to execute with `admin` privileges. For this, we created another template injection payload:

```javascript
<%=import('child_process').then(c=>{console.log(c.execSync('chmod u+s app/public/uploads/bash').toString())})%>
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1731339818157/b94b2cfc-b549-41e7-aade-d2d794bf4f6e.png align="center")

We repeated the upload and execution process, using `/app/views/index.ejs` to set the SUID bit on our bash binary. Again, we confirmed the change through SSH, finding that the bash was now marked with the SUID bit.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1731339858242/3cec69fc-ffc8-44f8-8cfe-00be5d9efea9.png align="center")

At this point, we had a bash binary capable of executing as `admin`, which allowed us to retrieve the flag in the admin's directory. By running the following command, we initiated a root shell and accessed files restricted to the admin user:

```bash
cd nas_storage/
./bash -p
cat /home/admin/flag
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1731339919051/a9e73d67-15d4-4745-a594-607665a81ee6.png align="center")

**Reference:**

* [https://nodejs.org/api/path.html#pathbasenamepath-suffix](https://nodejs.org/api/path.html#pathbasenamepath-suffix)
