Skip to content

Instantly share code, notes, and snippets.

@decal
Created January 7, 2019 14:59
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save decal/198399fde5858857b0d8a4930c8c5330 to your computer and use it in GitHub Desktop.
Save decal/198399fde5858857b0d8a4930c8c5330 to your computer and use it in GitHub Desktop.
Enumerate sub-domains with Google's site: search operator
#!/usr/bin/env bash
#
# goodoms: Enumerate sub-domains with Google's site: search operator
#
# Admittedly, general-purpose search engines aren't the best enumerators of DNS
# records. However, they are good at extracting host names that may have been
# otherwise inaccessible as a result of cached web pages in the search indices.
# This script was created to automate the process in a semi-predictable manner.
#
# Written by: Derek Callaway [derek.callaway (AT) ioactive {D0T} com]
# Created on: Mon Jul 23 21:03:33 PDT 2018
# Tested via: macOS High Sierra and WSL Ubuntu
# Final edit: Sun Jan 6 01:08:33 PST 2019
#
# *Pseudo-code:*
#
# 0. Parse arguments passed as command-line options
#
# 1. Perform an initial search of given parent domain
# i.e. `site:host.dom`
#
# 2. Iteratively negate the site operator for known sub-domain names
# i.e. `site:host.dom -site:www.host.dom -site:mail.host.dom`
#
# 3. Continue this behavior until no new sub-domains are discovered
#
# 4. Write the final accumulated sub-domain name list to standard output
#
# 5. Exit gracefully
#
if [ ! "$1" ]; then
# Show usage if no domain has been provided
echo
echo -e "\033[41;30musage:\033[m \033[43;32;3;1m$0\033[m \033[44;31mDOMAIN\033[m"
echo
echo -e ' \033[44;31mDOMAIN\033[m \033[42;33mdomain to enumerate hosts of with the Google \033[3;1msite:\033[m\033[42;33m operator\033[m'
echo
exit 1
fi
# Detect if the googler script has been installed
which googler >/dev/null
if [ $? -ne 0 ]; then
# Print installation instructions and error out if unable to run googler
echo -e '\n\033[41;30mgoogler:\033[m \033[31mUnknown command\033[m'
echo
echo -e ' \033[31;42m1\033[1m.\033[m \033[34;43;3;1mbrew install googler\033[m \033[4;1mor\033[m \033[34;43;3;1mpip install googler\033[m'
echo
echo -e ' \033[31;42m2\033[1m.\033[m \033[34;43mcheck your \033[3;1m$PATH\033[m\033[34;43m environment variable\033[m'
echo
exit 2
fi
# Initialization syntax of variables required to perform auxiliary storage
declare gargs="site:*.${1}"
declare -i count=0
declare -a hosts=() hostz=()
while true; do
# Pause execution occassionally to prevent Google from getting overwhelmed
[ $count -ne 0 ] && sleep $(( 4 + $[ RANDOM % 8 ] ))
# Extract DNS domain names from JSON syntax that comprises Google response
declare hosts=$(googler --json -- "$gargs" | grep '"url"' | cut -d: -f2- | cut -d\" -f2 | egrep "[.]${1}" | awk -F".${1}" '{print$1}' | awk -F'//' '{print$2}' | sort -u)
if [ ${#hosts} -eq 0 ]; then
if [ $count -eq 0 ]; then
# Show error message and exit if there are no result items
echo -e "\n\033[41;30mgoodoms:\033[m \033[31mNo search results detected!\033[m\n"
exit 3
fi
# Escape from loop if this is not the first iteration and it lacks results
break
fi
# Show the operator that the process is keeping busy
echo -ne '.' >/dev/stderr
# Ensure new host names are unique
hostz=$(echo ${hostz[@]} ${hosts[@]} | tr ' ' '\n' | sort -u | tr '\n' ' ')
# Increment the loop counter
count+=1
# Show activity by periodically outputting a dot to the process error stream
echo -ne '.' >/dev/stderr
# Wait at least two seconds with a possibility of up to four more
sleep $(( 2 + $[ RANDOM % 4 ] ))
# Iteratively append negated site operators to new search request
for h in ${hosts[*]}; do
# Craft query string based on discovered sub-domain names
gargs+=" -site:${h}.${1}"
done
# Continuously alert the operator to ongoing business
echo -ne '.' >/dev/stderr
# Avoid getting flagged as a bot by trying not to startle Google
sleep $(( 4 + $[ RANDOM % 8 ] ))
# Display another period via the standard error device
echo -ne '.' >/dev/stderr
done
# End dot sequence by dropping down onto the next terminal row via a newline
echo >/dev/stderr
# Output results array
for h in ${hostz[*]}; do
echo "${h}.${1}"
done
# Finished!
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment