Funnel teaches one of the most practical real-world skills in penetration testing: SSH local port forwarding (tunnelling). The attack chain begins with an FTP server leaking credentials via anonymous access, uses those credentials for SSH login, then tunnels through the SSH connection to reach a PostgreSQL database that is only accessible from the local machine. This pattern — pivoting through an SSH session to reach internal services — is fundamental to internal network assessments.
| Skill | Why it matters |
|---|---|
| FTP anonymous access for credential discovery | Sensitive files left on FTP servers are a recurring real-world finding |
| Password policy document analysis | Default password patterns in internal documents are goldmines for credential attacks |
| SSH local port forwarding (-L flag) | Tunnelling makes internal-only services reachable from your attack machine |
| PostgreSQL enumeration via psql | Direct database access once tunnelled — listing schemas, tables, and extracting data |
What you're seeing: anonymous FTP with a directory called mail_backup — almost certainly containing sensitive internal data. SSH on port 22 is the pivot channel. PostgreSQL is only listening on localhost (127.0.0.1:5432) — not exposed externally.
What you find: a password_policy.pdf and a welcome email. The policy document reveals the company's default password format: funnel123#!#. The welcome email lists new user accounts including optimus, albert, andreas, christine, and maria.
Try the default password against each discovered username. Users who haven't changed their password will be accessible.
What you're seeing: PostgreSQL bound exclusively to 127.0.0.1 on port 5432. It's not reachable from the network — only from the machine itself. This is where SSH tunnelling becomes essential.
SSH local port forwarding creates a tunnel: traffic sent to a port on your machine is forwarded through the SSH connection and exits on the remote host to a specified destination.
This maps localhost:1337 on your attack machine to 127.0.0.1:5432 on the target. Keep this SSH session open.
| Tunnel type | Command | Use case |
|---|---|---|
| Local (-L) | ssh -L localport:remotehost:remoteport user@host | Reach a service on the remote network from your machine |
| Remote (-R) | ssh -R remoteport:localhost:localport user@host | Expose a local service to the remote machine |
| Dynamic (-D) | ssh -D localport user@host | SOCKS5 proxy — route all traffic through the SSH host |
| Background (-N -f) | ssh -N -f -L ... user@host | Run tunnel in background without an interactive shell |
| Command | What it does |
|---|---|
| \l | List all databases |
| \c <db> | Connect to a specific database |
| \dt | List tables in the current database |
| \d <table> | Describe table columns and types |
| SELECT * FROM <table>; | Return all rows |
| \du | List database users and roles |
| \q | Quit psql |
Internal services bound to 127.0.0.1 are not safe if an attacker can SSH into the host. SSH tunnelling makes any locally-listening service reachable from anywhere on the network.
| Concept | Real-world relevance |
|---|---|
| Default password documents on FTP | Internal onboarding files regularly contain default credentials — never leave them on open shares |
| SSH local port forwarding | Core pivoting technique in any internal pentest — used to reach databases, admin panels, and APIs bound to localhost |
| PostgreSQL on localhost only | Binding to 127.0.0.1 is a partial control — it fails the moment an attacker has SSH or shell access |
| Credential reuse across services | The same default password worked for SSH and PostgreSQL — credential reuse is a systemic risk |
