
remove json test fil remove personnal repository clean code add json option to readme add json output support
396 lines
9.8 KiB
Bash
Executable file
396 lines
9.8 KiB
Bash
Executable file
#!/bin/bash
|
|
# Name: SearchSploit - Exploit-DB's CLI search tool
|
|
# Version: 3.3 (Release date: 2016-04-02)
|
|
# 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 something went wrong
|
|
# Exit code '2' 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
|
|
JSON=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
|
|
gitpath="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
csvpath="${gitpath}/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 " -j, --json Show result in JSON format."
|
|
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 " --colour Disable colour highlighting."
|
|
echo " --id Display EDB-ID value rather than local path."
|
|
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/major versions)."
|
|
echo " * When updating from git or displaying help, search terms will be ignored."
|
|
echo ""
|
|
exit 2
|
|
}
|
|
|
|
|
|
## Update database (via GIT)
|
|
function update()
|
|
{
|
|
## Make sure we are in the correct folder
|
|
mkdir -p "${gitpath}/"
|
|
cd "${gitpath}/"
|
|
|
|
## Are we in a git repo?
|
|
if [[ "$( git rev-parse --is-inside-work-tree )" != "true" ]]; then
|
|
if [[ "$( ls )" = "" ]]; then
|
|
# If directory is empty, just clone
|
|
echo -e '\n[i] Nothing here. Starting fresh...'
|
|
git clone "${gitremote}" .
|
|
fi
|
|
fi
|
|
|
|
# Is our git remote added? (aka homebrew)
|
|
if [[ "$( git remote -v )" != *"${gitremote}"* ]]; then
|
|
echo -e '\n[i] Missing git remote:' "${gitremote}"
|
|
git init >/dev/null
|
|
git remote add origin "${gitremote}" 2>/dev/null
|
|
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 -e "\n[*] 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}" == "--json" ]]; then
|
|
JSON=1
|
|
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 "cehjoptuw" arg "${ARGS}"; do
|
|
if [[ "${arg}" = "?" ]]; then
|
|
usage >&2;
|
|
fi
|
|
case ${arg} in
|
|
c) SCASE=1;;
|
|
e) EXACT=1;;
|
|
h) usage >&2;;
|
|
j) JSON=1;;
|
|
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
|
|
## Get EDB-ID from input
|
|
edbdb="$( echo ${TAGS} | tr -dc '0-9' )"
|
|
## Check files.csv
|
|
location=$( cut -d, -f2 "${csvpath}" | grep -m 1 -E "/${edbdb}(\..*)?$" )
|
|
title=$( grep -m 1 "${location}" "${csvpath}" | cut -d, -f3 | sed 's/"//g')
|
|
## Join paths
|
|
location="${gitpath}/${location}"
|
|
|
|
## Did we find the exploit?
|
|
if [[ -f "${location}" ]]; then
|
|
## Display out
|
|
echo "Exploit: ${title}"
|
|
echo " Path: ${location}"
|
|
echo ""
|
|
|
|
## Are any copy programs available?
|
|
if hash xclip 2>/dev/null || hash pbcopy 2>/dev/null; then
|
|
## Linux
|
|
if hash xclip 2>/dev/null; then
|
|
echo -ne "${location}" | xclip -selection clipboard
|
|
echo "Copied the file path to the clipboard."
|
|
## OSX
|
|
elif hash pbcopy 2>/dev/null; then
|
|
echo -ne "${location}" | pbcopy
|
|
echo "Copied the file path to the clipboard."
|
|
fi
|
|
fi
|
|
|
|
## Done
|
|
exit 0
|
|
else
|
|
## Feedback
|
|
echo "Could not find exploit EDB-ID #${edbdb}"
|
|
|
|
## Quit
|
|
exit 1
|
|
fi
|
|
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=$(( ${#gitpath} + 15 ))
|
|
fi
|
|
COL1=$(( $( tput cols ) - COL2 - 1 ))
|
|
|
|
## Remove leading space
|
|
TAGS="$(echo ${TAGS} | sed -e 's/^[[:space:]]//')"
|
|
|
|
## Print header if not in JSON
|
|
if [[ "${JSON}" -eq 0 ]]; then
|
|
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
|
|
## Print JSON header
|
|
else
|
|
echo "{"
|
|
echo " \"SEARCH\": \"${TAGS}\","
|
|
echo " \"RESULTS\": ["
|
|
fi
|
|
|
|
|
|
## 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
|
|
|
|
## 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
|
|
if [[ "${COLOUR_TAG}" ]]; then
|
|
COLOUR_TAG="${COLOUR_TAG}\|"
|
|
fi
|
|
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
|
|
SEARCH="${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}" ]] && [[ "${JSON}" -eq 0 ]]; 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
|
|
OUTPUT="$(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
|
|
OUTPUT="$(awk -F "\"*,\"*" '{ printf "%-'${FORMAT}'s | %s\n", $3, $1}' "${csvpath}" \
|
|
| eval "${SEARCH}" )"
|
|
## Print JSON format (full options)
|
|
elif [[ "${JSON}" -eq 1 ]]; then
|
|
OUTPUT="$(awk -F "\"*,\"*" '{ printf "\r\t\t'{'\"Exploit\":\"%s\",\"Path\":\"'${gitpath}/'%s\",\"EDB-ID\":%s},\n", $3, $2, $1}' "${csvpath}" \
|
|
| eval "${SEARCH}" \
|
|
| sed '$ s/,$//g' )"
|
|
## Default view
|
|
else
|
|
OUTPUT=$OUTPUT"$(awk -F "\"*,\"*" '{ printf "%-'${FORMAT}'s | %s\n", $3, $2}' "${csvpath}" \
|
|
| eval "${SEARCH}" \
|
|
| sed "s/| platforms/| ./" )"
|
|
fi
|
|
|
|
echo $OUTPUT
|
|
|
|
## Print footer if not in JSON
|
|
if [[ "${JSON}" -eq 0 ]]; then
|
|
drawline
|
|
## Print JSON footer
|
|
else
|
|
echo " ]"
|
|
echo "}"
|
|
fi
|
|
|
|
## Done
|
|
exit 0
|