#!/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 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 " -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}" == "--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 ## 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 )) ## 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 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}" ]]; 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