Skip to content

HTB_Sau: Pentration Testing Report

Nameitem
PlatformOSCP Play Ground
Date2025-07-29 09:37:48
AuthBlackwin
Tools usednmap; ffuf;
Key wordsCVE-2023–27163;Maltrail v0.53; Systemd LPE
Ip address10.10.11.224
Flagroot.txt: 25a4d7147fa2ee8aa1b6d12253b323e5user.txt: da145dbcc8f5f4cf4d26b423815b765b

1. Initial Reconasission

Port scanning

  • rustscan -a 10.10.11.224 --scripts none --ulimit 5000 | tee scans/rustscan
  • sudo nmap -sCV -p22,55555 10.10.11.224 -oN scans/nmap
  • sudo nmap -sCV -p- --open 10.10.11.224 -oN scans/nmap-all
  • nmap -p- --min-rate 10000 10.10.11.224

PORT      STATE SERVICE VERSION
22/tcp    open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 aa:88:67:d7:13:3d:08:3a:8a:ce:9d:c4:dd:f3:e1:ed (RSA)
|   256 ec:2e:b1:05:87:2a:0c:7d:b1:49:87:64:95:dc:8a:21 (ECDSA)
|_  256 b3:0c:47:fb:a2:f2:12:cc:ce:0b:58:82:0e:50:43:36 (ED25519)
55555/tcp open  http    Golang net/http server
| http-title: Request Baskets
|_Requested resource was /web
| fingerprint-strings: 
|   FourOhFourRequest: 
|     HTTP/1.0 400 Bad Request
|     Content-Type: text/plain; charset=utf-8
|     X-Content-Type-Options: nosniff
|     Date: Tue, 29 Jul 2025 13:39:13 GMT
|     Content-Length: 75
|     invalid basket name; the name does not match pattern: ^[wd-_\.]{1,250}$
|   GenericLines, Help, LPDString, RTSPRequest, SIPOptions, SSLSessionReq, Socks5: 
|     HTTP/1.1 400 Bad Request
|     Content-Type: text/plain; charset=utf-8
|     Connection: close
|     Request
|   GetRequest: 
|     HTTP/1.0 302 Found
|     Content-Type: text/html; charset=utf-8
|     Location: /web
|     Date: Tue, 29 Jul 2025 13:38:57 GMT
|     Content-Length: 27
|     href="/web">Found</a>.
|   HTTPOptions: 
|     HTTP/1.0 200 OK
|     Allow: GET, OPTIONS
|     Date: Tue, 29 Jul 2025 13:38:57 GMT
|     Content-Length: 0
|   OfficeScan: 
|     HTTP/1.1 400 Bad Request: missing required Host header
|     Content-Type: text/plain; charset=utf-8
|     Connection: close
|_    Request: missing required Host header

all TCp scan

2. Enumeration

Web Enum

default page request-baskets | Version: 1.2.1

generate a bucket

what's Request Baskets? https://github.com/darklynx/request-baskets

Request Baskets is a web service to collect arbitrary HTTP requests and inspect them via RESTful API or simple web UI. It is strongly inspired by ideas and application design of the RequestHub project and reproduces functionality offered by RequestBin service.

directory brute found nothing interesting.

3. Initial Shell

equipmented with infomation: request-baskets 1.2.1, I search for vulns and found this: https://github.com/advisories/GHSA-58g2-vgpg-335q

request-baskets up to v1.2.1 was discovered to contain a Server-Side Request Forgery (SSRF) via the component /api/baskets/{name}. This vulnerability allows attackers to access network resources and sensitive information via a crafted API request.

POC:https://github.com/entr0pie/CVE-2023-27163/blob/main/README.md

try to make a proxy with kali it's displaied the responder, but I don't known how to use this. When I look for help online and found 80 port is opening, and I can use it , then this time, when I access the site generated by poc script, I see the normal pages

Maltrail (v0.53) https://github.com/spookier/Maltrail-v0.53-Exploit

About Unauthenticated OS Command Injection

The service uses the subprocess.check_output() function to execute a shell command that logs the username provided by the user. If an attacker provides a specially crafted username, they can inject arbitrary shell commands that will be executed on the server

4. Post-Enumeration

upgrade shell

get flag: da145dbcc8f5f4cf4d26b423815b765b

sudo -l

server.py

python
#!/usr/bin/env python

"""
Copyright (c) 2014-2023 Maltrail developers (https://github.com/stamparm/maltrail/)
See the file 'LICENSE' for copying permission
"""

from __future__ import print_function  # Requires: Python >= 2.6

import sys

sys.dont_write_bytecode = True

import optparse
import os
import platform
import threading
import time
import traceback

