
Instead of saving data to insecure temporary files created without mktemp, simply echo them directly to the next stage of a pipeline. Also reset the $software at the beginning of each round, to prevent processing and then having to deduplicate many things, twice.
890 lines
26 KiB
Bash
Executable file
890 lines
26 KiB
Bash
Executable file
#!/bin/bash
|
|
# Name: SearchSploit - Exploit-DB's CLI search tool
|
|
# Version: 4.0.3 (2018-09-24)
|
|
# 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}"
|
|
[[ "${name_in}" == "Paper"* ]] && url="papers" || url="exploits"
|
|
|
|
|
|
## 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}]}"
|
|
[[ "${name}" == "Paper"* ]] && url="papers/${edbdb}/" || url="exploits/${edbdb}/"
|
|
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
|