From 85361a1879756b58c234f58579b81bd41e32272b Mon Sep 17 00:00:00 2001 From: g0tmi1k Date: Thu, 11 Jun 2015 14:16:29 +0100 Subject: [PATCH] SearchSploit - Code clean up & new features + Header will display full path (e.g. `/usr/share/exploitdb/platforms`) + Add 'Web Link' (`-w`) to show URLs + Add 'EDB-ID' (`--id`) to show only EDB-ID values + Add colour mode - will highlight results by default (`--colour` to disable it) + Better performance (Less pipes - but more awks. _So theres still work_). + Search results are more accurate (doesn't search path - only exploit title) --- searchsploit | 320 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 202 insertions(+), 118 deletions(-) diff --git a/searchsploit b/searchsploit index 7ad78196b..f5103ee46 100755 --- a/searchsploit +++ b/searchsploit @@ -1,156 +1,240 @@ #!/bin/bash -# exploitdb CLI search tool -# Version 3 -# Written by Unix-Ninja +# Name: searchsploit - Exploit-DB's CLI search tool +# Version: 3.1 (Release date: 2015-06-11) +# Written by: Offensive Security, Unix-Ninja & g0tmi1k +# Homepage: https://github.com/offensive-security/exploit-database -gitremote=https://github.com/offensive-security/exploit-database.git -gitpath=/usr/share/exploitdb -csvpath=${gitpath}/files.csv -progname=`basename $0` -TAGS= -SCASE='-i' +## NOTE: +# Exit code '0' means finished normally +# 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 +TAGS="" +SCASE="tolower" UPDATE=0 VERBOSE=0 +WEBLINK=0 +EDBID=0 +COLOUR='true' -# NOTE: -# Exit code 0 means finished normally -# Exit code 6 means updated from github -# if files.csv is in the searchsploit path, use that -if [ -f "$( dirname $0 )/files.csv" ]; then - csvpath="$( dirname $0 )/files.csv" +## 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 + +## Usage info function usage() { - echo "Usage: $progname [options] term1 [term2] ... [termN]" - echo "Example: $progname oracle windows local" - echo - echo "=========" - echo " Options " - echo "=========" - echo " -c Perform case-sensitive searches; by default, searches will" - echo " try to be greedy" - echo " -h, --help Show help screen" - echo " -u Update db from git" - echo " -v By setting verbose output, description lines are allowed to" - echo " overflow their columns" - echo - echo "=======" - echo " NOTES " - echo "=======" - echo " * Use any number of search terms you would like (minimum: 1)" - echo " * Search terms are not case sensitive, and order is irrelevant" - echo " * When updating from git, searches will be ignored" - exit 1 + echo "Usage: ${progname} [options] term1 [term2] ... [termN]" + echo "Example: ${progname} oracle windows local" + echo + echo "=========" + echo " Options " + echo "=========" + echo " -c, --case Perform case-sensitive searches. (default is insensitive)" + echo " -h, --help Show this help screen" + echo " -u, --update Update Database from GIT" + echo " -v, --verbose Verbose output. (Title lines are allowed to overflow their columns)" + echo " -w, --www Show URLs to Exploit-DB.com rather than local path" + echo " --colour Disables colour highlighting on match" + echo " --id Display EDB-ID value rather than local path" + echo + echo "=======" + echo " Notes " + echo "=======" + echo " * Use any number of search terms you would like (minimum: 1)" + echo " * Search terms are not case sensitive, and order is irrelevant" + echo " * When updating from git, searches will be ignored" + exit 1 } -# dynamically set column widths -COL2=35 -COL1=$(( `tput cols` - $COL2 - 1 )) -# check for empty args +## 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 + usage >&2 fi -# parse long arguments + +## Parse long arguments ARGS="-" -for param in $@; do - if [ "$param" == "--help" ]; then - usage >&2 - else - if [ "${param:0:1}" == "-" ]; then - ARGS=$ARGS${param:1} - shift - continue - fi - TAGS="$TAGS $param" +for param in "$@"; do + if [ "${param}" == "--help" ]; then + usage >&2 + elif [ "${param}" == "--web" ]; then + WEBLINK=1 + elif [ "${param}" == "--case" ]; then + SCASE='' + elif [ "${param}" == "--update" ]; then + UPDATE=1 + elif [ "${param}" == "--verbose" ]; then + VERBOSE=1 + elif [ "${param}" == "--id" ]; then + EDBID=1 + elif [ "${param}" == "--colour" ] || [ "${param}" == "--color" ]; then + COLOUR='' + else + if [ "${param:0:1}" == "-" ]; then + ARGS=$ARGS${param:1} + shift + continue fi + TAGS="${TAGS} ${param}" + fi done -# parse short arguments -while getopts "chuv" arg $ARGS; do - if [ "$arg" = "?" ]; then - usage >&2; - fi - case $arg in - c) SCASE='';; - h) usage >&2;; - u) UPDATE=1;; - v) VERBOSE=1;; - esac - shift $((OPTIND-1)) + +## Parse short arguments +while getopts "uchvw" arg "$ARGS"; do + if [ "$arg" = "?" ]; then + usage >&2; + fi + case $arg in + c) SCASE='';; + h) usage >&2;; + u) UPDATE=1;; + v) VERBOSE=1;; + w) WEBLINK=1;; + esac + shift $(( OPTIND - 1 )) done -# was an update requested? + +## Was an update requested? if [ "$UPDATE" -eq 1 ]; then - 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 github - git pull origin master - # if conflicts, clean and try again - if [ "$?" -ne 0 ]; then - git clean -d -fx "" - git pull origin master - fi + cd ${gitpath}/ - echo "Update finished." - exit 6 + # 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 fi -# print header -printf "%0.s-" `eval echo {1..$(( $COL1 + 1 ))}` -echo -n " " -printf "%0.s-" `eval echo {1..$(( $COL2 - 1 ))}` -printf "%-${COL1}s %s" " Description" -echo "| Path" +## Dynamically set column widths +if [[ ${WEBLINK} -eq '1' ]]; then + COL2=45 +else + COL2=34 +fi +COL1=$(( $( tput cols ) - COL2 - 1 )) -printf "%0.s-" `eval echo {1..$(( $COL1 + 1 ))}` -echo -n " " -printf "%0.s-" `eval echo {1..$(( $COL2 - 1 ))}` -echo -# create search command +## 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 + +## Create (AND) search command SEARCH= -for tag in $TAGS; do - if [ "$SEARCH" ]; then - SEARCH="$SEARCH |" - fi - SEARCH="$SEARCH fgrep $SCASE \"$tag\"" -done +for tag in ${TAGS}; do + if [ "${SEARCH}" ]; then + SEARCH="${SEARCH}/ && ${SCASE}(\$1) ~ /" + fi -# set LANG variable to avoid illegal byte sequence errors in sed + if [ "${COLOUR}" ]; then + COLOUR="${COLOUR}\|${tag}" + fi + + if [[ ${SCASE} ]]; then + tag="$( echo ${tag} | tr '[:upper:]' '[:lower:]' )" + fi + + SEARCH="${SEARCH}${tag}" +done +SEARCH="awk -F '[|]' '${SCASE}(\$1) ~ /${SEARCH}/ {print}'" + +if [ "${COLOUR}" ]; then + SEARCH="${SEARCH} | grep --color=always -ie \"\${COLOUR}\"" +fi + + +## Set LANG variable to avoid illegal byte sequence errors LANG=C -# search, format, and print results -if [ "$VERBOSE" -eq 0 ]; then - FORMAT=$COL1'.'$COL1 + +## Search, format, and print results +if [ "${VERBOSE}" -eq 0 ]; then + FORMAT=${COL1}'.'${COL1} else - FORMAT=$COL1 + FORMAT=${COL1} fi - cat $csvpath \ - | eval $SEARCH \ - | awk -F "\"*,\"*" '{ printf "%-'$FORMAT's | %s\n", $3, $2}' \ - | sed " s/| platforms/| /" \ - | eval $SEARCH -printf "%0.s-" `eval echo {1..$(( $COL1 + 1 ))}` -echo -n " " -printf "%0.s-" `eval echo {1..$(( $COL2 - 1 ))}` +## Web link format? +if [[ ${WEBLINK} -eq '1' ]]; then + ## Magic search Fu + awk -F "\"*,\"*" '{ printf "%-'${FORMAT}'s | %s\n", $3, "https://www.exploit-db.com/exploits/"$1"/"}' "${csvpath}" \ + | eval "${SEARCH}" \ + +elif [[ ${EDBID} -eq '1' ]]; then + ## Magic search Fu + awk -F "\"*,\"*" '{ printf "%-'${FORMAT}'s | %s\n", $3, $1}' "${csvpath}" \ + | eval "${SEARCH}" \ + +else + ## Magic search Fu + awk -F "\"*,\"*" '{ printf "%-'${FORMAT}'s | %s\n", $3, $2}' "${csvpath}" \ + | eval "${SEARCH}" \ + | sed "s/| platforms/| ./" +fi + + +## Print footer +drawline + + +## Done exit 0 +