907 lines
26 KiB
Bash
Executable file
907 lines
26 KiB
Bash
Executable file
#!/bin/bash
|
|
# Name: SearchSploit - Exploit-DB's CLI search tool
|
|
# Version: 4.0.5 (2019-03-27)
|
|
# Written by: Offensive Security, Unix-Ninja, and g0tmi1k
|
|
# Homepage: https://github.com/offensive-security/exploitdb
|
|
# Manual: https://www.exploit-db.com/searchsploit
|
|
#
|
|
## NOTE:
|
|
# Exit code '0' means finished normally
|
|
# Exit code '1' means something went wrong
|
|
# Exit code '2' means help screen
|
|
# Exit code '6' means updated packages (APT, brew or Git)
|
|
#-----------------------------------------------------------------------------#
|
|
|
|
|
|
## Settings File
|
|
rc_file=""
|
|
|
|
|
|
## Default options
|
|
CLIPBOARD=0
|
|
COLOUR=1
|
|
EDBID=0
|
|
EXACT=0
|
|
EXAMINE=0
|
|
FILEPATH=1
|
|
GETPATH=0
|
|
JSON=0
|
|
MIRROR=0
|
|
OVERFLOW=0
|
|
SCASE=0
|
|
VERBOSE=0
|
|
WEBLINK=0
|
|
XML=0
|
|
COLOUR_TAG=""
|
|
TAGS=""
|
|
SEARCH=""
|
|
EXCLUDE=""
|
|
CASE_TAG_GREP="-i"
|
|
CASE_TAG_FGREP="tolower"
|
|
AWK_SEARCH=""
|
|
COLOUR_OFF_GREP=
|
|
COLOUR_ON_GREP=
|
|
|
|
|
|
## Check if our grep supports --color
|
|
if grep --help 2>&1 | grep "[-]-color" >/dev/null 2>&1 ; then
|
|
COLOUR_OFF_GREP="--color=never"
|
|
COLOUR_ON_GREP="--color=always"
|
|
fi
|
|
|
|
|
|
## Set LANG variable to avoid illegal byte sequence errors
|
|
LANG=C
|
|
|
|
|
|
## Usage info
|
|
function usage()
|
|
{
|
|
echo " Usage: ${progname} [options] term1 [term2] ... [termN]"
|
|
echo ""
|
|
echo "=========="
|
|
echo " Examples "
|
|
echo "=========="
|
|
echo " ${progname} afd windows local"
|
|
echo " ${progname} -t oracle windows"
|
|
echo " ${progname} -p 39446"
|
|
echo " ${progname} linux kernel 3.2 --exclude=\"(PoC)|/dos/\""
|
|
echo " ${progname} linux reverse password"
|
|
echo ""
|
|
echo " For more examples, see the manual: https://www.exploit-db.com/searchsploit"
|
|
echo ""
|
|
echo "========="
|
|
echo " Options "
|
|
echo "========="
|
|
echo " -c, --case [Term] Perform a case-sensitive search (Default is inSEnsITiVe)."
|
|
echo " -e, --exact [Term] Perform an EXACT match on exploit title (Default is AND) [Implies \"-t\"]."
|
|
echo " -h, --help Show this help screen."
|
|
echo " -j, --json [Term] Show result in JSON format."
|
|
echo " -m, --mirror [EDB-ID] Mirror (aka copies) an exploit to the current working directory."
|
|
echo " -o, --overflow [Term] Exploit titles are allowed to overflow their columns."
|
|
echo " -p, --path [EDB-ID] Show the full path to an exploit (and also copies the path to the clipboard if possible)."
|
|
echo " -t, --title [Term] Search JUST the exploit title (Default is title AND the file's path)."
|
|
echo " -u, --update Check for and install any exploitdb package updates (deb or git)."
|
|
echo " -w, --www [Term] Show URLs to Exploit-DB.com rather than the local path."
|
|
echo " -x, --examine [EDB-ID] Examine (aka opens) the exploit using \$PAGER."
|
|
echo " --colour Disable colour highlighting in search results."
|
|
echo " --id Display the EDB-ID value rather than local path."
|
|
echo " --nmap [file.xml] Checks all results in Nmap's XML output with service version (e.g.: nmap -sV -oX file.xml)."
|
|
echo " Use \"-v\" (verbose) to try even more combinations"
|
|
echo " --exclude=\"term\" Remove values from results. By using \"|\" to separated you can chain multiple values."
|
|
echo " e.g. --exclude=\"term1|term2|term3\"."
|
|
echo ""
|
|
echo "======="
|
|
echo " Notes "
|
|
echo "======="
|
|
echo " * You can use any number of search terms."
|
|
echo " * Search terms are not case-sensitive (by default), and ordering 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 using numbers - i.e. versions)."
|
|
echo " * When updating or displaying help, search terms will be ignored."
|
|
echo ""
|
|
exit 2
|
|
}
|
|
|
|
|
|
## Update database check
|
|
function update()
|
|
{
|
|
arraylength="${#files_array[@]}"
|
|
for (( i=0; i<${arraylength}; i++ )); do
|
|
## Check to see if we already have the value
|
|
[[ "${tmp_package[*]}" =~ "${package_array[${i}]}" ]] && continue
|
|
|
|
## Else save all the information
|
|
tmp_git+=("${git_array[${i}]}")
|
|
tmp_path+=("${path_array[${i}]}")
|
|
tmp_package+=("${package_array[${i}]}")
|
|
done
|
|
|
|
|
|
## Loop around all the new arrays
|
|
arraylength="${#tmp_git[@]}"
|
|
for (( i=0; i<${arraylength}; i++ )); do
|
|
git="${tmp_git[${i}]}"
|
|
path="${tmp_path[${i}]}"
|
|
package="${tmp_package[${i}]}"
|
|
|
|
# Update from the repos (e.g. Kali)
|
|
dpkg -l "${package}" 2>/dev/null >/dev/null
|
|
if [[ "$?" == "0" ]]; then
|
|
updatedeb "${package}"
|
|
else
|
|
# Update from homebrew (e.g. OSX)
|
|
brew 2>/dev/null >/dev/null
|
|
if [[ "$?" == "0" ]]; then
|
|
# This only really only updates "./searchsploit". The rest (can) come via git as its updated more frequently
|
|
updatedbrew "${package}"
|
|
fi
|
|
|
|
# Update via Git
|
|
updategit "${package}" "${path}" "${git}"
|
|
fi
|
|
done
|
|
|
|
# Done
|
|
exit 6
|
|
}
|
|
|
|
|
|
## Update database (via .deb/apt)
|
|
function updatedeb()
|
|
{
|
|
package_in="${1}"
|
|
|
|
echo -e "[i] Updating via apt package management (Expect weekly-ish updates): ${package_in}\n"
|
|
|
|
sudo apt update \
|
|
|| echo -e "\n[-] Issue with apt update (Please check network connectivity & apt SourcesList values)." 1>&2
|
|
sudo apt -y install "${package_in}" \
|
|
|| echo -e "\n[-] Issue with apt upgrade." 1>&2
|
|
|
|
echo -e "\n[*] apt update finished."
|
|
}
|
|
|
|
|
|
## Update database (via homebrew)
|
|
function updatedbrew()
|
|
{
|
|
package_in="${1}"
|
|
|
|
echo -e "[i] Updating via brew package management.\n"
|
|
|
|
brew update \
|
|
|| echo -e "\n[-] Issue with brew update (Please check network connectivity)." 1>&2
|
|
brew upgrade "${package_in}"
|
|
|
|
echo -e "\n[*] Brew update finished."
|
|
}
|
|
|
|
|
|
## Update database (via Git)
|
|
function updategit()
|
|
{
|
|
package_in="${1}"
|
|
path_in="${2}"
|
|
git_in="${3}"
|
|
|
|
echo -e "[i] Updating via Git (Expect daily updates): ${package_in} ~ ${path_in}\n"
|
|
|
|
## Make sure we are in the correct folder
|
|
mkdir -p "${path_in}/" 2>/dev/null \
|
|
|| sudo mkdir -p "${path_in}/"
|
|
cd "${path_in}/"
|
|
|
|
## Are we in a Git repo?
|
|
if [[ "$( git rev-parse --is-inside-work-tree 2>/dev/null )" != "true" ]]; then
|
|
if [[ "$( ls )" = "" ]]; then
|
|
# If directory is empty, just clone
|
|
echo -e "\n[-] Nothing here (${path_in}). Starting fresh..."
|
|
git clone -v "${git_in}" "${path_in}/" 2>/dev/null \
|
|
|| sudo git clone -v "${git_in}" "${path_in}/"
|
|
fi
|
|
fi
|
|
|
|
# Is our Git remote added? (aka wouldn't be via homebrew method)
|
|
if [[ "$( git remote -v )" != *"upstream"*"${git_in}"* ]]; then
|
|
echo -e "\n[-] Missing Git remote upstream (${git_in})"
|
|
git init 2>/dev/null \
|
|
|| sudo git init
|
|
git remote add upstream "${git_in}" 2>/dev/null \
|
|
|| sudo git remote add upstream "${git_in}"
|
|
fi
|
|
|
|
# Make sure to prep checkout first
|
|
git checkout -- . 2>/dev/null \
|
|
|| sudo git checkout -- .
|
|
|
|
# Update from git
|
|
echo -e "\n[i] Git pull'ing"
|
|
git pull -v upstream master 2>/dev/null \
|
|
|| sudo git pull -v upstream master
|
|
|
|
# If conflicts, clean and try again
|
|
if [[ "$?" -ne 0 ]]; then
|
|
echo -e "\n[-] Git conflict"
|
|
git clean -d -fx "" \
|
|
|| sudo git clean -d -fx ""
|
|
git pull -v upstream master \
|
|
|| sudo git pull -v upstream master
|
|
fi
|
|
|
|
echo -e "\n[*] Git update finished."
|
|
echo "[i] Path: ${path_in}/"
|
|
}
|
|
|
|
|
|
## 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 ""
|
|
}
|
|
|
|
|
|
## Used in searchsploitout/nmap's XML
|
|
function validterm()
|
|
{
|
|
## Check to see if its any phrases which would give a TON of incorrect results
|
|
if [ "$( echo ${1} | tr '[:upper:]' '[:lower:]' )" == "microsoft" ] \
|
|
|| [ "$( echo ${1} | tr '[:upper:]' '[:lower:]' )" == "microsoft windows" ] \
|
|
|| [ "$( echo ${1} | tr '[:upper:]' '[:lower:]' )" == "windows" ] \
|
|
|| [ "$( echo ${1} | tr '[:upper:]' '[:lower:]' )" == "apache" ] \
|
|
|| [ "$( echo ${1} | tr '[:upper:]' '[:lower:]' )" == "ftp" ] \
|
|
|| [ "$( echo ${1} | tr '[:upper:]' '[:lower:]' )" == "http" ] \
|
|
|| [ "$( echo ${1} | tr '[:upper:]' '[:lower:]' )" == "linux" ] \
|
|
|| [ "$( echo ${1} | tr '[:upper:]' '[:lower:]' )" == "net" ] \
|
|
|| [ "$( echo ${1} | tr '[:upper:]' '[:lower:]' )" == "network" ] \
|
|
|| [ "$( echo ${1} | tr '[:upper:]' '[:lower:]' )" == "oracle" ] \
|
|
|| [ "$( echo ${1} | tr '[:upper:]' '[:lower:]' )" == "ssh" ] \
|
|
|| [ "$( echo ${1} | tr '[:upper:]' '[:lower:]' )" == "unknown" ]; then
|
|
echo -e "[-] Skipping term: ${1} (Term is too general. Please re-search manually: $0 ${arg} ${1})\n" 1>&2
|
|
## Issues, return with something
|
|
return 1
|
|
fi
|
|
|
|
## No issues, return without anything
|
|
return 0
|
|
}
|
|
|
|
|
|
## Used in searchsploitout/nmap's XML
|
|
function searchsploitout()
|
|
{
|
|
## Make sure there is a value
|
|
[ "${software}" = "" ] && return
|
|
|
|
#echo "" 1>&2
|
|
|
|
arg="-t" ## Title search by default!
|
|
[[ "${JSON}" == "1" ]] && arg="${arg} --json"
|
|
[[ "${OVERFLOW}" == "1" ]] && arg="${arg} --overflow"
|
|
[[ "${WEBLINK}" == "1" ]] && arg="${arg} --www"
|
|
[[ "${COLOUR}" != "1" ]] && arg="${arg} --colour"
|
|
[[ "${EDBID}" == "1" ]] && arg="${arg} --id"
|
|
|
|
## Try and remove terms that could confuse searches
|
|
#software=$( echo "${software}" | sed 's_/_ _g' )
|
|
software=$( echo "${software}" | sed -e 's/[^a-zA-Z0-9]/ /g' )
|
|
|
|
if [[ "${VERBOSE}" -eq 1 ]]; then
|
|
## Loop each word?
|
|
tmp=""
|
|
for word in $( echo ${software} ); do
|
|
## Add current search term on
|
|
tmp="${tmp}${word} "
|
|
|
|
## Check to see if its any phrases which would give a TON of incorrect results
|
|
validterm "${tmp}" \
|
|
|| continue
|
|
|
|
## Feedback
|
|
echo "[i] $0 ${arg} ${tmp}" 1>&2
|
|
out=$( bash "$0" ${arg} ${tmp} )
|
|
|
|
## Are there too many result?
|
|
lines=$( echo -e "${out}" | wc -l )
|
|
if [[ "${lines}" -gt 100 ]]; then
|
|
echo -e "[-] Skipping output: ${tmp} (Too many results. Please re-search manually: $0 ${arg} ${tmp})\n" 1>&2
|
|
## Are there any result?
|
|
elif [[ "${lines}" -gt 5 ]]; then
|
|
echo -e "${out}\n\n"
|
|
## If there's no results
|
|
else
|
|
break
|
|
fi
|
|
done
|
|
|
|
## Padding between loops
|
|
echo -e "\n\n" 1>&2
|
|
else
|
|
## Check to see if its any phrases which would give a TON of incorrect results
|
|
validterm "${software}" \
|
|
|| return
|
|
|
|
## Feedback
|
|
echo "[i] $0 ${arg} ${software}" 1>&2
|
|
out=$( bash "$0" ${arg} ${software} )
|
|
|
|
## Are there too many result?
|
|
lines=$( echo -e "${out}" | wc -l )
|
|
if [[ "${lines}" -gt 100 ]]; then
|
|
echo -e "[-] Skipping output: ${software} (Too many results. Please re-search manually: $0 ${arg} ${software})\n" 1>&2
|
|
## Are there any result?
|
|
elif [[ "${lines}" -gt 5 ]]; then
|
|
echo -e "${out}\n\n"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
|
|
## Read XML file
|
|
function nmapxml()
|
|
{
|
|
## Feedback to the end user
|
|
echo -e "[i] Reading: '${FILE}'\n"
|
|
|
|
## Read in XMP (IP, name, service and version)
|
|
xmllint --xpath '//address/@addr|//service/@name|//service/@product|//service/@version' "${FILE}" \
|
|
| sed -e $'s/addr=/\\\n[IP] /g; s/name=/\\\n[NAME] /g; s/product=/\\\n[PRODUCT] /g;s/" version="/\\\n[VERSION] /g; s/"//g' \
|
|
| grep -v '\[IP\].*\:' \
|
|
| while read line; do
|
|
type=$( echo "${line}" | cut -d" " -f 1 )
|
|
input=$( echo "${line}" | cut -d" " -f 2- )
|
|
|
|
case "${type}" in
|
|
"[IP]")
|
|
#[[ "${VERBOSE}" -eq 1 ]] && echo -e "\n\n\e[32m[*] IP: ${input}\e[39m" 1>&2
|
|
;;
|
|
"[NAME]")
|
|
## If we have already looped around and got something, save it before moving onto the current value
|
|
if [[ "${software}" ]]; then
|
|
#searchsploitout
|
|
echo "${software}"
|
|
fi
|
|
## Something is better than nothing. Will just go on the default service that matches the port. e.g. domain
|
|
software="${input}"
|
|
## Might not get any more than this, if -sV failed
|
|
;;
|
|
"[PRODUCT]")
|
|
## We have a name, but no version (yet?) e.g. dnsmasq
|
|
software="${input}"
|
|
;;
|
|
"[VERSION]")
|
|
software="${software} ${input}"
|
|
## Name & version. There isn't any more information to get, game over. e.g. dnsmasq 2.72
|
|
echo "${software}"
|
|
software=
|
|
;;
|
|
esac
|
|
done | tr '[:upper:]' '[:lower:]' | awk '!x[$0]++' | while read software; do
|
|
searchsploitout
|
|
done
|
|
}
|
|
|
|
|
|
## Build search terms
|
|
function buildterms()
|
|
{
|
|
tag_in="${1}"
|
|
|
|
## If we are to use colour ("--colour"), add the values to search for between "or"
|
|
if [[ "${COLOUR}" -eq 1 ]]; then
|
|
[[ "${COLOUR_TAG}" ]] && COLOUR_TAG="${COLOUR_TAG}|"
|
|
COLOUR_TAG="${COLOUR_TAG}${tag_in}"
|
|
fi
|
|
|
|
## Search both title AND path
|
|
if [[ "${FILEPATH}" -eq 1 ]]; then
|
|
## Search command for each term (with case sensitive flag, "-c")
|
|
SEARCH="${SEARCH} | grep ${COLOUR_OFF_GREP} -F ${CASE_TAG_GREP} \"${tag_in}\""
|
|
## Search just the title, NOT the path ("-t"/"-e")
|
|
else
|
|
## If there is already a value, prepend text to get ready
|
|
[[ "${AWK_SEARCH}" ]] && AWK_SEARCH="${AWK_SEARCH}/ && ${CASE_TAG_FGREP}(\$3) ~ /"
|
|
|
|
## Escape any slashes
|
|
tag_in="$( echo ${tag_in} | sed 's_/_\\/_g' )"
|
|
|
|
## Case sensitive ("-c")?
|
|
if [[ "${SCASE}" -eq 1 ]]; then
|
|
AWK_SEARCH="${AWK_SEARCH}${tag_in}"
|
|
else
|
|
AWK_SEARCH="${AWK_SEARCH}$( echo ${tag_in} | tr '[:upper:]' '[:lower:]' )"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
|
|
## Read in the values from files_*.csv
|
|
function findresults()
|
|
{
|
|
file_in="${1}"
|
|
path_in="${2}"
|
|
name_in="${3}"
|
|
|
|
if [[ "${name_in}" == "Paper"* ]]; then
|
|
url="papers"
|
|
elif [[ "${name_in}" == "Shellcode"* ]]; then
|
|
url="shellcodes"
|
|
else
|
|
url="exploits"
|
|
fi
|
|
|
|
|
|
## JSON require full options
|
|
if [[ "${JSON}" -eq 1 ]]; then
|
|
## Read in (id, title, path, date, author, type, platform) separated between commas
|
|
SEARCH="awk -F '[,]' '{print \$1\",\"\$2\",\"\$3\",\"\$4\",\"\$5\",\"\$6\",\"\$7}' \"${path_in}/${file_in}\""
|
|
else
|
|
## Read in (id, title, path) separated between commas (as these are the only visible fields)
|
|
SEARCH="awk -F '[,]' '{print \$1\",\"\$2\",\"\$3}' \"${path_in}/${file_in}\""
|
|
fi
|
|
|
|
|
|
## EXACT search command ("-e")?
|
|
if [[ "${EXACT}" -eq 1 ]]; then
|
|
buildterms "${TAGS}"
|
|
## or AND search command?
|
|
else
|
|
## For each term
|
|
for TAG in ${TAGS}; do
|
|
buildterms "${TAG}"
|
|
done
|
|
fi
|
|
|
|
|
|
## If we are NOT to use the path name ("-t"/"-e")
|
|
[[ "${FILEPATH}" -eq 0 ]] && SEARCH="${SEARCH} | awk -F '[,]' '${CASE_TAG_FGREP}(\$3) ~ /${AWK_SEARCH}/ {print}'"
|
|
|
|
|
|
## If we are to use colour ("--colour"), add the value here
|
|
if [[ "${COLOUR_TAG}" ]] && [[ "${JSON}" -eq 0 ]]; then
|
|
COLOUR_TAG="grep ${COLOUR_ON_GREP} -iE \"${COLOUR_TAG}|$\""
|
|
fi
|
|
|
|
|
|
## Dynamically set column widths to the current screen size
|
|
[[ "${WEBLINK}" -eq 1 ]] && COL2=45 || COL2=$(( ${#path_in} + 21 ))
|
|
COL1=$(( $( tput cols ) - COL2 - 1 ))
|
|
|
|
|
|
## Search, format, and print results (--overflow)
|
|
if [[ "${OVERFLOW}" -eq 1 ]]; then
|
|
FORMAT_COL1=${COL1}
|
|
else
|
|
FORMAT_COL1=${COL1}'.'${COL1}
|
|
fi
|
|
|
|
## Maximum length COL2 can be
|
|
FORMAT_COL2=$(( ${COL2} - 2 ))
|
|
|
|
## Strip un-wanted values
|
|
SEARCH="${SEARCH} | sed 's/\"//g'"
|
|
|
|
|
|
## Remove any terms not wanted from the search
|
|
[[ "${EXCLUDE}" ]] && SEARCH="${SEARCH} | grep -vEi '${EXCLUDE}'"
|
|
|
|
|
|
## Magic search Fu
|
|
## Print JSON format (full options) ("--json")?
|
|
if [[ "${JSON}" -eq 1 ]]; then
|
|
## Web link format ("--json --www")?
|
|
if [[ "${WEBLINK}" -eq 1 ]]; then
|
|
OUTPUT="$( eval ${SEARCH} \
|
|
| awk -F ',' '{ printf "\\n\\t\\t'{'\"Title\":\"%s\",\"URL\":\"https://www.exploit-db.com/'${url}'/%s\"},", $3, $1 }' )"
|
|
## Just the EDB-ID ("--json --id")?
|
|
elif [[ "${EDBID}" -eq 1 ]]; then
|
|
OUTPUT="$( eval ${SEARCH} \
|
|
| awk -F ',' '{ printf "\\n\\t\\t'{'\"Title\":\"%s\",\"EDB-ID\":\"%s\",\"Path\":\"'${path_in}/'%s\"},", $3, $1, $2 }' )"
|
|
## Default JSON ("--json")?
|
|
else
|
|
OUTPUT="$( eval ${SEARCH} \
|
|
| awk -F ',' '{ printf "\\n\\t\\t'{'\"Title\":\"%s\",\"EDB-ID\":\"%s\",\"Date\":\"%s\",\"Author\":\"%s\",\"Type\":\"%s\",\"Platform\":\"%s\",\"Path\":\"'${path_in}/'%s\"},", $3, $1, $4, $5, $6, $7, $2 }' )"
|
|
fi
|
|
OUTPUT="$( echo -e ${OUTPUT} \
|
|
| sort \
|
|
| sed '$ s/,$//' )"
|
|
## Web link format ("--www")?
|
|
elif [[ "${WEBLINK}" -eq 1 ]]; then
|
|
OUTPUT="$( eval ${SEARCH} \
|
|
| awk -F ',' '{ printf "%-'${FORMAT_COL1}'s | %s\n", $3, "https://www.exploit-db.com/'${url}'/"$1 }' \
|
|
| sort )"
|
|
## Just the EDB-ID ("--id")?
|
|
elif [[ "${EDBID}" -eq 1 ]]; then
|
|
OUTPUT="$( eval ${SEARCH} \
|
|
| awk -F ',' '{ printf "%-'${FORMAT_COL1}'s | %s\n", $3, $1 }' \
|
|
| sort )"
|
|
## Default view
|
|
else
|
|
OUTPUT="$( eval ${SEARCH} \
|
|
| awk -F ',' '{ printf "%-'${FORMAT_COL1}'s | %.'${FORMAT_COL2}'s\n", $3, $2 }' \
|
|
| sort )"
|
|
fi
|
|
|
|
|
|
## Display colour highlights ("--colour")?
|
|
if [[ "${COLOUR_TAG}" ]] && [[ "${JSON}" -eq 0 ]]; then
|
|
[[ "${OUTPUT}" ]] && OUTPUT=$( echo -e "${OUTPUT}" | eval ${COLOUR_TAG} )
|
|
fi
|
|
}
|
|
|
|
|
|
function printresults()
|
|
{
|
|
title_in="${1}"
|
|
path_in="${2}"
|
|
json_title="$(echo ${title_in} | tr /a-z/ /A-Z/)"
|
|
|
|
|
|
## Print header if in JSON ("--json")
|
|
if [[ "${JSON}" -eq 1 ]]; then
|
|
printf ",\n\t\"DB_PATH_${json_title}\": \"${path_in}\",\n"
|
|
printf "\t\"RESULTS_${json_title}\": ["
|
|
## ASCII table
|
|
else
|
|
drawline
|
|
printf "%-${COL1}s %s" " ${title_in} Title"
|
|
if [[ "${WEBLINK}" -eq 1 ]]; then
|
|
echo "| URL"
|
|
elif [[ "${EDBID}" -eq 1 ]]; then
|
|
echo "| EDB-ID"
|
|
else
|
|
echo "| Path"
|
|
#echo " > Results (0)"
|
|
printf "%-${COL1}s "
|
|
echo "| (${path_in}/)"
|
|
fi
|
|
drawline
|
|
fi
|
|
|
|
|
|
## Show content
|
|
[[ "${OUTPUT}" ]] && echo "${OUTPUT}"
|
|
|
|
|
|
## Print footer if in JSON ("--json")
|
|
if [[ "${JSON}" -eq 1 ]]; then
|
|
printf "\t]"
|
|
else
|
|
drawline
|
|
fi
|
|
}
|
|
|
|
|
|
#-----------------------------------------------------------------------------#
|
|
|
|
|
|
## Locate setting file
|
|
## User home folder config
|
|
if [[ -f "${HOME}/.searchsploit_rc" ]]; then
|
|
rc_file="${HOME}/.searchsploit_rc"
|
|
## Global config
|
|
elif [[ -f "/etc/searchsploit_rc" ]]; then
|
|
rc_file="/etc/searchsploit_rc"
|
|
## Method #1 - File itself
|
|
elif [[ -f "$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)/.searchsploit_rc" ]]; then
|
|
rc_file="$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)/.searchsploit_rc"
|
|
## Method #2 - Symbolic link
|
|
elif [[ -f "$(dirname "$(readlink "$0")")/.searchsploit_rc" ]]; then
|
|
rc_file="$(dirname "$(readlink "$0")")/.searchsploit_rc"
|
|
## Manually specified?
|
|
elif [[ ! -f "${rc_file}" ]]; then
|
|
echo "[!] Could not find: rc_file ~ ${rc_file}"
|
|
exit 1
|
|
fi
|
|
|
|
|
|
## Use config file
|
|
source "${rc_file}"
|
|
|
|
|
|
#-----------------------------------------------------------------------------#
|
|
|
|
|
|
## Check for empty arguments
|
|
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}" == "--examine" ]] || [[ "${param}" == "--open" ]] || [[ "${param}" == "--view" ]]; then
|
|
GETPATH=1
|
|
EXAMINE=1
|
|
elif [[ "${param}" == "--help" ]]; then
|
|
usage >&2
|
|
elif [[ "${param}" == "--json" ]]; then
|
|
JSON=1
|
|
elif [[ "${param}" == "--mirror" ]] || [[ "${param}" == "--copy" ]] || [[ "${param}" == "--dup" ]] || [[ "${param}" == "--duplicate" ]]; then
|
|
GETPATH=1
|
|
MIRROR=1
|
|
elif [[ "${param}" == "--overflow" ]]; then
|
|
OVERFLOW=1
|
|
elif [[ "${param}" == "--path" ]]; then
|
|
GETPATH=1
|
|
CLIPBOARD=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
|
|
elif [[ "${param}" == "--nmap" ]]; then
|
|
XML=1
|
|
elif [[ "${param}" =~ "--exclude=" ]]; then
|
|
EXCLUDE="$( echo "${param}" | cut -d '=' -f 2- )"
|
|
elif [[ "${param}" == "--verbose" ]]; then
|
|
VERBOSE=1
|
|
else
|
|
if [[ "${param:0:1}" == "-" ]]; then
|
|
ARGS=${ARGS}${param:1}
|
|
shift
|
|
continue
|
|
fi
|
|
TAGS="${TAGS} ${param//\`/_}"
|
|
fi
|
|
done
|
|
|
|
|
|
## Parse short arguments
|
|
while getopts "cehjmnoptuvwx" arg "${ARGS}"; do
|
|
if [[ "${arg}" = "?" ]]; then
|
|
usage >&2;
|
|
fi
|
|
case ${arg} in
|
|
c) SCASE=1;;
|
|
e) EXACT=1;;
|
|
h) usage >&2;;
|
|
j) JSON=1;;
|
|
m) GETPATH=1; MIRROR=1;;
|
|
n) XML=1;;
|
|
o) OVERFLOW=1;;
|
|
p) GETPATH=1; CLIPBOARD=1;;
|
|
t) FILEPATH=0;;
|
|
u) update;;
|
|
v) VERBOSE=1;;
|
|
w) WEBLINK=1;;
|
|
x) GETPATH=1; EXAMINE=1;;
|
|
esac
|
|
shift $(( OPTIND - 1 ))
|
|
done
|
|
|
|
|
|
#-----------------------------------------------------------------------------#
|
|
|
|
|
|
## Check for files_*.csv
|
|
arraylength="${#files_array[@]}"
|
|
for (( i=0; i<${arraylength}; i++ )); do
|
|
files="${path_array[${i}]}/${files_array[${i}]}"
|
|
|
|
if [[ -f "${files}" ]]; then
|
|
continue
|
|
## Method #1 - File itself
|
|
elif [[ -f "$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)/${files_array[${i}]}" ]]; then
|
|
echo "[i] Found (#1): $(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)/${files_array[${i}]}"
|
|
echo "[i] To remove this message, please edit \"${rc_file}\" for \"${files_array[${i}]}\" (package_array: ${package_array[${i}]})"
|
|
path_array[${i}]="$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)"
|
|
echo
|
|
## Method #2 - Symbolic link
|
|
elif [[ -f "$(dirname "$(readlink "$0")")/${files_array[${i}]}" ]]; then
|
|
echo "[i] Found (#2): $(dirname "$(readlink "$0")")/${files_array[${i}]}"
|
|
echo "[i] To remove this message, please edit \"${rc_file}\" for \"${files_array[${i}]}\" (package_array: ${package_array[${i}]})"
|
|
path_array[${i}]="$(dirname "$(readlink "$0")")"
|
|
echo
|
|
else
|
|
#echo "[!] Could not find: ${files}"
|
|
#echo "[i] To remove this message, please remove \"${files_array[${i}]}\" (package_array: ${package_array[${i}]}) from \"${rc_file}\""
|
|
unset "files_array[${i}]"
|
|
unset "path_array[${i}]"
|
|
unset "name_array[${i}]"
|
|
unset "git_array[${i}]"
|
|
unset "package_array[${i}]"
|
|
#echo
|
|
fi
|
|
done
|
|
|
|
|
|
#-----------------------------------------------------------------------------#
|
|
|
|
|
|
## Read in XML
|
|
if [[ "${XML}" -eq 1 ]]; then
|
|
## Trim white spaces
|
|
FILE=$( echo ${TAGS} | xargs )
|
|
|
|
## Is there a file?
|
|
if [[ ! -f "${FILE}" ]]; then
|
|
echo -e "\n[!] Could not find file: ${FILE}" 1>&2
|
|
exit 1
|
|
fi
|
|
|
|
if ! hash xmllint 2>/dev/null; then
|
|
echo -e "\n[!] Please install xmllint" 1>&2
|
|
echo -e "[i] Kali Linux -> apt -y install libxml2-utils" 1>&2
|
|
exit 1
|
|
fi
|
|
|
|
if [[ "${VERBOSE}" -ne 1 ]]; then
|
|
echo "[i] SearchSploit's XML mode (without verbose enabled). To enable: ${progname} -v --xml..."
|
|
fi
|
|
|
|
## Do the magic
|
|
nmapxml
|
|
|
|
## Done
|
|
exit 0
|
|
fi
|
|
|
|
|
|
## Print the full path. If pbcopy/xclip is available then copy to the clipboard
|
|
if [[ "${GETPATH}" -eq 1 ]]; then
|
|
for exploit in $( echo ${TAGS} ); do
|
|
## Get EDB-ID from input
|
|
edbdb="$( echo ${exploit} | rev | cut -d '/' -f1 | rev | cut -d'-' -f1 | cut -d'.' -f1 | tr -dc '0-9' )"
|
|
|
|
|
|
## Loop until we find something
|
|
arraylength="${#files_array[@]}"
|
|
for (( i=0; i<${arraylength}; i++ )); do
|
|
files="${path_array[${i}]}/${files_array[${i}]}"
|
|
|
|
## Check to see if the files_*.csv has a value
|
|
line=$( grep -m 1 -E "^${edbdb}," "${files}" )
|
|
|
|
if [[ "${line}" ]]; then
|
|
path="$( echo $line | cut -d ',' -f 2 )"
|
|
location="${path_array[${i}]}/${path}"
|
|
name="${name_array[${i}]}"
|
|
|
|
if [[ "${name}" == "Paper"* ]]; then
|
|
url="papers/${edbdb}"
|
|
elif [[ "${name}" == "Shellcode"* ]]; then
|
|
url="shellcodes/${edbdb}"
|
|
else
|
|
url="exploits/${edbdb}"
|
|
fi
|
|
|
|
break
|
|
fi
|
|
done
|
|
|
|
|
|
## Did we find the exploit?
|
|
if [[ -f "${location}" ]]; then
|
|
## Get title
|
|
title=$( grep -m 1 "${path}" "${files}" | cut -d ',' -f 3 | sed 's/"//g' )
|
|
|
|
## File type
|
|
fileinfo="$(file -b "${location}")"
|
|
|
|
## How long is the name?
|
|
PADDING=$(( 9 - ${#name} ))
|
|
|
|
## Display out
|
|
printf "%-${PADDING}s%s"
|
|
echo "${name}: ${title}"
|
|
echo " URL: https://www.exploit-db.com/${url}"
|
|
echo " Path: ${location}"
|
|
echo "File Type: ${fileinfo}"
|
|
echo ""
|
|
|
|
## Copy to clipboard?
|
|
if [[ "${CLIPBOARD}" -eq 1 ]]; then
|
|
## Are any copy programs available?
|
|
if hash xclip 2>/dev/null || hash pbcopy 2>/dev/null; then
|
|
## Linux (Will require $DISPLAY)
|
|
if hash xclip 2>/dev/null; then
|
|
echo -ne "${location}" | xclip -selection clipboard 2>/dev/null
|
|
echo "Copied EDB-ID #${edbdb}'s path to the clipboard."
|
|
## OSX
|
|
elif hash pbcopy 2>/dev/null; then
|
|
echo -ne "${location}" | pbcopy
|
|
echo "Copied EDB-ID #${edbdb}'s path to the clipboard."
|
|
fi
|
|
fi
|
|
|
|
## Done (early!)
|
|
exit 0
|
|
fi
|
|
|
|
## Open the exploit up?
|
|
if [[ "${EXAMINE}" -eq 1 ]]; then
|
|
if [[ "${PAGER}" ]]; then
|
|
/bin/sh -c "${PAGER} ${location}"
|
|
elif [[ -f "$( which pager 2>/dev/null )" ]]; then
|
|
pager "${location}"
|
|
else
|
|
less "${location}"
|
|
fi
|
|
echo -e "\n"
|
|
fi
|
|
|
|
if [[ "${MIRROR}" -eq 1 ]]; then
|
|
cp -i "${location}" "$( pwd )/"
|
|
echo "Copied to: $( pwd )/$( basename ${location} )"
|
|
echo -e "\n"
|
|
fi
|
|
else
|
|
## Feedback
|
|
echo "[!] Could not find EDB-ID #${edbdb}"
|
|
echo -e "\n"
|
|
fi
|
|
done
|
|
|
|
## Done
|
|
exit 0
|
|
fi
|
|
|
|
|
|
#-----------------------------------------------------------------------------#
|
|
|
|
|
|
## If we are doing an exact match ("-e")? If so, do NOT check folder path (Implies "-t").
|
|
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
|
|
|
|
|
|
## Remove leading space
|
|
TAGS="$( echo ${TAGS} | sed -e 's/^[[:space:]]//' )"
|
|
|
|
|
|
#-----------------------------------------------------------------------------#
|
|
|
|
|
|
## Print header if in JSON ("--json")
|
|
[[ "${JSON}" -eq 1 ]] && printf "{\n\t\"SEARCH\": \"${TAGS}\""
|
|
|
|
|
|
## Check for files_*.csv
|
|
arraylength="${#files_array[@]}"
|
|
for (( i=0; i<${arraylength}; i++ )); do
|
|
## Search
|
|
findresults "${files_array[${i}]}" "${path_array[${i}]}" "${name_array[${i}]}"
|
|
## Print results if in JSON ("--json") or if there is any results
|
|
if ([[ "${JSON}" -eq 1 ]] || [[ "${OUTPUT}" ]]); then
|
|
printresults "${name_array[${i}]}" "${path_array[${i}]}"
|
|
## Summary if NOT JSON ("--json")
|
|
elif [[ "${JSON}" -eq 0 ]]; then
|
|
echo "${name_array[${i}]}s: No Result"
|
|
fi
|
|
## Reset
|
|
COLOUR_TAG=""
|
|
done
|
|
|
|
|
|
## Print footer if in JSON ("--json")
|
|
[[ "${JSON}" -eq 1 ]] && printf "\n}\n"
|
|
|
|
|
|
## Done
|
|
exit 0
|