Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hashlist helpers implemented #1042

Merged
merged 5 commits into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions ci/apiv2/hashtopolis.py
Original file line number Diff line number Diff line change
Expand Up @@ -683,3 +683,33 @@ def purge_task(self, task):
'taskId': task.id,
}
return self._helper_request("purgeTask", payload)

def export_cracked_hashes(self, hashlist):
payload = {
'hashlistId': hashlist.id,
}
response = self._helper_request("exportCrackedHashes", payload)
return File(**response['data'])

def export_left_hashes(self, hashlist):
payload = {
'hashlistId': hashlist.id,
}
response = self._helper_request("exportLeftHashes", payload)
return File(**response['data'])

def export_wordlist(self, hashlist):
payload = {
'hashlistId': hashlist.id,
}
response = self._helper_request("exportWordlist", payload)
return File(**response['data'])

def import_cracked_hashes(self, hashlist, source_data, separator):
payload = {
'hashlistId': hashlist.id,
'sourceData': source_data,
'separator': separator,
}
response = self._helper_request("importCrackedHashes", payload)
return response['data']
100 changes: 99 additions & 1 deletion ci/apiv2/test_hashlist.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from hashtopolis import Hashlist, Helper
from hashtopolis import Hashlist, Helper, File
from utils import BaseTest


Expand Down Expand Up @@ -38,6 +38,104 @@ def test_create_alternative_hashtype(self):
model_obj = self.create_test_object(file_id='003')
self._test_create(model_obj)

def test_export_cracked_hashes(self):
model_obj = self.create_test_object(file_id='001')

helper = Helper()
file = helper.export_cracked_hashes(model_obj)

obj = File.objects.get(fileId=file.id)
self.assertEqual(int(file.id), obj.id)
self.assertIn('Pre-cracked_', obj.filename)

self.delete_after_test(obj)

def test_export_left_hashes(self):
model_obj = self.create_test_object(file_id='001')

helper = Helper()
file = helper.export_left_hashes(model_obj)

obj = File.objects.get(fileId=file.id)
self.assertEqual(int(file.id), obj.id)
self.assertIn('Leftlist_', obj.filename)

self.delete_after_test(obj)

def test_export_wordlist(self):
model_obj = self.create_test_object(file_id='001')

cracked = "cc03e747a6afbbcbf8be7668acfebee5:test123"

helper = Helper()
helper.import_cracked_hashes(model_obj, cracked, ':')

file = helper.export_wordlist(model_obj)

obj = File.objects.get(fileId=file.id)
self.assertEqual(int(file.id), obj.id)
self.assertIn('Wordlist_', obj.filename)

self.delete_after_test(obj)

def test_import_cracked_hashes(self):
model_obj = self.create_test_object(file_id='001')

cracked = "cc03e747a6afbbcbf8be7668acfebee5:test123"

helper = Helper()
result = helper.import_cracked_hashes(model_obj, cracked, ':')

self.assertEqual(result['totalLines'], 1)
self.assertEqual(result['newCracked'], 1)

obj = Hashlist.objects.get(hashlistId=model_obj.id)
self.assertEqual(obj.cracked, 1)

def test_import_cracked_hashes_invalid(self):
model_obj = self.create_test_object(file_id='001')

cracked = "cc03e747a6afbbcbf8be7668acfebee5__test123"

helper = Helper()
result = helper.import_cracked_hashes(model_obj, cracked, ':')

self.assertEqual(result['totalLines'], 1)
self.assertEqual(result['invalid'], 1)

obj = Hashlist.objects.get(hashlistId=model_obj.id)
self.assertEqual(obj.cracked, 0)

def test_import_cracked_hashes_notfound(self):
model_obj = self.create_test_object(file_id='001')

cracked = "ffffffffffffffffffffffffffffffff:test123"

helper = Helper()
result = helper.import_cracked_hashes(model_obj, cracked, ':')

self.assertEqual(result['totalLines'], 1)
self.assertEqual(result['notFound'], 1)

obj = Hashlist.objects.get(hashlistId=model_obj.id)
self.assertEqual(obj.cracked, 0)

def test_import_cracked_hashes_already_cracked(self):
model_obj = self.create_test_object(file_id='001')

cracked = "cc03e747a6afbbcbf8be7668acfebee5:test123"

helper = Helper()
helper.import_cracked_hashes(model_obj, cracked, ':')

result = helper.import_cracked_hashes(model_obj, cracked, ':')

self.assertEqual(result['totalLines'], 1)
self.assertEqual(result['alreadyCracked'], 1)

obj = Hashlist.objects.get(hashlistId=model_obj.id)
self.assertEqual(obj.cracked, 1)

def test_helper_create_superhashlist(self):
hashlists = [self.create_test_object() for _ in range(2)]

