-
Notifications
You must be signed in to change notification settings - Fork 250
Implemented a better handling of (partially) unsalted hashlists #1657 #1751
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
Open
Eric-Wasson
wants to merge
6
commits into
dev
Choose a base branch
from
1657-unsalted-hashlist
base: dev
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
6f3a8b9
Implemented a better handling of (partially) unsalted hashlists
Eric-Wasson 4c11b58
Added return of creation information when creating a new hashlist
Eric-Wasson 9e47568
Merge branch 'dev' into 1657-unsalted-hashlist
Eric-Wasson eb7c438
Merge branch 'dev' into 1657-unsalted-hashlist
Eric-Wasson f01bd53
Fixed phpstan tests and a db communication bug
Eric-Wasson ddf3e02
Merge branch 'dev' into 1657-unsalted-hashlist
s3inlc File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -782,7 +782,8 @@ public static function export($hashlistId, $user) { | |
| * @param User $user | ||
| * @param int $brainId | ||
| * @param int $brainFeatures | ||
| * @return Hashlist | ||
| * @param boolean $writeResultsToNotes | ||
| * @return array | ||
| * @throws HTException | ||
| */ | ||
| public static function createHashlist($name, $isSalted, $isSecret, $isHexSalted, $separator, $format, $hashtype, $saltSeparator, $accessGroupId, $source, $post, $files, $user, $brainId, $brainFeatures) { | ||
|
|
@@ -851,33 +852,62 @@ public static function createHashlist($name, $isSalted, $isSecret, $isHexSalted, | |
| Factory::getAgentFactory()->getDB()->rollback(); | ||
| throw new HttpError("Hashlist has too many lines!"); | ||
| } | ||
|
|
||
| $file = fopen($tmpfile, "rb"); | ||
| if (!$file) { | ||
| Factory::getAgentFactory()->getDB()->rollback(); | ||
| throw new HttpError("Failed to open file!"); | ||
| } | ||
|
|
||
| if ($format == DHashlistFormat::PLAIN && $salted) { | ||
| // find out if the file contains a salt separator at all | ||
| rewind($file); | ||
|
|
||
| $saltSeparatorFound = false; | ||
| while (($currentLine = fgets($file)) !== false) { | ||
| if (strpos($currentLine, $saltSeparator) !== false) { | ||
| $saltSeparatorFound = true; | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| if ($saltSeparatorFound === false) { | ||
| fclose($file); | ||
| unlink($tmpfile); | ||
| Factory::getAgentFactory()->getDB()->rollback(); | ||
|
|
||
| throw new HttpError("Salted hashes separator not found at all in the hashlist! Hashlist not created."); | ||
| } | ||
| } | ||
| else { | ||
| $saltSeparator = ""; | ||
| } | ||
|
|
||
| Factory::getAgentFactory()->getDB()->commit(); | ||
|
|
||
| $added = 0; | ||
| $preFound = 0; | ||
| $hashlistStatistics = []; | ||
| $hashlistStatistics["uploadedTotalLines"] = 0; | ||
| $hashlistStatistics["uploadedEmptyLines"] = 0; | ||
| $hashlistStatistics["uploadedValidHashes"] = 0; | ||
| $hashlistStatistics["uploadedValidHashesWithoutExpectedSalt"] = 0; | ||
| $hashlistStatistics["uploadedInvalidHashes"] = 0; | ||
|
|
||
| switch ($format) { | ||
| case DHashlistFormat::PLAIN: | ||
| if ($salted) { | ||
| // find out if the first line contains field separator | ||
| rewind($file); | ||
| $bufline = stream_get_line($file, 1024); | ||
| if (strpos($bufline, $saltSeparator) === false) { | ||
| throw new HttpError("Salted hashes separator not found in file!"); | ||
| } | ||
| } | ||
| else { | ||
| $saltSeparator = ""; | ||
| } | ||
| rewind($file); | ||
|
|
||
| Factory::getAgentFactory()->getDB()->beginTransaction(); | ||
| $values = array(); | ||
| $bufferCount = 0; | ||
|
|
||
| while (!feof($file)) { | ||
| $line = trim(fgets($file)); | ||
| $hashlistStatistics["uploadedTotalLines"]++; | ||
|
|
||
| if (strlen($line) == 0) { | ||
| $hashlistStatistics["uploadedEmptyLines"]++; | ||
| continue; | ||
| } | ||
| $hash = $line; | ||
|
|
@@ -888,8 +918,12 @@ public static function createHashlist($name, $isSalted, $isSecret, $isHexSalted, | |
| $hash = substr($line, 0, $pos); | ||
| $salt = substr($line, $pos + 1); | ||
| } | ||
| else { | ||
| $hashlistStatistics["uploadedValidHashesWithoutExpectedSalt"]++; | ||
| } | ||
| } | ||
| if (strlen($hash) == 0) { | ||
| $hashlistStatistics["uploadedEmptyLines"]++; | ||
| continue; | ||
| } | ||
| //TODO: check hash length here | ||
|
|
@@ -906,13 +940,15 @@ public static function createHashlist($name, $isSalted, $isSecret, $isHexSalted, | |
| } | ||
| } | ||
| } | ||
|
|
||
| if ($found == null) { | ||
| $values[] = new Hash(null, $hashlist->getId(), $hash, $salt, "", 0, null, 0, 0); | ||
| } | ||
| else { | ||
| $values[] = new Hash(null, $hashlist->getId(), $hash, $salt, $found->getPlaintext(), time(), null, 1, 0); | ||
| $preFound++; | ||
| } | ||
|
|
||
| $bufferCount++; | ||
| if ($bufferCount >= 5000) { | ||
| $result = Factory::getHashFactory()->massSave($values); | ||
|
|
@@ -921,27 +957,42 @@ public static function createHashlist($name, $isSalted, $isSecret, $isHexSalted, | |
| $bufferCount = 0; | ||
| } | ||
| } | ||
|
|
||
| if (sizeof($values) > 0) { | ||
| $result = Factory::getHashFactory()->massSave($values); | ||
| $added += $result->rowCount(); | ||
| } | ||
|
|
||
| fclose($file); | ||
| unlink($tmpfile); | ||
|
|
||
| if ($added === 0) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this check should be done at the very end (as the same could be checked for BINARY and WPA hashes). The $added has to be incremented on line 1047 as well, but for WPA it's already done and can be used. |
||
| Factory::getAgentFactory()->getDB()->rollback(); | ||
| Factory::getHashlistFactory()->delete($hashlist); | ||
| Factory::getAgentFactory()->getDB()->commit(); | ||
| throw new HttpError("No valid hashes found! Hashlist not created."); | ||
| } | ||
|
|
||
| Factory::getHashlistFactory()->mset($hashlist, [Hashlist::HASH_COUNT => $added, Hashlist::CRACKED => $preFound]); | ||
| Util::createLogEntry("User", $user->getId(), DLogEntry::INFO, "New Hashlist created: " . $hashlist->getHashlistName()); | ||
| Util::createLogEntry("User", $user->getId(), DLogEntry::INFO, "New Hashlist created: " . $hashlist->getHashlistName() . ". Total lines: " . $hashlistStatistics["uploadedTotalLines"] . " Empty lines: " . $hashlistStatistics["uploadedEmptyLines"] . " Valid hashes: " . $hashlistStatistics["uploadedValidHashes"] . " Valid hashes without expected salt: " . $hashlistStatistics["uploadedValidHashesWithoutExpectedSalt"] . " Invalid hashes: " . $hashlistStatistics["uploadedInvalidHashes"]); | ||
|
|
||
| NotificationHandler::checkNotifications(DNotificationType::NEW_HASHLIST, new DataSet(array(DPayloadKeys::HASHLIST => $hashlist))); | ||
| break; | ||
| case DHashlistFormat::WPA: | ||
| $added = 0; | ||
| $values = []; | ||
|
|
||
| while (!feof($file)) { | ||
| $hashlistStatistics["uploadedTotalLines"]++; | ||
|
|
||
| if ($hashlist->getHashTypeId() == 2500) { // HCCAPX hashes | ||
| $data = fread($file, 393); | ||
| if (strlen($data) == 0) { | ||
| $hashlistStatistics["uploadedInvalidHashes"]++; | ||
| break; | ||
| } | ||
| if (strlen($data) != 393) { | ||
| $hashlistStatistics["uploadedInvalidHashes"]++; | ||
| UI::printError("ERROR", "Data file only contains " . strlen($data) . " bytes!"); | ||
| } | ||
| // get the SSID | ||
|
|
@@ -969,11 +1020,13 @@ public static function createHashlist($name, $isSalted, $isSecret, $isHexSalted, | |
| $mac_cli = Util::bintohex($mac_cli); | ||
| $hash = new HashBinary(null, $hashlist->getId(), $mac_ap . SConfig::getInstance()->getVal(DConfig::FIELD_SEPARATOR) . $mac_cli . SConfig::getInstance()->getVal(DConfig::FIELD_SEPARATOR) . Util::bintohex($network), Util::bintohex($data), null, 0, null, 0, 0); | ||
| Factory::getHashBinaryFactory()->save($hash); | ||
| $hashlistStatistics["uploadedValidHashes"]++; | ||
| $added++; | ||
| } | ||
| else { // PMKID hashes | ||
| $line = trim(fgets($file)); | ||
| if (strlen($line) == 0) { | ||
| $hashlistStatistics["uploadedEmptyLines"]++; | ||
| continue; | ||
| } | ||
| if (strpos($line, "*") !== false) { | ||
|
|
@@ -992,14 +1045,15 @@ public static function createHashlist($name, $isSalted, $isSecret, $isHexSalted, | |
| } | ||
| $hash = new HashBinary(null, $hashlist->getId(), $identification, Util::bintohex($line . "\n"), null, 0, null, 0, 0); | ||
| Factory::getHashBinaryFactory()->save($hash); | ||
| $hashlistStatistics["uploadedValidHashes"]++; | ||
| $added++; | ||
| } | ||
| } | ||
| fclose($file); | ||
| unlink($tmpfile); | ||
|
|
||
| Factory::getHashlistFactory()->set($hashlist, Hashlist::HASH_COUNT, $added); | ||
| Util::createLogEntry("User", $user->getId(), DLogEntry::INFO, "New Hashlist created: " . $hashlist->getHashlistName()); | ||
| Util::createLogEntry("User", $user->getId(), DLogEntry::INFO, "New Hashlist created: " . $hashlist->getHashlistName() . ". Total lines: " . $hashlistStatistics["uploadedTotalLines"] . " Empty lines: " . $hashlistStatistics["uploadedEmptyLines"] . " Valid hashes: " . $hashlistStatistics["uploadedValidHashes"] . " Valid hashes without expected salt: " . $hashlistStatistics["uploadedValidHashesWithoutExpectedSalt"] . " Invalid hashes: " . $hashlistStatistics["uploadedInvalidHashes"]); | ||
|
|
||
| NotificationHandler::checkNotifications(DNotificationType::NEW_HASHLIST, new DataSet(array(DPayloadKeys::HASHLIST => $hashlist))); | ||
| break; | ||
|
|
@@ -1008,17 +1062,21 @@ public static function createHashlist($name, $isSalted, $isSecret, $isHexSalted, | |
| $data = fread($file, Util::filesize($tmpfile)); | ||
| $hash = new HashBinary(null, $hashlist->getId(), "", Util::bintohex($data), "", 0, null, 0, 0); | ||
| Factory::getHashBinaryFactory()->save($hash); | ||
| $hashlistStatistics["uploadedValidHashes"]++; | ||
| } | ||
|
|
||
| fclose($file); | ||
| unlink($tmpfile); | ||
|
|
||
| Factory::getHashlistFactory()->set($hashlist, Hashlist::HASH_COUNT, 1); | ||
| Util::createLogEntry("User", $user->getId(), DLogEntry::INFO, "New Hashlist created: " . $hashlist->getHashlistName()); | ||
| Util::createLogEntry("User", $user->getId(), DLogEntry::INFO, "New Hashlist created: " . $hashlist->getHashlistName() . ". Total lines: " . $hashlistStatistics["uploadedTotalLines"] . " Empty lines: " . $hashlistStatistics["uploadedEmptyLines"] . " Valid hashes: " . $hashlistStatistics["uploadedValidHashes"] . " Valid hashes without expected salt: " . $hashlistStatistics["uploadedValidHashesWithoutExpectedSalt"] . " Invalid hashes: " . $hashlistStatistics["uploadedInvalidHashes"]); | ||
|
|
||
| NotificationHandler::checkNotifications(DNotificationType::NEW_HASHLIST, new DataSet(array(DPayloadKeys::HASHLIST => $hashlist))); | ||
| break; | ||
| } | ||
|
|
||
| Factory::getAgentFactory()->getDB()->commit(); | ||
| return $hashlist; | ||
| return ["hashlist" => $hashlist, "statistics" => $hashlistStatistics]; | ||
| } | ||
|
|
||
| /** | ||
|
|
||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using static strings as the key names is maybe not ideal, as it easily can happen that typos remain undiscovered and it's more difficult to discover errors.
Maybe it makes sense to define either constants for these keys or create a data class type object to handle the different values and then return the class object.