Busqueda is an Easy HackTheBox machine.

  • Foothold: Searchor CVE
  • Privesc: Python script executed as root by relative path

Port Scan

Nmap scan revealed only two services, of which HTTP on 80 looks like the only exploitable one, so let’s go ahead with that. Port 80 redirects us to searcher.htb, so don’t forget to add that to the hosts file.

Searcher

The Searchor service seems to just be a search engine aggregator of sorts, with the option to directly redirect to the selected search engine.

The bottom of the page shows that the Searchor executable used by this service is on version 2.4.0, which is vulnerable to command injection:

The vulnerability is caused by an unsafe eval that uses unsanitized user input. While the engine parameter does not seem to be injectable through Burp Suite, query definitely is. Do note that you cannot eval multiple statements, so try to make a reverse shell a simple function call (imports can be done as an expression through __import__('<module>')).

@click.argument("query")
def search(engine, query, open, copy):
    try:
        url = eval(
            f"Engine.{engine}.search('{query}', copy_url={copy}, open_web={open})"
        )
        click.echo(url)
        searchor.history.update(engine, query, url)
        if open:
            click.echo("opening browser...")
# ...

Getting the reverse shell should be easy:

Upgrading the terminal (see here)… stty raw -echo never seems to work with fish shell, so I always switch to bash to launch netcat listeners.

I had to reset the box because another HTB user ran chmod +s /bin/bash without cleaning up after themself. I was originally surprised how easy that privesc was, then I thought there’s no way an active HTB box uses such an easy privesc vector in 2023, not even for Easy boxes.

LinPEAS had a stroke on this machine (even after the reset), mistakenly saying that I have write permissions to many system paths and configurations. Well, I didn’t find anything useful out of LinPEAS, except that there’s also a gitea server on gitea.searcher.htb, which prompted me to look for .git/config files. It turns out the web app itself has a .git directory, which reveals the gitea credentials of cody:

The credential can be used to login into the gitea server, but there’s nothing there except the web app. I didn’t find any gitea CVE of the currently running version either, so I thought this might’ve been reused somewhere, and indeed it was reused as the svc user’s password, which allows us to sudo:

The system-checkup script provides three subcommands. The first two didn’t really seem injectable, but the third one looks odd as it didn’t work:

What’s weird is that once we cd into the scripts directory, it becomes functional again:

This suggests that perhaps the system-checkup.py script tries to execute a full-checkup.sh not relative to its own directory, but to the working directory. Well, /var/www/app contains nothing of that sort, so that’s why it failed earlier. This gives us an opportunity to make a fake full-checkup.sh that sends us a reverse shell (setuid bash wouldn’t work since all the tmpfs have all been mounted with nosuid).

We got root:

Just for curiosity’s sake, I checked the /opt/scripts directory for git config, but there isn’t any administrator credentials within the file:

… and the system-checkup.py script indeed uses relative paths:

# ...
    elif action == 'full-checkup':
        try:
            arg_list = ['./full-checkup.sh']
            print(run_command(arg_list))
            print('[+] Done!')
        except:
            print('Something went wrong')
            exit(1)
# ...