Expand Down
4 changes: 4 additions & 0 deletions src/api/v2/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,10 @@ public function process(Request $request, RequestHandler $handler): Response {
require __DIR__ . "/../../inc/apiv2/helper/abortChunk.routes.php";
require __DIR__ . "/../../inc/apiv2/helper/createSupertask.routes.php";
require __DIR__ . "/../../inc/apiv2/helper/createSuperHashlist.routes.php";
require __DIR__ . "/../../inc/apiv2/helper/exportCrackedHashes.routes.php";
require __DIR__ . "/../../inc/apiv2/helper/exportLeftHashes.routes.php";
require __DIR__ . "/../../inc/apiv2/helper/exportWordlist.routes.php";
require __DIR__ . "/../../inc/apiv2/helper/importCrackedHashes.routes.php";
require __DIR__ . "/../../inc/apiv2/helper/importFile.routes.php";
require __DIR__ . "/../../inc/apiv2/helper/purgeTask.routes.php";
require __DIR__ . "/../../inc/apiv2/helper/resetChunk.routes.php";
Expand Down
37 changes: 37 additions & 0 deletions src/inc/apiv2/helper/exportCrackedHashes.routes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php
use DBA\File;
use DBA\Hash;
use DBA\Hashlist;

require_once(dirname(__FILE__) . "/../common/AbstractHelperAPI.class.php");

class ExportCrackedHashesHelperAPI extends AbstractHelperAPI {
public static function getBaseUri(): string {
return "/api/v2/helper/exportCrackedHashes";
}

public static function getAvailableMethods(): array {
return ['POST'];
}

public function getRequiredPermissions(string $method): array
{
return [Hashlist::PERM_READ, Hash::PERM_READ, File::PERM_CREATE];
}

public function getFormFields(): array
{
return [
Hashlist::HASHLIST_ID => ["type" => "int"],
];
}

public function actionPost($data): array|null {
$hashlist = self::getHashlist($data[Hashlist::HASHLIST_ID]);

$file = HashlistUtils::export($hashlist->getId(), $this->getCurrentUser());
return $this->object2Array($file);
}
}

ExportCrackedHashesHelperAPI::register($app);
38 changes: 38 additions & 0 deletions src/inc/apiv2/helper/exportLeftHashes.routes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php
use DBA\File;
use DBA\Hash;
use DBA\Hashlist;

require_once(dirname(__FILE__) . "/../common/AbstractHelperAPI.class.php");

class ExportLeftHashesHelperAPI extends AbstractHelperAPI {
public static function getBaseUri(): string {
return "/api/v2/helper/exportLeftHashes";
}

public static function getAvailableMethods(): array {
return ['POST'];
}

public function getRequiredPermissions(string $method): array
{
return [Hashlist::PERM_READ, Hash::PERM_READ, File::PERM_CREATE];
}

public function getFormFields(): array
{
return [
Hashlist::HASHLIST_ID => ["type" => "int"],
];
}

public function actionPost($data): array|null {
$hashlist = self::getHashlist($data[Hashlist::HASHLIST_ID]);

$file = HashlistUtils::leftlist($hashlist->getId(), $this->getCurrentUser());

return $this->object2Array($file);
}
}

ExportLeftHashesHelperAPI::register($app);
38 changes: 38 additions & 0 deletions src/inc/apiv2/helper/exportWordlist.routes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php
use DBA\File;
use DBA\Hash;
use DBA\Hashlist;

require_once(dirname(__FILE__) . "/../common/AbstractHelperAPI.class.php");

class ExportWordlistHelperAPI extends AbstractHelperAPI {
public static function getBaseUri(): string {
return "/api/v2/helper/exportWordlist";
}

public static function getAvailableMethods(): array {
return ['POST'];
}

public function getRequiredPermissions(string $method): array
{
return [Hashlist::PERM_READ, Hash::PERM_READ, File::PERM_CREATE];
}

public function getFormFields(): array
{
return [
Hashlist::HASHLIST_ID => ["type" => "int"],
];
}

public function actionPost($data): array|null {
$hashlist = self::getHashlist($data[Hashlist::HASHLIST_ID]);

$arr = HashlistUtils::createWordlists($hashlist->getId(), $this->getCurrentUser());

return $this->object2Array($arr[2]);
}
}

ExportWordlistHelperAPI::register($app);
47 changes: 47 additions & 0 deletions src/inc/apiv2/helper/importCrackedHashes.routes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

use DBA\Hash;
use DBA\Hashlist;

require_once(dirname(__FILE__) . "/../common/AbstractHelperAPI.class.php");

class ImportCrackedHashesHelperAPI extends AbstractHelperAPI {
public static function getBaseUri(): string {
return "/api/v2/helper/importCrackedHashes";
}

public static function getAvailableMethods(): array {
return ['POST'];
}

public function getRequiredPermissions(string $method): array {
return [Hashlist::PERM_UPDATE, Hash::PERM_UPDATE];
}

public function getFormFields(): array {
return [
Hashlist::HASHLIST_ID => ["type" => "int"],
"sourceData" => ['type' => 'str'],
"separator" => ['type' => 'str'],
];
}

public function actionPost($data): array|null {
$hashlist = self::getHashlist($data[Hashlist::HASHLIST_ID]);

$result = HashlistUtils::processZap($hashlist->getId(), $data["separator"], "paste", ["hashfield" => $data["sourceData"]], [], $this->getCurrentUser());

# TODO: Check how to handle custom return messages that are not object, probably we want that to be in some kind of standardized form.
return [
s3inlc marked this conversation as resolved.
Show resolved Hide resolved
"totalLines" => $result[0],
"newCracked" => $result[1],
"alreadyCracked" => $result[2],
"invalid" => $result[3],
"notFound" => $result[4],
"processTime" => $result[5],
"tooLongPlaintexts" => $result[6],
];
}
}

ImportCrackedHashesHelperAPI::register($app);
5 changes: 3 additions & 2 deletions src/inc/utils/HashlistUtils.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,9 @@ public static function createWordlists($hashlistId, $user) {
fclose($wordlistFile);

//add file to files list
$file = new File(null, $wordlistName, Util::filesize($wordlistFilename), $hashlist->getIsSecret(), 0, $hashlist->getAccessGroupId(), null);
Factory::getFileFactory()->save($file);
$file = new File(null, $wordlistName, Util::filesize($wordlistFilename), $hashlist->getIsSecret(), 0, $hashlist->getAccessGroupId(), $wordCount);
$file = Factory::getFileFactory()->save($file);
# TODO: returning wordCount and wordlistName are not really required here as the name and the count are already given in the file object
return [$wordCount, $wordlistName, $file];
}

Expand Down
Loading