Busqueda
Executive summary — Busqueda exposes a Flask application that builds search-engine URLs on top of the Searchor 2.4.0 library, vulnerable to CVE-2023-43364 (
eval()injection). The unusual part — and the most instructive lesson of the box — is that the application's own code is correct: it validates the engine against a whitelist and runs the subprocess with an argument list, withoutshell=True. The flaw isn't in that code; it's in the dependency declared inrequirements.txt, invisible to any review of the application's own source. From there, a.git/mistakenly deployed to production and three separate password reuses chain the access all the way to asudoscript that invokes another script through a relative path — the one thingsudonever sanitizes is the working directory.
| Platform | Hack The Box |
| Operating system | Linux |
| Difficulty | Easy |
| Status | Retired |
| Target IP | 10.129.228.217 |
Attack map
[80] searcher.htb — Flask "Searcher" app, builds search-engine URLs
│ the footer declares the dependency: Searchor 2.4.0
▼
[RCE] CVE-2023-43364 — Searchor interpolates the query into an f-string, then eval()s it
│ the app's own code is correct (subprocess with an argument list, no shell=True);
│ the flaw lives one layer down, in the dependency
▼
[RCE] svc (unauthenticated command execution, via an HTTP return channel)
│ /var/www/app/.git/config (mistakenly deployed) leaks Gitea credentials:
│ cody:jh1usoih2bkjaspwe92 — the same password works for system SSH
▼
[SSH] svc (user.txt)
│ sudo (root) /usr/bin/python3 /opt/scripts/system-checkup.py *
│ unrestricted docker-inspect leaks the Gitea DB password, reused as the Gitea
│ admin password -> source code confirms a relative path: system-checkup.py
│ invokes './full-checkup.sh'
▼
[ROOT] attacker-controlled CWD + relative path -> our own full-checkup.sh runs
as root (root.txt)
1. Reconnaissance
nmap -p- --min-rate 5000 -T4 -Pn -oN nmap-allports.txt 10.129.228.217
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
Not shown: 65290 closed tcp ports (reset), 243 filtered tcp ports (no-response)
The 243 "filtered" ports are an artifact of the aggressive --min-rate (nmap warns it hit the retransmission cap), not a selective firewall. Real surface: two ports, and the vector has to be on 80.
nmap -sCV -p22,80 -Pn -oN nmap-services.txt 10.129.228.217
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
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
OpenSSH 8.9p1 + Apache 2.4.52 pins the OS to Ubuntu 22.04 LTS. More useful still: the line Did not follow redirect to http://searcher.htb/ reveals the vhost name with no fuzzing needed — Apache hands it over for free by redirecting on plain IP access. That cheap check is worth running before firing thousands of ffuf requests.
With no sudo password on the attacking box to edit /etc/hosts, resolution was handled with curl --resolve, which injects the resolution at the request level without touching the system:
#!/bin/bash
# c.sh — curl against searcher.htb without touching /etc/hosts
exec curl -s --resolve searcher.htb:80:10.129.228.217 "$@"
The app (./c.sh http://searcher.htb/) looks harmless: a POST /search form with three parameters (engine, query, auto_redirect) that builds the chosen engine's search URL. The decisive finding comes from reading the full HTML, not just the visible part — the footer voluntarily declares its main dependency:
<p class="copyright">Powered by
<a href="https://flask.palletsprojects.com">Flask</a> and
<a href="https://github.com/ArjunSharda/Searchor">Searchor 2.4.0</a></p>
No need to guess the stack or infer it from behavior: the app states outright which library processes user input, and which version. And Searchor 2.4.0 has a known, critical vulnerability: CVE-2023-43364.
Resumen ejecutivo — Busqueda expone una aplicación Flask que construye URLs de búsqueda apoyándose en la biblioteca Searchor 2.4.0, vulnerable a CVE-2023-43364 (inyección en
eval()). Lo poco habitual — y lo más instructivo de la máquina — es que el código de la aplicación es correcto: valida el motor contra una lista blanca y ejecuta el subproceso con lista de argumentos, sinshell=True. El fallo no está en ese código, sino en la dependencia que declara enrequirements.txt, invisible a cualquier revisión del propio código. A partir de ahí, un.git/desplegado por error en producción y tres reutilizaciones de contraseña encadenan el acceso hasta un script desudoque invoca otro script mediante una ruta relativa — la única variable quesudonunca sanea es el directorio de trabajo.
| Plataforma | Hack The Box |
| Sistema operativo | Linux |
| Dificultad | Easy |
| Estado | Retired |
| IP objetivo | 10.129.228.217 |
Mapa del ataque
[80] searcher.htb — app Flask "Searcher", construye URLs de búsqueda
│ el pie de página declara la dependencia: Searchor 2.4.0
▼
[RCE] CVE-2023-43364 — Searchor interpola la query en un f-string y lo pasa a eval()
│ el código de la app es correcto (subprocess con lista de args, sin shell=True);
│ el fallo vive una capa más abajo, en la dependencia
▼
[RCE] svc (ejecución de comandos sin autenticación, vía canal de retorno HTTP)
│ /var/www/app/.git/config (desplegado por error) filtra credenciales de Gitea:
│ cody:jh1usoih2bkjaspwe92 — la misma contraseña sirve para SSH del sistema
▼
[SSH] svc (user.txt)
│ sudo (root) /usr/bin/python3 /opt/scripts/system-checkup.py *
│ docker-inspect sin restricciones filtra la contraseña de la BD de Gitea,
│ reutilizada como la del admin de Gitea -> código fuente del script confirma
│ una ruta relativa: system-checkup.py invoca './full-checkup.sh'
▼
[ROOT] CWD controlado por el atacante + ruta relativa -> nuestro full-checkup.sh
se ejecuta como root (root.txt)
1. Reconocimiento
nmap -p- --min-rate 5000 -T4 -Pn -oN nmap-allports.txt 10.129.228.217
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
Not shown: 65290 closed tcp ports (reset), 243 filtered tcp ports (no-response)
Los 243 puertos "filtered" son un artefacto del --min-rate agresivo (nmap avisa de que ha agotado los reintentos), no un firewall selectivo. Superficie real: dos puertos, y el vector tiene que estar en el 80.
nmap -sCV -p22,80 -Pn -oN nmap-services.txt 10.129.228.217
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
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
La combinación OpenSSH 8.9p1 + Apache 2.4.52 fija el sistema operativo en Ubuntu 22.04 LTS. Y algo más útil: la línea Did not follow redirect to http://searcher.htb/ revela el nombre de vhost sin necesidad de fuzzing — Apache lo entrega gratis al redirigir por defecto desde el acceso por IP. Conviene comprobar siempre este caso barato antes de lanzar miles de peticiones de ffuf.
Sin permisos de sudo en la máquina atacante para editar /etc/hosts, se resolvió con curl --resolve, que inyecta la resolución a nivel de petición sin tocar el sistema:
#!/bin/bash
# c.sh — curl contra searcher.htb sin tocar /etc/hosts
exec curl -s --resolve searcher.htb:80:10.129.228.217 "$@"
La aplicación (./c.sh http://searcher.htb/) es un buscador de apariencia inofensiva: un formulario POST /search con tres parámetros (engine, query, auto_redirect) que construye la URL de búsqueda del motor elegido. El hallazgo decisivo aparece leyendo el HTML completo, no solo la parte visible — el pie de página declara voluntariamente su dependencia principal:
<p class="copyright">Powered by
<a href="https://flask.palletsprojects.com">Flask</a> and
<a href="https://github.com/ArjunSharda/Searchor">Searchor 2.4.0</a></p>
No hace falta adivinar la tecnología ni deducirla por comportamiento: la app dice literalmente qué biblioteca procesa la entrada del usuario y en qué versión. Y Searchor 2.4.0 tiene una vulnerabilidad conocida y crítica: CVE-2023-43364.
This content is Root Access only. Everything else on the site — the free tier, the whole public library — stays open.
See Root Access plansNo account? Create one free then upgrade from your console.
Este contenido es solo para Root Access. Todo lo demás del sitio — el nivel gratuito, toda la biblioteca pública — sigue abierto.
Ver planes de Root Access¿Sin cuenta? Crea una gratis y luego mejora desde tu consola.