mirror of
https://github.com/trustedsec/hate_crack.git
synced 2026-07-28 14:47:22 -07:00
fix(hashview): correct hash-type parsing for MD5 and hashfile listing
get_hashfile_details used 'or' fallthrough on hash_type, so MD5
(hash_type 0, falsy) resolved to the envelope 'type' string
('message') instead of 0. Select by key presence and drop the
bogus 'type' fallback.
get_hashfile_hash_type looked for file_ids/ids/hashfile_ids keys
that the endpoint never returns; it always yielded []. Read the
actual 'hashfiles' envelope array and extract each file id.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
df3554e077
commit
61b197f10e
+20
-7
@@ -1138,7 +1138,13 @@ class HashviewAPI:
|
||||
data = None
|
||||
hashtype = None
|
||||
if data:
|
||||
hashtype = data.get("hashtype") or data.get("hash_type") or data.get("type")
|
||||
# Prefer explicit hash-type keys by PRESENCE, not truthiness: MD5 is
|
||||
# hash_type 0, which is falsy. Never fall back to `type` — that is
|
||||
# the envelope tag ("message"), never a hash mode.
|
||||
if "hash_type" in data:
|
||||
hashtype = data["hash_type"]
|
||||
elif "hashtype" in data:
|
||||
hashtype = data["hashtype"]
|
||||
if self.debug:
|
||||
print(
|
||||
f"[DEBUG] get_hashfile_details({hashfile_id}): raw data={data}, hashtype={hashtype}"
|
||||
@@ -1660,21 +1666,28 @@ class HashviewAPI:
|
||||
def get_hashfile_hash_type(self, hashtype_id):
|
||||
"""
|
||||
Query /v1/hashfiles/hash_type/<int:hashtype_id> and return a list of file IDs.
|
||||
|
||||
The endpoint answers with an envelope ``{..., "hashfiles": [ {...} ]}``
|
||||
(native JSON objects); we extract the ``id`` of each hashfile.
|
||||
"""
|
||||
url = f"{self.base_url}/v1/hashfiles/hash_type/{hashtype_id}"
|
||||
resp = self.session.get(url)
|
||||
resp.raise_for_status()
|
||||
try:
|
||||
data = resp.json()
|
||||
# Expecting a list of file IDs or a dict with a key containing them
|
||||
# A bare list is tolerated for forward/backward compatibility.
|
||||
if isinstance(data, list):
|
||||
return data
|
||||
hashfiles = data
|
||||
elif isinstance(data, dict):
|
||||
# Try common keys
|
||||
for key in ("file_ids", "ids", "hashfile_ids"):
|
||||
if key in data and isinstance(data[key], list):
|
||||
return data[key]
|
||||
hashfiles = data.get("hashfiles") or []
|
||||
else:
|
||||
return []
|
||||
ids = []
|
||||
for hf in hashfiles:
|
||||
hf_id = hf.get("id") if isinstance(hf, dict) else hf
|
||||
if hf_id is not None:
|
||||
ids.append(hf_id)
|
||||
return ids
|
||||
except Exception:
|
||||
return []
|
||||
|
||||
|
||||
@@ -196,6 +196,49 @@ class TestHashviewAPI:
|
||||
result = api.list_customers()
|
||||
assert result["customers"] == [{"id": 2, "name": "Beta"}]
|
||||
|
||||
def test_get_hashfile_details_md5_zero(self, api):
|
||||
"""hash_type 0 (MD5) is falsy; must not fall through to the envelope `type`."""
|
||||
mock_resp = Mock()
|
||||
mock_resp.json.return_value = {
|
||||
"hash_type": 0,
|
||||
"msg": "OK",
|
||||
"status": 200,
|
||||
"type": "message",
|
||||
}
|
||||
mock_resp.raise_for_status = Mock()
|
||||
api.session.get.return_value = mock_resp
|
||||
|
||||
details = api.get_hashfile_details(42)
|
||||
assert details["hashtype"] == 0
|
||||
|
||||
def test_get_hashfile_details_ntlm(self, api):
|
||||
"""Sanity: NTLM (1000) still parses from `hash_type`."""
|
||||
mock_resp = Mock()
|
||||
mock_resp.json.return_value = {
|
||||
"hash_type": 1000,
|
||||
"msg": "OK",
|
||||
"status": 200,
|
||||
"type": "message",
|
||||
}
|
||||
mock_resp.raise_for_status = Mock()
|
||||
api.session.get.return_value = mock_resp
|
||||
|
||||
assert api.get_hashfile_details(7)["hashtype"] == 1000
|
||||
|
||||
def test_get_hashfile_hash_type_reads_hashfiles_key(self, api):
|
||||
"""Endpoint returns {hashfiles: [...]} objects; return their ids."""
|
||||
mock_resp = Mock()
|
||||
mock_resp.json.return_value = {
|
||||
"status": 200,
|
||||
"type": "message",
|
||||
"msg": "OK",
|
||||
"hashfiles": [{"id": 3, "name": "a"}, {"id": 9, "name": "b"}],
|
||||
}
|
||||
mock_resp.raise_for_status = Mock()
|
||||
api.session.get.return_value = mock_resp
|
||||
|
||||
assert api.get_hashfile_hash_type(1000) == [3, 9]
|
||||
|
||||
def test_upload_cracked_hashes_success(self, api, tmp_path):
|
||||
"""Test uploading cracked hashes with valid lines (real API if possible)."""
|
||||
hashview_url, hashview_api_key = self._get_hashview_config()
|
||||
|
||||
Reference in New Issue
Block a user