Web


Nmap initially discovered that the service running on port 3000 is Apache Hadoop It later turned out to be wrong as it showed a web server built on Node.js

Webroot It is indeed a web application It also appears to be a custom website

wappalyzer also identified the technologies involved AngularJS 1.6.5 Express Node.js

There is a section that displays new members These are potential usernames tom mark rastating

There are files embedded to those photo, pointing to their profiles located at the /profile/ directory

The login button leads to /login

/login


It is a login page; /login I tried some basic SQLi as well as default/weak credentials None of them works

Interception


While poking around to see if there is any potential vulnerabilities that I can exploit, I discovered something very strange.

When I sent a GET request to the webroot and intercept it

The website first

  • responses with a 304
  • requests the browser to load /partials/home.html

Upon forwarding, the highlighted gets loaded. It must be the/partials/home.html file

Then the web server

  • responses with a 304 again
  • requests the browser to load /api/users/latest

Upon intercepting the request to /api/users/latest/, the web server responses with this This must be the API for users. It’s a JSON data and it contains what appears to be password hashes

And those users gets loaded when I forward the intercepted request above

This is the whole structure crawled by Burp Suite I can see the /api/users/latest file

I these password hashes to Hashcat for cracking

It also shows that none of these users are admin

Password Cracking

tom


┌──(kali㉿kali)-[~/archive/htb/labs/node]
└─$ hashcat -a 0 -m 1400 hash/tom.hash /usr/share/wordlists/rockyou.txt
hashcat (v6.2.6) starting
 
Hashes: 1 digests; 1 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
Rules: 1
 
Dictionary cache hit:
* Filename..: /usr/share/wordlists/rockyou.txt
* Passwords.: 14344385
* Bytes.....: 139921507
* Keyspace..: 14344385
 
