348 lines
8.3 KiB
Bash
Executable file
348 lines
8.3 KiB
Bash
Executable file
#!/bin/bash
|
|
# Name: SearchSploit - Exploit-DB's CLI search tool
|
|
# Version: 3.2 (Release date: 2016-03-18)
|
|
# Written by: Offensive Security, Unix-Ninja & g0tmi1k
|
|
# Homepage: https://github.com/offensive-security/exploit-database
|
|
#
|
|
## NOTE:
|
|
# Exit code '0' means finished normally
|
|
# Exit code '1' means finished help screen
|
|
# Exit code '6' means updated from GitHub
|
|
|
|
|
|
## OS settings
|
|
gitpath="/usr/share/exploitdb"
|
|
csvpath="${gitpath}/files.csv"
|
|
|
|
|
|
## Program settings
|
|
gitremote="https://github.com/offensive-security/exploit-database.git"
|
|
progname="$( basename "$0" )"
|
|
|
|
|
|
## Default options
|
|
COLOUR=1
|
|
EDBID=0
|
|
EXACT=0
|
|
FILEPATH=1
|
|
GETPATH=0
|
|
OVERFLOW=0
|
|
WEBLINK=0
|
|
SCASE=0
|
|
TAGS=""
|
|
CASE_TAG_GREP="-i"
|
|
CASE_TAG_FGREP="tolower"
|
|
COLOUR_TAG=""
|
|
SEARCH=""
|
|
|
|
|
|
## Set LANG variable to avoid illegal byte sequence errors
|
|
LANG=C
|
|
|
|
|
|
## If files.csv is in the searchsploit path, use that instead
|
|
if [[ -f "$( dirname "$0" )/files.csv" ]]; then
|
|
csvpath="$( dirname "$0" )/files.csv"
|
|
fi
|
|
|
|
|
|
## Usage info
|
|
function usage()
|
|
{
|
|
echo " Usage: ${progname} [options] term1 [term2] ... [termN]"
|
|
echo "Example:"
|
|
echo " ${progname} afd windows local"
|
|
echo " ${progname} -t oracle windows"
|
|
echo
|
|
echo "========="
|
|
echo " Options "
|
|
echo "========="
|
|
echo " -c, --case Perform a case-sensitive search (Default is inSEnsITiVe)."
|
|
echo " -e, --exact Perform an EXACT match on exploit title (Default is AND) [Implies \"-t\"]."
|
|
echo " -h, --help Show this help screen."
|
|
echo " -o, --overflow Exploit title's are allowed to overflow their columns."
|
|
echo " -p, --path Show the full path to an exploit (Copies path to clipboard if possible)."
|
|
echo " -t, --title Search just the exploit title (Default is title AND the file's path)."
|
|
echo " -u, --update Update exploit database from git."
|
|
echo " -w, --www Show URLs to Exploit-DB.com rather than local path."
|
|
echo " --id Display EDB-ID value rather than local path."
|
|
echo " --colour Disable colour highlighting."
|
|
echo
|
|
echo "======="
|
|
echo " Notes "
|
|
echo "======="
|
|
echo " * Use any number of search terms."
|
|
echo " * Search terms are not case sensitive, and order is irrelevant."
|
|
echo " * Use '-c' if you wish to reduce results by case-sensitive searching."
|
|
echo " * And/Or '-e' if you wish to filter results by using an exact match."
|
|
echo " * Use '-t' to exclude the file's path to filter the search results."
|
|
echo " * Remove false positives (especially when searching numbers/versions)."
|
|
echo " * When updating from git or displaying help, search terms will be ignored."
|
|
echo ""
|
|
exit 1
|
|
}
|
|
|
|
## Update database (via GIT)
|
|
function update()
|
|
{
|
|
## Make sure we are in the correct folder
|
|
mkdir -p "${gitpath}/"
|
|
cd "${gitpath}/"
|
|
|
|
## Make sure a git repo is init before updating
|
|
if [[ "$( git rev-parse --is-inside-work-tree )" != "true" ]]; then
|
|
if [[ "$( ls )" = "" ]]; then
|
|
# If directory is empty, just clone
|
|
git clone "${gitremote}" .
|
|
else
|
|
# If not empty, init and add remote
|
|
git init >/dev/null
|
|
git remote add origin "${gitremote}"
|
|
fi
|
|
fi
|
|
|
|
# Make sure to prep checkout first
|
|
git checkout -- .
|
|
|
|
# Update from git
|
|
git pull origin master
|
|
|
|
# If conflicts, clean and try again
|
|
if [[ "$?" -ne 0 ]]; then
|
|
git clean -d -fx ""
|
|
git pull origin master
|
|
fi
|
|
|
|
echo "[*] Update finished."
|
|
exit 6
|
|
}
|
|
|
|
|
|
## Printing dotted lines in the correct manner
|
|
function drawline()
|
|
{
|
|
printf "%0.s-" $( eval echo {1..$(( COL1 + 1 ))} )
|
|
echo -n " "
|
|
printf "%0.s-" $( eval echo {1..$(( COL2 - 1 ))} )
|
|
echo ""
|
|
}
|
|
|
|
|
|
## Check for empty args
|
|
if [[ $# -eq 0 ]]; then
|
|
usage >&2
|
|
fi
|
|
|
|
|
|
## Parse long arguments
|
|
ARGS="-"
|
|
for param in "$@"; do
|
|
if [[ "${param}" == "--case" ]]; then
|
|
SCASE=1
|
|
elif [[ "${param}" == "--exact" ]]; then
|
|
EXACT=1
|
|
elif [[ "${param}" == "--help" ]]; then
|
|
usage >&2
|
|
elif [[ "${param}" == "--overflow" ]]; then
|
|
OVERFLOW=1
|
|
elif [[ "${param}" == "--path" ]]; then
|
|
GETPATH=1
|
|
elif [[ "${param}" == "--title" ]]; then
|
|
FILEPATH=0
|
|
elif [[ "${param}" == "--update" ]]; then
|
|
update
|
|
elif [[ "${param}" == "--www" ]]; then
|
|
WEBLINK=1
|
|
elif [[ "${param}" == "--colour" ]] || [[ "${param}" == "--color" ]]; then
|
|
COLOUR=""
|
|
elif [[ "${param}" == "--id" ]]; then
|
|
EDBID=1
|
|
else
|
|
if [[ "${param:0:1}" == "-" ]]; then
|
|
ARGS=${ARGS}${param:1}
|
|
shift
|
|
continue
|
|
fi
|
|
TAGS="${TAGS} ${param//\`/_}"
|
|
fi
|
|
done
|
|
|
|
|
|
## Parse short arguments
|
|
while getopts "cehoptuw" arg "${ARGS}"; do
|
|
if [[ "${arg}" = "?" ]]; then
|
|
usage >&2;
|
|
fi
|
|
case ${arg} in
|
|
c) SCASE=1;;
|
|
e) EXACT=1;;
|
|
h) usage >&2;;
|
|
o) OVERFLOW=1;;
|
|
p) GETPATH=1;;
|
|
t) FILEPATH=0;;
|
|
u) update;;
|
|
w) WEBLINK=1;;
|
|
esac
|
|
shift $(( OPTIND - 1 ))
|
|
done
|
|
|
|
|
|
## Print the full path. If pbcopy/xclip is available then copy to the clipboard
|
|
if [[ "${GETPATH}" -eq '1' ]]; then
|
|
|
|
tag="$(echo ${TAGS} | tr '[:upper:]' '[:lower:]')"
|
|
edbid=$(echo "${tag}" | tr -dc '0-9')
|
|
edbpath=$(awk -F ',' '{print $2}' ${csvpath} | grep -E "/${edbid}(\..*)?$")
|
|
location="${gitpath}/${edbpath}"
|
|
|
|
echo "The exploit should be at: ${location}"
|
|
|
|
# Are any copy programs available?
|
|
if hash xclip 2>/dev/null || hash pbcopy 2>/dev/null; then
|
|
|
|
if hash xclip 2>/dev/null; then
|
|
echo -ne "${location}" | xclip -selection clipboard
|
|
else
|
|
echo -ne "${location}" | pbcopy
|
|
fi
|
|
|
|
echo "Location has been copied to the clipboard."
|
|
fi
|
|
|
|
exit 0
|
|
fi
|
|
|
|
|
|
## If we are doing an exact match, do not check folder path.
|
|
if [[ "${EXACT}" -eq 1 ]]; then
|
|
FILEPATH=0
|
|
fi
|
|
|
|
|
|
## Case sensitive?
|
|
if [[ "${SCASE}" -eq 1 ]]; then
|
|
## Remove the default flags
|
|
CASE_TAG_GREP=""
|
|
CASE_TAG_FGREP=""
|
|
fi
|
|
|
|
|
|
## Dynamically set column widths to the current screen size
|
|
if [[ "${WEBLINK}" -eq 1 ]]; then
|
|
COL2=45
|
|
else
|
|
COL2=35
|
|
fi
|
|
COL1=$(( $( tput cols ) - COL2 - 1 ))
|
|
|
|
|
|
## Print header
|
|
drawline
|
|
printf "%-${COL1}s %s" " Exploit Title"
|
|
if [[ "${WEBLINK}" -eq 1 ]]; then
|
|
echo "| URL"
|
|
elif [[ "${EDBID}" -eq 1 ]]; then
|
|
echo "| EDB-ID"
|
|
else
|
|
echo "| Path"
|
|
printf "%-${COL1}s "
|
|
echo "| (${gitpath}/platforms)"
|
|
fi
|
|
drawline
|
|
|
|
|
|
## EXACT search command?
|
|
if [[ "${EXACT}" -eq 1 ]]; then
|
|
## Case sensitive?
|
|
if [[ "${SCASE}" -eq 1 ]]; then
|
|
SEARCH="${TAGS}"
|
|
else
|
|
SEARCH="$( echo ${TAGS} | tr '[:upper:]' '[:lower:]' )"
|
|
fi
|
|
|
|
## Remove leading space
|
|
SEARCH="$(echo ${SEARCH} | sed -e 's/^[[:space:]]//')"
|
|
|
|
## If we are to use colour, add the values to search for
|
|
if [[ "${COLOUR}" -eq 1 ]]; then
|
|
COLOUR_TAG="${SEARCH}"
|
|
fi
|
|
## or AND search command?
|
|
else
|
|
## For each term
|
|
for tag in ${TAGS}; do
|
|
## If we are to use colour, add the values to search for between "or"
|
|
if [[ "${COLOUR}" -eq 1 ]]; then
|
|
COLOUR_TAG="${COLOUR_TAG}\|${tag}"
|
|
fi
|
|
|
|
## Search both title and path?
|
|
if [[ "${FILEPATH}" -eq 1 ]]; then
|
|
## Is there a value already?
|
|
if [[ "${SEARCH}" ]]; then
|
|
SEARCH="${SEARCH} |"
|
|
fi
|
|
|
|
## Search command for each term
|
|
SEARCH="${SEARCH} fgrep ${CASE_TAG_GREP} \"${tag}\""
|
|
## Search just the title, not the path
|
|
else
|
|
## If there is already a value, prepend text to get ready
|
|
if [[ "${SEARCH}" ]]; then
|
|
SEARCH="${SEARCH}/ && ${CASE_TAG_FGREP}(\$1) ~ /"
|
|
fi
|
|
|
|
## Case sensitive?
|
|
if [[ "${SCASE}" -eq 1 ]]; then
|
|
EARCH="${SEARCH}${tag}"
|
|
else
|
|
SEARCH="${SEARCH}$( echo ${tag} | tr '[:upper:]' '[:lower:]' )"
|
|
fi
|
|
fi
|
|
done
|
|
fi
|
|
|
|
|
|
## If we are not to use the path name
|
|
if [[ "${FILEPATH}" -eq 0 ]]; then
|
|
SEARCH="awk -F '[|]' '${CASE_TAG_FGREP}(\$1) ~ /${SEARCH}/ {print}'"
|
|
fi
|
|
|
|
|
|
## If we are to use colour, add the value here
|
|
if [[ "${COLOUR_TAG}" ]]; then
|
|
SEARCH="${SEARCH} | grep --color=always -ie \"\${COLOUR_TAG}\""
|
|
fi
|
|
|
|
|
|
## Search, format, and print results
|
|
if [[ "${OVERFLOW}" -eq 1 ]]; then
|
|
FORMAT=${COL1}
|
|
else
|
|
FORMAT=${COL1}'.'${COL1}
|
|
fi
|
|
|
|
|
|
## Magic search Fu
|
|
## Web link format?
|
|
if [[ "${WEBLINK}" -eq 1 ]]; then
|
|
awk -F "\"*,\"*" '{ printf "%-'${FORMAT}'s | %s\n", $3, "https://www.exploit-db.com/exploits/"$1"/"}' "${csvpath}" \
|
|
| eval "${SEARCH}"
|
|
## Just the EDB-ID?
|
|
elif [[ "${EDBID}" -eq 1 ]]; then
|
|
awk -F "\"*,\"*" '{ printf "%-'${FORMAT}'s | %s\n", $3, $1}' "${csvpath}" \
|
|
| eval "${SEARCH}"
|
|
## Default view
|
|
else
|
|
awk -F "\"*,\"*" '{ printf "%-'${FORMAT}'s | %s\n", $3, $2}' "${csvpath}" \
|
|
| eval "${SEARCH}" \
|
|
| sed "s/| platforms/| ./"
|
|
fi
|
|
|
|
|
|
## Print footer
|
|
drawline
|
|
|
|
|
|
## Done
|
|
exit 0
|