from core.common import check_connection
from core.common import check_sudo
from core.common import get_ex_message
from core.common import patch_parser
from core.httpd import start_httpd
from core.log import create_log_directory
from core.log import log_error
from core.log import start_logd
from core.settings import config
from core.settings import read_config
from core.settings import CHECK_CONNECTION_MAX_RETRIES
from core.settings import CONFIG_FILE
from core.settings import HOMEPAGE
from core.settings import IS_WIN
from core.settings import NAME
from core.settings import VERSION
from core.update import update_ipcat
from core.update import update_trails
from thirdparty import six

def main():
    print("%s (server) #v%s {%s}\n" % (NAME, VERSION, HOMEPAGE))

    if "--version" in sys.argv:
        raise SystemExit

    parser = optparse.OptionParser(version=VERSION)
    parser.add_option("-c", dest="config_file", default=CONFIG_FILE, help="configuration file (default: '%s')" % os.path.split(CONFIG_FILE)[-1])
    parser.add_option("--debug", dest="debug", action="store_true", help=optparse.SUPPRESS_HELP)

    patch_parser(parser)

    options, _ = parser.parse_args()

    print("[*] starting @ %s\n" % time.strftime("%X /%Y-%m-%d/"))

    read_config(options.config_file)

    if options.debug:
        config.SHOW_DEBUG = True

    if six.PY2 and config.USE_SSL:
        try:
            __import__("OpenSSL")
        except ImportError:
            if IS_WIN:
                sys.exit("[!] please install 'pyopenssl' (e.g. 'pip install pyopenssl')")
            else:
                msg = "[!] please install 'pyopenssl'"

                for distros, install in {("fedora", "centos"): "sudo yum install pyOpenSSL", ("debian", "ubuntu"): "sudo apt-get install python-openssl"}.items():
                    for distro in distros:
                        if distro in (platform.uname()[3] or "").lower():
                            msg += " (e.g. '%s')" % install
                            break

                sys.exit(msg)

        if not config.SSL_PEM or not os.path.isfile(config.SSL_PEM):
            hint = "openssl req -new -x509 -keyout %s -out %s -days 365 -nodes -subj '/O=%s CA/C=EU'" % (config.SSL_PEM or "server.pem", config.SSL_PEM or "server.pem", NAME)
            sys.exit("[!] invalid configuration value for 'SSL_PEM' ('%s')\n[?] (hint: \"%s\")" % (config.SSL_PEM, hint))

    def update_timer():
        retries = 0
        while retries < CHECK_CONNECTION_MAX_RETRIES and not check_connection():
            sys.stdout.write("[!] can't update because of lack of Internet connection (waiting..." if not retries else '.')
            sys.stdout.flush()
            time.sleep(10)
            retries += 1

        if retries:
            print(")")

        if retries == CHECK_CONNECTION_MAX_RETRIES:
            print("[x] going to continue without online update")
            _ = update_trails(offline=True)
        else:
            _ = update_trails()
            update_ipcat()

        thread = threading.Timer(config.UPDATE_PERIOD, update_timer)
        thread.daemon = True
        thread.start()

    if config.UDP_ADDRESS and config.UDP_PORT:
        if config.UDP_PORT <= 1024 and not config.DISABLE_CHECK_SUDO and check_sudo() is False:
            sys.exit("[!] please run '%s' with root privileges when using 'UDP_ADDRESS' configuration value" % __file__)

        create_log_directory()
        start_logd(address=config.UDP_ADDRESS, port=config.UDP_PORT, join=False)

    try:
        if config.USE_SERVER_UPDATE_TRAILS:
            update_timer()

        start_httpd(address=config.HTTP_ADDRESS, port=config.HTTP_PORT, pem=config.SSL_PEM if config.USE_SSL else None, join=True)
    except KeyboardInterrupt:
        print("\r[x] stopping (Ctrl-C pressed)")

if __name__ == "__main__":
    code = 0

    try:
        main()
    except SystemExit as ex:
        if isinstance(get_ex_message(ex), six.string_types) and get_ex_message(ex).strip('0'):
            print(get_ex_message(ex))
            code = 1
    except IOError:
        log_error("\n\n[!] session abruptly terminated\n[?] (hint: \"https://stackoverflow.com/a/20997655\")")
        code = 1
    except Exception:
        msg = "\r[!] unhandled exception occurred ('%s')" % sys.exc_info()[1]
        msg += "\n[x] please report the following details at 'https://github.com/stamparm/maltrail/issues':\n---\n'%s'\n---" % traceback.format_exc()
        log_error("\n\n%s" % msg.replace("\r", ""))

        print(msg)
        code = 1
    finally:
        if not any(_ in sys.argv for _ in ("--version", "-h", "--help")):
            print("\n[*] ending @ %s" % time.strftime("%X /%Y-%m-%d/"))

        os._exit(code)

5. Root Shell

6. What learned

https://gist.github.com/A1vinSmith/78786df7899a840ec43c5ddecb6a4740

⚠️ 内容仅供学习交流使用 | 本站访问量