Skip to content

Commit

Permalink
Modify password cracking (#1346)
Browse files Browse the repository at this point in the history
* Only try single word list for speed

* Expand regex for nested dirs and double timeout

* Recover if not rules file

* Don't actually bruteforce in the tests

* Formatting

* Temp rules file

* Nits from PR

* Formatting

* Two more spaces apparently
  • Loading branch information
Fryyyyy authored Sep 28, 2023
1 parent 98698c6 commit 7af4690
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 10 deletions.
1 change: 1 addition & 0 deletions docker/worker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ RUN cd /home/turbinia && echo "" > password.lst
RUN cd /home/turbinia && curl -s https://raw.githubusercontent.com/danielmiessler/SecLists/285474cf9bff85f3323c5a1ae436f78acd1cb62c/Passwords/UserPassCombo-Jay.txt >> password.lst
RUN cd /home/turbinia && curl -s https://raw.githubusercontent.com/danielmiessler/SecLists/master/Passwords/Common-Credentials/10-million-password-list-top-1000000.txt >> password.lst
RUN cp /home/turbinia/password.lst /root/
RUN echo ':\nd' > /home/turbinia/turbinia-password-cracking.rules

# Copy Kubernetes support tool to home folder
COPY --chown=turbinia:turbinia k8s/tools/check-lockfile.py /home/turbinia/check-lockfile.py
Expand Down
17 changes: 12 additions & 5 deletions turbinia/lib/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ def bruteforce_password_hashes(

pot_file = os.path.join((tmp_dir or tempfile.gettempdir()), 'hashcat.pot')
password_list_file_path = os.path.expanduser('~/password.lst')
password_rules_file_path = os.path.expanduser(
'~/turbinia-password-cracking.rules')

# Fallback
if not os.path.isfile(password_list_file_path):
Expand All @@ -180,21 +182,26 @@ def bruteforce_password_hashes(
if not os.path.isfile(password_list_file_path):
raise TurbiniaException('No password list available')

# Does rules file exist? If not make a temp one
if not os.path.isfile(password_rules_file_path):
with tempfile.NamedTemporaryFile(delete=False, mode='w+') as rf:
password_rules_file_path = rf.name
rf.write('\n'.join([':', 'd']))

if '$y$' in ''.join(password_hashes):
cmd = [
'john', '--format=crypt', f'--wordlist={password_list_file_path}',
password_hashes_file_path
]
pot_file = os.path.expanduser('~/.john/john.pot')
else:
cmd = ['hashcat', '--force', '-a', '1']
# Ignore warnings & plain word list attack (with rules)
cmd = ['hashcat', '--force', '-a', '0']
if extra_args:
cmd = cmd + extra_args.split(' ')
cmd = cmd + [f'--potfile-path={pot_file}']
cmd = cmd + [
password_hashes_file_path, password_list_file_path,
password_list_file_path
]
cmd = cmd + [password_hashes_file_path, password_list_file_path]
cmd = cmd + ['-r', password_rules_file_path]

with open(os.devnull, 'w') as devnull:
try:
Expand Down
4 changes: 2 additions & 2 deletions turbinia/workers/analysis/jenkins.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class JenkinsAnalysisTask(TurbiniaTask):
TASK_CONFIG = {
# This is the length of time in seconds that the collected passwords will
# be bruteforced.
'bruteforce_timeout': 300
'bruteforce_timeout': 600
}

def run(self, evidence, result):
Expand Down Expand Up @@ -72,7 +72,7 @@ def run(self, evidence, result):

jenkins_artifacts = []
jenkins_re = re.compile(
r'^.*jenkins[^\/]*(\/home)?(\/users\/[^\/]+)*\/config\.xml$')
r'^.*?jenkins[^\/]*(\/home)?(\/users)?(\/.*?)\/config\.xml$')
for collected_artifact in collected_artifacts:
if re.match(jenkins_re, collected_artifact):
jenkins_artifacts.append(collected_artifact)
Expand Down
19 changes: 16 additions & 3 deletions turbinia/workers/analysis/postgresql_acct_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"""Tests for the PostgreSQL account analysis task."""

import os
import mock
import unittest

from turbinia import config
Expand All @@ -35,7 +36,7 @@ class PostgresAcctAnalysisTaskTest(TestTurbiniaTaskBase):

POSTGRES_REPORT = """#### **PostgreSQL analysis found 1 weak password(s)**
* **1 weak password(s) found:**
* User 'postgres' with password 'password'"""
* User 'postgres' with password 'postgres'"""

def setUp(self):
super(PostgresAcctAnalysisTaskTest, self).setUp()
Expand Down Expand Up @@ -72,22 +73,34 @@ def test_extract_scram_creds(self):
_, hashes = task._extract_creds(['/scram_database'], self.evidence)
self.assertDictEqual(hashes, self.EXPECTED_SCRAM_CREDENTIALS)

def test_analyse_md5_postgres_creds(self):
@mock.patch(
'turbinia.workers.analysis.postgresql_acct.bruteforce_password_hashes')
def test_analyse_md5_postgres_creds(self, bruteforce_mock):
"""Tests the _analyse_postgres_creds method."""
config.LoadConfig()
task = postgresql_acct.PostgresAccountAnalysisTask()

bruteforce_mock.side_effect = [
[(list(self.EXPECTED_MD5_CREDENTIALS.keys())[0], 'postgres')], []
]

(report, priority, summary) = task._analyse_postgres_creds(
self.EXPECTED_MD5_CREDENTIALS, {})
self.assertEqual(report, self.POSTGRES_REPORT)
self.assertEqual(priority, 10)
self.assertEqual(summary, 'PostgreSQL analysis found 1 weak password(s)')

def test_analyse_scram_postgres_creds(self):
@mock.patch(
'turbinia.workers.analysis.postgresql_acct.bruteforce_password_hashes')
def test_analyse_scram_postgres_creds(self, bruteforce_mock):
"""Tests the _analyse_postgres_creds method."""
config.LoadConfig()
task = postgresql_acct.PostgresAccountAnalysisTask()

bruteforce_mock.side_effect = [
[], [(list(self.EXPECTED_SCRAM_CREDENTIALS.keys())[0], 'postgres')]
]

(report, priority, summary) = task._analyse_postgres_creds(
{}, self.EXPECTED_SCRAM_CREDENTIALS)
self.assertEqual(report, self.POSTGRES_REPORT)
Expand Down

0 comments on commit 7af4690

Please sign in to comment.