Clicker

Gaining Access

Nmap scan:

$ nmap -p- --min-rate 3000 10.129.70.56 
Starting Nmap 7.93 ( https://nmap.org ) at 2023-09-24 23:35 +08
Nmap scan report for 10.129.70.56
Host is up (0.043s latency).
Not shown: 65526 closed tcp ports (conn-refused)
PORT      STATE SERVICE
22/tcp    open  ssh
80/tcp    open  http
111/tcp   open  rpcbind
2049/tcp  open  nfs
38863/tcp open  unknown
41469/tcp open  unknown
43433/tcp open  unknown
47485/tcp open  unknown
58185/tcp open  unknown

Did a detailed scan too:

$ nmap -p 22,80,111,2049,38863,41469,43433,47485,58185 -sC -sV --min-rate 3000 10.129.70.56 
Starting Nmap 7.93 ( https://nmap.org ) at 2023-09-24 23:35 +08
Nmap scan report for 10.129.70.56
Host is up (0.011s latency).

PORT      STATE SERVICE  VERSION
22/tcp    open  ssh      OpenSSH 8.9p1 Ubuntu 3ubuntu0.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 89d7393458a0eaa1dbc13d14ec5d5a92 (ECDSA)
|_  256 b4da8daf659cbbf071d51350edd81130 (ED25519)
80/tcp    open  http     Apache httpd 2.4.52 ((Ubuntu))
|_http-title: Did not follow redirect to http://clicker.htb/
|_http-server-header: Apache/2.4.52 (Ubuntu)
111/tcp   open  rpcbind  2-4 (RPC #100000)
| rpcinfo: 
|   program version    port/proto  service
|   100000  2,3,4        111/tcp   rpcbind
|   100000  2,3,4        111/udp   rpcbind
|   100000  3,4          111/tcp6  rpcbind
|   100000  3,4          111/udp6  rpcbind
|   100003  3,4         2049/tcp   nfs
|   100003  3,4         2049/tcp6  nfs
|   100005  1,2,3      37311/udp   mountd
|   100005  1,2,3      47485/tcp   mountd
|   100005  1,2,3      51863/udp6  mountd
|   100005  1,2,3      53445/tcp6  mountd
|   100021  1,3,4      34639/udp   nlockmgr
|   100021  1,3,4      37758/udp6  nlockmgr
|   100021  1,3,4      43025/tcp6  nlockmgr
|   100021  1,3,4      43433/tcp   nlockmgr
|   100024  1          38863/tcp   status
|   100024  1          46781/tcp6  status
|   100024  1          49246/udp   status
|   100024  1          52153/udp6  status
|   100227  3           2049/tcp   nfs_acl
|_  100227  3           2049/tcp6  nfs_acl
2049/tcp  open  nfs_acl  3 (RPC #100227)
38863/tcp open  status   1 (RPC #100024)
41469/tcp open  mountd   1-3 (RPC #100005)
43433/tcp open  nlockmgr 1-4 (RPC #100021)
47485/tcp open  mountd   1-3 (RPC #100005)
58185/tcp open  mountd   1-3 (RPC #100005)

Lots of RPC ports, and NFS is open on port 2049. We can also add clicker.htb to the /etc/hosts file.

NFS -> Source Code

We can first check whether we can mount anything on NFS. A quick showmount shows that we can:

There's a backups directory to read, and we can mount it.

It seems that there's a zip file, and we can cp this to another directory and then unzip it to find some PHP code.

We probably need to do source code review later, but for now we can move on to enumerating the website itself.

Web Enumeration + Source Code Review

The website advertises a game:

There are some reviews left behind by users in the Info tab:

We might need these usernames. First, let's register a user and login to see what this game is about. As it turns out, this is just a cookie clicker:

Based on the source code, there doesn't seem to be a subdomain or hidden directory (yet), so let's take a look at it to find vulnerabilities. authenticate.php handles the user sessions:

This assigns a ROLE for the user. admin.php uses this ROLE variable:

The export.php code is another file that contains this 'Admin' check, meaning we probably need to somehow become the administrator of this site, and then abuse a vulnerability within that code later.

Within the diagnostic.php file, there's another check and its for the token this time:

I couldn't crack this hash, so I'll just take note of this for now. The save_game.php file contains some interesting stuff:

It seems that it checks the key-value pair for role, and prevents it from being modified. The save_profile function is from db_utils.php:

Admin Takeover

Based on the source code above, I'm pretty sure that the strtolower($key) check can be bypassed. Also, it looks really intentionally left there. If we can bypass it and add the Role parameter, we can update it with Admin since it's directly passed directly to $args[$key] = $value.

The only source I could find was this:

The above was for SQL Injection, and it shows how putting the characters in hex works. We can test this out using this request:

The above request returns a 302 instead of a 500 (which this machine does for errors), indicating that it worked! Now we just need to specify the value of 'Admin' in hex. For some reason, it only accepts "Admin" as a valid parameter. Since this is passed to the SQL database, I added a # character to the end to quote the rest of the query.

After re-login, we see this:

We are now the administrators!

Export RCE

Here's the rest of the export.php code:

There's a lot of things going on here. In short, there are 3 parts to it:

  • Accepts one extension POST value that is NOT SANITISED (we can indicate PHP!)

  • If we don't specify a .txt or a .json, it will create a HTML file for us and output it somewhere on the machine. Since there is no validation on the parameters being passed in, and we can specify any file extension we want, we could potentially inject PHP code onto the machine to get RCE.

To abuse this, we can easily change our nickname to a PHP payload using the same exploit to get admin. The code doesn't check for the nickname parameter, so we only need to URL encode our PHP payload.

Afterwards, we can send a POST request with the extension parameter.

From that .php file stored, check for RCE:

Then, we can get a reverse shell:

Privilege Escalation

jack is the user present, and cannot grab the user flag yet:

RE SUID Binary -> Arbitrary Read

I searched for all files on the system owned by this user.

Seems like the /opt directory is next. The README.txt file contains some interesting information:

The execute_query file is an ELF binary, and has SUID set for jack.

I transferred it back to my machine for some reverse engineering via ghidra. When decompiled, we can see how there are switch cases within the main function:

Firstly, I noticed that the .sql files DO NOT have absolute paths, meaning we could potentially do PATH hijacking. There's also some usage of the system function:

Interesting. When run on the machine, it just shows this:

It seems to print the contents of the file it is reading from. If we run strings on the binary, we can retrieve the exact command being used:

The above can be converted to:

The above command was taking input from somewhere, and I assume it's a file. When taking another look at the switch statements, I noticed that there was a default case, which basically controlled pcVar3, the same variable contains filenames from the other switch cases.

The variable also had limited space since calloc is used to allocate memory for it. Since the command is printing verbose output, I tried specifying other files / directories:

This worked! I tried reading the id_rsa file (since we are in /home/jack/queries) and it worked as well:

Using the above, we can ssh in as jack:

Sudo Privileges -> Root

I checked sudo privileges, and found that jack can execute monitor.sh as root:

Here's the script contents:

There's no PATH hijacking for this binary, and the script uses unset on some PATH variables, which sets them to nothing basically. When searching for env variable exploits for PERL5LIB and PERLLIB, I found this site:

Based on the above, setting PERL5OPT=-d and PERL5DB=system("sh");exit;, we can get a root shell. I tried it in the machine, and it worked!

Now, we can easily get a root shell:

Rooted!

Last updated