is an easy box released on April 8th, 2023 by kavigihan.
User Own
Nmap scan:
Starting Nmap 7.93 ( https://nmap.org ) at 2023-04-14 15:10 EDT
Nmap scan report for searcher.htb (10.10.11.208)
Host is up (0.17s latency).
Not shown: 998 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-server-header:
| Apache/2.4.52 (Ubuntu)
|_ Werkzeug/2.1.2 Python/3.10.6
|_http-title: Searcher
Service Info: 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 42.63 seconds
The box is running a website called Searcher.
Going to the website http://searcher.htb, we get the homepage. The website takes a search engine and a query, then generates a valid query for that website. Looking at the bottom of the page, the website uses Flask and Searchor.
Searchor is a CLI tool for generating search queries. Using the query --help shows this much.
Looking at the source code, we can see:
main.py
@click.argument("engine")
@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...")
if copy:
click.echo("link copied to clipboard")
except AttributeError:
print("engine not recognized")
The URL gets created in an eval, and the query parameter is wrapped in single quotes. This eval can be hijacked.
config contains credentials for cody. These credentials also work to login as svc through SSH.
sudo -l reveals:
Matching Defaults entries for svc on busqueda:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
User svc may run the following commands on busqueda:
(root) /usr/bin/python3 /opt/scripts/system-checkup.py *
Inside /opt/scripts:
-rwx--x--x 1 root root 586 Dec 24 21:23 check-ports.py
-rwx--x--x 1 root root 857 Dec 24 21:23 full-checkup.sh
-rwx--x--x 1 root root 3.3K Dec 24 21:23 install-flask.sh
-rwx--x--x 1 root root 1.9K Dec 24 21:23 system-checkup.py
Usage: /opt/scripts/system-checkup.py <action> (arg1) (arg2)
docker-ps : List running docker containers
docker-inspect : Inpect a certain docker container
full-checkup : Run a full system checkup
Output of full-checkup:
[=] Docker conteainers
{
"/gitea": "running"
}
{
"/mysql_db": "running"
}
[=] Docker port mappings
{
"22/tcp": [
{
"HostIp": "127.0.0.1",
"HostPort": "222"
}
],
"3000/tcp": [
{
"HostIp": "127.0.0.1",
"HostPort": "3000"
}
]
}
[=] Apache webhosts
[+] searcher.htb is up
[+] gitea.searcher.htb is up
[=] PM2 processes
┌─────┬────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
├─────┼────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
│ 0 │ app │ default │ N/A │ fork │ 1645 │ 19m │ 0 │ online │ 0% │ 30.1mb │ svc │ disabled │
└─────┴────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘
[+] Done!
MySQL and a new subdomain, gitea.searcher.htb. Adding that to /etc/hosts leads to a Gitea page. The login credentials for cody from before work, but there is nothing of interest.
Output of docker-inspect after checking the config of MySQL:
The administrator account of Gitea can be logged into with MYSQL_PASSWORD. This gives us the previously inaccessible source code of the scripts in /opt/scripts.
The source code of system-checkup.py can help us figure out how to exploit it. In the condition for full-checkup:
system-checkup.py runs full-checkup.sh, but only grabs the relative file. This means a custom bash script with the name full-checkup.sh can be run in a different directory. Putting a reverse shell in the custom bash script will give us access to root.