f0e2e750791171b0391b682ec35835bd6a5c3f7c8d1d0191451ec77b4d75f240:spongebob
 
Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 1400 (SHA2-256)
Hash.Target......: f0e2e750791171b0391b682ec35835bd6a5c3f7c8d1d0191451...75f240
Time.Started.....: Wed Jan 18 21:34:56 2023 (1 sec)
Time.Estimated...: Wed Jan 18 21:34:57 2023 (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........:   435.3 kH/s (0.15ms) @ Accel:256 Loops:1 Thr:1 Vec:8
Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
Progress.........: 768/14344385 (0.01%)
Rejected.........: 0/768 (0.00%)
Restore.Point....: 0/14344385 (0.00%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1
Candidate.Engine.: Device Generator
Candidates.#1....: 123456 -> james1
Hardware.Mon.#1..: Util: 48%
 
Started: Wed Jan 18 21:34:55 2023
Stopped: Wed Jan 18 21:34:58 2023

Password hash cracked for tom spongebob

mark


┌──(kali㉿kali)-[~/archive/htb/labs/node]
└─$ hashcat -a 0 -m 1400 hash/mark.hash /usr/share/wordlists/rockyou.txt
hashcat (v6.2.6) starting
 
hashes: 1 digests; 1 unique digests, 1 unique salts
bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
rules: 1
 
dictionary cache hit:
* filename..: /usr/share/wordlists/rockyou.txt
* passwords.: 14344385
* bytes.....: 139921507
* keyspace..: 14344385
 
de5a1adf4fedcce1533915edc60177547f1057b61b7119fd130e1f7428705f73:snowflake
 
session..........: hashcat
status...........: Cracked
hash.mode........: 1400 (SHA2-256)
hash.target......: de5a1adf4fedcce1533915edc60177547f1057b61b7119fd130...705f73
time.started.....: Wed Jan 18 21:35:06 2023 (0 secs)
time.estimated...: Wed Jan 18 21:35:06 2023 (0 secs)
kernel.feature...: Pure Kernel
guess.base.......: File (/usr/share/wordlists/rockyou.txt)
guess.queue......: 1/1 (100.00%)
speed.#1.........:  1485.4 kH/s (0.15ms) @ Accel:256 Loops:1 Thr:1 Vec:8
recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
progress.........: 1536/14344385 (0.01%)
rejected.........: 0/1536 (0.00%)
restore.point....: 768/14344385 (0.01%)
restore.sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1
candidate.engine.: Device Generator
candidates.#1....: football1 -> mexico1
hardware.mon.#1..: Util: 41%
 
started: Wed Jan 18 21:35:05 2023
stopped: Wed Jan 18 21:35:08 2023

Password hash cracked for mark snowflake

rastating


┌──(kali㉿kali)-[~/archive/htb/labs/node]
└─$ hashcat -a 0 -m 1400 hash/rastating.hash /usr/share/wordlists/rockyou.txt 
hashcat (v6.2.6) starting
 
Hashes: 1 digests; 1 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
Rules: 1
 
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......: 5065db2df0d4ee53562c650c29bacf55b97e231e3fe88570abc...8ac2f0
Time.Started.....: Wed Jan 18 21:35:23 2023 (7 secs)
Time.Estimated...: Wed Jan 18 21:35:30 2023 (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........:  2169.8 kH/s (0.12ms) @ Accel:256 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[2121216a696d212121] -> $HEX[042a0337c2a156616d6f732103]
Hardware.Mon.#1..: Util: 46%
 
Started: Wed Jan 18 21:35:22 2023
Stopped: Wed Jan 18 21:35:32 2023

Hashcat was unable to crack rastating’s password hash

Validating


Now that I cracked the password hashes for tom and mark, I will validate the credentials by attempting to login

I was able to log in to the website as tom but there isn’t much to check.

Same goes for mark as well.

Broken Access Control


While I was validating the credentials, I had some interesting discoveries JSON data for the POST request

It requests to load the /partials/admin.html

and it showed this, due to both user not having the admin access

But that’s not the case, if I navigate to the file itself. There is a button to download backup

However, I am unable to download it as the button doesn’t work.

Admin


Looking back at /api/users/latest, it shows 3 users. yet none of them are admin

But the web server displays another user if I change the URL to /api/users/ The myP14ceAdm1nAcc0uNT user is admin

┌──(kali㉿kali)-[~/archive/htb/labs/node]
└─$ hashcat -a 0 -m 1400 hash/myP14ceAdm1nAcc0uNT.hash /usr/share/wordlists/rockyou.txt
hashcat (v6.2.6) starting
 
hashes: 1 digests; 1 unique digests, 1 unique salts
bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
rules: 1
 
dictionary cache hit:
* filename..: /usr/share/wordlists/rockyou.txt
* passwords.: 14344385
* bytes.....: 139921507
* keyspace..: 14344385
 
dffc504aa55359b9265cbebe1e4032fe600b64475ae3fd29c07d23223334d0af:manchester
                                                          
session..........: hashcat
status...........: Cracked
hash.mode........: 1400 (SHA2-256)
hash.target......: dffc504aa55359b9265cbebe1e4032fe600b64475ae3fd29c07...34d0af
time.started.....: Wed Jan 18 22:57:20 2023 (0 secs)
time.estimated...: Wed Jan 18 22:57:20 2023 (0 secs)
kernel.feature...: Pure Kernel
guess.base.......: File (/usr/share/wordlists/rockyou.txt)
guess.queue......: 1/1 (100.00%)
speed.#1.........:   699.4 kH/s (0.13ms) @ Accel:256 Loops:1 Thr:1 Vec:8
recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
progress.........: 768/14344385 (0.01%)
rejected.........: 0/768 (0.00%)
restore.point....: 0/14344385 (0.00%)
restore.sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1
candidate.engine.: Device Generator
candidates.#1....: 123456 -> james1
hardware.mon.#1..: Util: 40%
 
started: Wed Jan 18 22:57:19 2023
stopped: Wed Jan 18 22:57:22 2023
 

Password hash cracked for myP14ceAdm1nAcc0uNT The password is manchester

Successfully authenticated and logged as myP14ceAdm1nAcc0uNT The button is available

backup


┌──(kali㉿kali)-[~/…/htb/labs/node/webapp]
└─$ file myplace.backup
myplace.backup: ASCII text, with very long lines (65536), with no line terminators

It shows that the file contains a lot of texts

┌──(kali㉿kali)-[~/…/htb/labs/node/webapp]
└─$ cat myplace.backup
 
[...REDACTED...]
 
3L215cGxhY2Uvc3RhdGljL3BhcnRpYWxzL2FkbWluLmh0bWxVVAUAAyv1q1l1eAsAAQQAAAAABAAAAABQSwECHgMUAAkACABAASJLCYNSgUABAADFAgAAKgAYAAAAAAABAAAAtIED8CUAdmFyL3d3dy9teXBsYWNlL3N0YXRpYy9wYXJ0aWFscy9sb2dpbi5odG1sVVQFAAPH6KlZdXgLAAEEAAAAAAQAAAAAUEsBAh4DFAAJAAgACWUiSzCQGVICAgAANwUAACkAGAAAAAAAAQAAALSBt/ElAHZhci93d3cvbXlwbGFjZS9zdGF0aWMvcGFydGlhbHMvaG9tZS5odG1sVVQFAAOimKpZdXgLAAEEAAAAAAQAAAAAUEsBAh4DFAAJAAgATWUiSyhsx/IUAQAAFAIAACwAGAAAAAAAAQAAALSBLPQlAHZhci93d3cvbXlwbGFjZS9zdGF0aWMvcGFydGlhbHMvcHJvZmlsZS5odG1sVVQFAAMimapZdXgLAAEEAAAAAAQAAAAAUEsBAh4DFAAJAAgAfWMiS4Tw22u4BAAAFQ8AABgAGAAAAAAAAQAAALSBtvUlAHZhci93d3cvbXlwbGFjZS9hcHAuaHRtbFVUBQADvpWqWXV4CwABBAAAAAAEAAAAAFBLBQYAAAAAXwNfA3edAQDQ+iUAAAA=

It appears to be a very long line of Base64 string

┌──(kali㉿kali)-[~/…/htb/labs/node/webapp]
└─$ cat myplace.backup | base64 -d > myplace.backup.decoded 
 
┌──(kali㉿kali)-[~/…/htb/labs/node/webapp]
└─$ cat myplace.backup.decoded
 
[...REDACTED...]
 
EB /  1  mpr r @    #   T   ~W	G  }⯯Cd\
 Io+     x^  nb  k $R    1(  ?CX^U ^PfN 
  z H 8n.  1   CP @ Ed                  2 ! /~ SFW
 gmLkj  ݅ mCnM  ӇE P*fҺ] `   C"0cS}
 
[...REDACTED...]

So I decode it and it now appears to be in binary format

┌──(kali㉿kali)-[~/…/htb/labs/node/webapp]
└─$ file myplace.backup.decoded 
myplace.backup.decoded: Zip archive data, at least v1.0 to extract, compression method=store

It’s a ZIP archive. Of course. This is a backup for the webserver

┌──(kali㉿kali)-[~/…/htb/labs/node/webapp]
└─$ unzip myplace.backup.decoded 
Archive:  myplace.backup.decoded
   creating: var/www/myplace/
[myplace.backup.decoded] var/www/myplace/package-lock.json password:

The archive is password-protected.

┌──(kali㉿kali)-[~/…/htb/labs/node/webapp]
└─$ zip2john myplace.backup.decoded                        
ver 1.0 myplace.backup.decoded/var/www/myplace/ is not encrypted, or stored with non-handled compression type
ver 2.0 efh 5455 efh 7875 myplace.backup.decoded/var/www/myplace/package-lock.json PKZIP Encr: TS_chk, cmplen=4404, decmplen=21264, crc=37EF7D4C ts=0145 cs=0145 type=8
 
[...REDACTED...]
 
myplace.backup.decoded:$pkzip$8*1*1*0*0*11*2938*bf16bd5431e58bc8db90e47c2afb489c1b*1*0*0*17*996a*8f22db1e59bdf34f2857338c52ec0ba43f5bda58c9e545*1*0*0*19*5083*3eee568417a1ddf4f5f3996dcd2f7e84f6d90b3f6a65ea870b*1*0*0*1f*b16f*fcab91b9df57c2b8060c3d8693a829a2cdda6452f6a3e21f5e68ea0aeeabb3*1*0*0*24*a3cc*3e97e0bb3a6870ee867a75141340305f46b60eb09581b09d395c54e089ca09039bf4867f*1*0*8*24*5083*27df6b4d9a909a4e3ae441e2623615dfc26b3cf7e609d635bd1e0a4bceffeb6713b4ac0b*1*0*0*24*9679*f852cfa1cc264209b9d2f3b8e5989203857e573e78156b3be7ad5d718e46fdd82a997032*2*0*11*5*118f1dfc*94cb*67*0*11*3d0f*d60277fc480569b0652682aaccac54024a*$/pkzip$::myplace.backup.decoded:var/www/myplace/node_modules/qs/.eslintignore, var/www/myplace/node_modules/express/node_modules/qs/.eslintignore, var/www/myplace/node_modules/string_decoder/.npmignore, var/www/myplace/node_modules/isarray/.npmignore, var/www/myplace/node_modules/ipaddr.js/.npmignore, var/www/myplace/node_modules/cookie-signature/.npmignore, var/www/myplace/node_modules/isarray/.travis.yml, var/www/myplace/node_modules/debug/node.js:myplace.backup.decoded
NOTE: It is assumed that all files in each archive have the same password.
If that is not the case, the hash may be uncrackable. To avoid this, use
option -o to pick a file at a time.

So I tried converting the archive to crack-able hash with zip2john. It showed a lot of errors, mostly related to the files inside not having the same configuration for compression. $pkzip$8*1*1*0*0*11*2938*bf16bd5431e58bc8db90e47c2afb489c1b*1*0*0*17*996a*8f22db1e59bdf34f2857338c52ec0ba43f5bda58c9e545*1*0*0*19*5083*3eee568417a1ddf4f5f3996dcd2f7e84f6d90b3f6a65ea870b*1*0*0*1f*b16f*fcab91b9df57c2b8060c3d8693a829a2cdda6452f6a3e21f5e68ea0aeeabb3*1*0*0*24*a3cc*3e97e0bb3a6870ee867a75141340305f46b60eb09581b09d395c54e089ca09039bf4867f*1*0*8*24*5083*27df6b4d9a909a4e3ae441e2623615dfc26b3cf7e609d635bd1e0a4bceffeb6713b4ac0b*1*0*0*24*9679*f852cfa1cc264209b9d2f3b8e5989203857e573e78156b3be7ad5d718e46fdd82a997032*2*0*11*5*118f1dfc*94cb*67*0*11*3d0f*d60277fc480569b0652682aaccac54024a*$/pkzip$ But I got one at the bottom. I removed myplace.backup.decoded at the both end with : because that would be for john I want to crack the hash with Hashcat

┌──(kali㉿kali)-[~/…/htb/labs/node/webapp]
└─$ hashcat -a 0 -m 17225 myplace.hash /usr/share/wordlists/rockyou.txt
 
hashcat (v6.2.6) starting
 
Hashes: 1 digests; 1 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
Rules: 1
 
Dictionary cache hit:
* Filename..: /usr/share/wordlists/rockyou.txt
* Passwords.: 14344385
* Bytes.....: 139921507
* Keyspace..: 14344385
 
$pkzip$8*1*1*0*0*11*2938*bf16bd5431e58bc8db90e47c2afb489c1b*1*0*0*17*996a*8f22db1e59bdf34f2857338c52ec0ba43f5bda58c9e545*1*0*0*19*5083*3eee568417a1ddf4f5f3996dcd2f7e84f6d90b3f6a65ea870b*1*0*0*1f*b16f*fcab91b9df57c2b8060c3d8693a829a2cdda6452f6a3e21f5e68ea0aeeabb3*1*0*0*24*a3cc*3e97e0bb3a6870ee867a75141340305f46b60eb09581b09d395c54e089ca09039bf4867f*1*0*8*24*5083*27df6b4d9a909a4e3ae441e2623615dfc26b3cf7e609d635bd1e0a4bceffeb6713b4ac0b*1*0*0*24*9679*f852cfa1cc264209b9d2f3b8e5989203857e573e78156b3be7ad5d718e46fdd82a997032*2*0*11*5*118f1dfc*94cb*67*0*11*3d0f*d60277fc480569b0652682aaccac54024a*$/pkzip$:magicword
                                                          
Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 17225 (PKZIP (Mixed Multi-File))
Hash.Target......: $pkzip$8*1*1*0*0*11*2938*bf16bd5431e58bc8db90e47c2a...pkzip$
Time.Started.....: Wed Jan 18 23:20:23 2023 (0 secs)
Time.Estimated...: Wed Jan 18 23:20:23 2023 (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........:  2091.9 kH/s (0.13ms) @ Accel:256 Loops:1 Thr:1 Vec:8
Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
Progress.........: 183552/14344385 (1.28%)
Rejected.........: 0/183552 (0.00%)
Restore.Point....: 182784/14344385 (1.27%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1
Candidate.Engine.: Device Generator
Candidates.#1....: mandy33 -> laroya
Hardware.Mon.#1..: Util: 37%
 
Started: Wed Jan 18 23:20:08 2023
Stopped: Wed Jan 18 23:20:25 2023

Hashcat cracked the password hash for the archive The password is magicword

┌──(kali㉿kali)-[~/…/htb/labs/node/webapp]
└─$ unzip myplace.backup.decoded 
Archive:  myplace.backup.decoded
   creating: var/www/myplace/
[myplace.backup.decoded] var/www/myplace/package-lock.json password: magicword
  inflating: var/www/myplace/package-lock.json
 
[...REDACTED...]

I put the password and extracted the content from the archive

┌──(kali㉿kali)-[~/…/htb/labs/node/webapp]
└─$ du -h ./var
 
[...REDACTED...]
 
8.9M	./var

About 8.9Mb worth of data was extracted. It’s the whole app

┌──(kali㉿kali)-[~/…/webapp/var/www/myplace]
└─$ ll
total 56K
4.0K drwxr-xr-x  3 kali kali 4.0K Jan 18 23:21 ..
4.0K drwxr-xr-x  4 kali kali 4.0K Aug 16 18:08 .
8.0K -rw-rw-r--  1 kali kali 7.9K Sep  3  2017 app.js
4.0K -rw-rw-r--  1 kali kali 3.8K Sep  2  2017 app.html
4.0K drwxr-xr-x 69 kali kali 4.0K Sep  2  2017 node_modules
 24K -rw-r--r--  1 kali kali  21K Sep  2  2017 package-lock.json
4.0K drwxrwxr-x  6 kali kali 4.0K Sep  2  2017 static
4.0K -rw-rw-r--  1 kali kali  283 Sep  2  2017 package.json

The app.js file is the main file.

There is a SQL connection string for connecting to the myplace DB in the backend MongoDB it contains a credential mark:5AYRft73VtFpc84k

There is also a variable named, backup_key,

This must be the function used to backup the web server. I can see that the function is calling a binary located at /usr/local/bin/backup The binary is then executed with the backup_key in the argument

For now, I will test the credential for password reuse