Skip to content

Instantly share code, notes, and snippets.

@ibitebyt3s
Created September 23, 2023 19:19
Show Gist options
  • Save ibitebyt3s/8338f4aa49f6fddf59d3c68a8ec94646 to your computer and use it in GitHub Desktop.
Save ibitebyt3s/8338f4aa49f6fddf59d3c68a8ec94646 to your computer and use it in GitHub Desktop.
Get CVE details right in your terminal. Check the images below
#! /bin/zsh
# cve_info
# Docs: https://nvd.nist.gov/developers/start-here
# Get your api key here: https://nvd.nist.gov/developers/request-an-api-key
# Get CVE details right in your terminal. Sometimes I'm in the need of looking up some CVE information and copy and
# pasting each individual CVE into the web browser is too slow. Specially when dealing with nmap output or nuclei recently
# added CVE templates. This script aims to speed up the CVE details extraction. It accepts input from stidn, a file or
# as arguments. It's still a very informal script that gets the job done and a lot of optimizations can be made. Also
# worth saying that some rate limiting checks were made but aren't fully tested. Use at your own risk.
# Get an API_KEY to increase your rate limit from 5 to 50 in a rolling time window of 30 seconds
api_key="API_KEY"
NC='\033[0m' # Text Reset
BRED='\033[1;31m' # Red
BGREEN='\033[1;32m' # Green
BYELLOW='\033[1;33m' # Yellow
ON_RED='\033[41m' # Red background
BBLUE='\033[1;34m' # Blue bold
BGREEN='\033[1;32m' # Green
INFO="${BBLUE}[*]${NC}"
TASK="${BGREEN}[+]${NC}"
CVE_regex="CVE-\d{4}-\d{4,7}"
alias xcat="sed 's/\x1b\[[0-9;]*m//g'" # deletes garbage bytes from a text strem such as color codes /r
alias tr2uppercase="tr '[:lower:]' '[:upper:]'"
alias sed_delete_empty_lines='sed '\''/^\s*$/d'\'
alias sed_delete_trailing_whitespace='sed -e '\''s/^[[:space:]]*//g'\'' -e '\''s/[[:space:]]*$//g'\'
alias grep_CVEs='grep -P "$CVE_regex"'
alias unix_date="date +%s"
echo_info() {
>&2 echo "${INFO} ${1}${NC}"
}
echo_task() {
>&2 echo "${TASK} ${1}${NC}"
}
# Get the input from a file
if test -n "$1"; then
if [ -f $1 ];then
if ! [ -s $1 ]; then
echo_error "The file ${BYELLOW}$1${NC} is empty" && \
exit 1
else
input=$(cat $1 | sed_delete_empty_lines)
fi
# get the input from command arguemnts
elif (( $(sd '\s' '\n' <<< $@ | sed_delete_empty_lines | wc -l) >= 1 )) && grep_CVEs -q <<< $@; then
input=$(sd '\s' '\n' <<< $@ | sed_delete_empty_lines )
else
echo_error "The input ${BYELLOW}$1${NC} isn't a CVE" && \
exit 1
fi
# elif get the infput from stdin
elif test ! -t 0; then
input=$(cat < /dev/stdin) && \
[ -z $input ] && \
echo_error "Input from ${BYELLOW}stdin${NC} is empty" && \
exit 1
else
# input=$(cat .asns.txt | sed_delete_empty_lines | sv) &> /dev/null
[[ -z $input ]] && \
echo_error "No ${BYELLOW}input${NC} was provided" && \
exit 1
fi
IFS=$'\n'
i=1
total=$(wc -l <<< $input| sed_delete_trailing_whitespace ) # delete trailing whitespace for Mac users
rate_limit_filename=/tmp/cve_info_rate_limit.tmp
saved_time=0
request_counter=0
if [[ $api_key == "API_KEY" ]]; then
RATE_LIMIT=4
else
RATE_LIMIT=45
fi
for cve in $(echo $input); do
id=$cve
# rate limit functionality of 50 request in a 30 seconds window
# https://nvd.nist.gov/developers/start-here
# Check the time:counter values stored in a file if found
unix_date=$(unix_date)
if [ -f $rate_limit_filename ]; then
rate_limit_data=$(cat $rate_limit_filename)
saved_time=$(cut -d : -f1 <<< $rate_limit_data)
request_counter=$(cut -d : -f2 <<< $rate_limit_data)
else
saved_time=$unix_date
fi
elapsed_time=$((unix_date-saved_time))
remeaning_time=$((30-elapsed_time))
# Compare the values with the actual time and check if rate limit is not being exceeded
# if it is, sleep for the remeaning time
if [ -f $rate_limit_filename ] && [[ $request_counter -ge $RATE_LIMIT ]]; then
echo_task "sleeping for $remeaning_time seconds..."
sleep $remeaning_time
fi
# continue normal operations when done...
# request CVE information
if [[ $api_key == "API_KEY" ]]; then
json_data=$(curl "https://services.nvd.nist.gov/rest/json/cves/2.0?cveId=$id" | xcat | head -n1)
else
json_data=$(curl -H "apiKey:$api_key" "https://services.nvd.nist.gov/rest/json/cves/2.0?cveId=$id" | xcat | head -n1)
fi
# create or update the rate limit time:counter values
# if elapsed_time is less or equal to zero, update the time to current time and counter to 1
# else just update the counter
if [[ $remeaning_time -le 0 ]]; then
echo "$unix_date:1" > $rate_limit_filename
else
((request_counter++))
echo "$saved_time:$request_counter" > $rate_limit_filename
fi
# parse the data depending its CVSS version
description=$(jq -r '.vulnerabilities[0].cve.descriptions[0].value' <<< $json_data)
webpage="https://nvd.nist.gov/vuln/detail/$id"
score=$(jq '.vulnerabilities[0].cve.metrics.cvssMetricV31[0].cvssData.baseScore' <<< $json_data)
[[ $score == "null" ]] && \
score=$(jq '.vulnerabilities[0].cve.metrics.cvssMetricV2[0].cvssData.baseScore' <<< $json_data )
severity=$(jq -r '.vulnerabilities[0].cve.metrics.cvssMetricV31[0].cvssData.baseSeverity' <<< $json_data)
[[ $severity == "null" ]] && \
severity=$(jq -r '.vulnerabilities[0].cve.metrics.cvssMetricV2[0].baseSeverity' <<< $json_data)
# cvss=$(jq -r '.vulnerabilities[0].cve.metrics.cvssMetricV31[0].cvssData.vectorString' <<< $json_data | )
cvss=$(jq -r '.vulnerabilities[0].cve.metrics.cvssMetricV31[0].cvssData.vectorString' <<< $json_data | cut -d ':' -f2-)
[[ $cvss == "null" ]] && \
cvss=$(jq -r '.vulnerabilities[0].cve.metrics.cvssMetricV2[0].cvssData.vectorString' <<< $json_data )
creation_date=$(jq -r '.vulnerabilities[0].cve.published' <<< $json_data)
last_update_date=$(jq -r '.vulnerabilities[0].cve.lastModified' <<< $json_data)
# # network=$( jq '.vulnerabilities[].cve.metrics.cvssMetricV31[0].cvssData.attackVector' )
# Prettify the Score
# detect CVSS version
# version 3.0
# none 0.0
# low 0.1-3.9
# medium 4.0-6.9
# High 7.0-8.9
# Critical 9.0-10.0
# version 2.0
# low 0.0 - 3.9
# medium 4.0-6.9
# High 7.0-10.0
# if CVSS version 3
# else CVSS version 2
if grep -qE "^3" <<< $cvss; then
if grep -qE '(^0\.[1-9]$)|(^1(\.[0-9])?$)|(^2(\.[0-9])?$)|(^3(\.[0-8])?$)'<<< $score; then
score="${BGREEN}$score${NC}"
elif grep -qE '^([4-6](\.[0-9])?|6\.[0-8])$'<<< $score; then
score="${BYELLOW}$score${NC}"
elif grep -qE '^(7(\.[0-9])?|8(\.[0-8])?)$'<<< $score; then
score="${BRED}$score${NC}"
elif grep -qE '^(9(\.0)?|10(\.0)?)$' <<< $score; then
score="${ON_RED} $score ${NC}"
fi
else
if grep -qE '^(0(\.[0-9])?|[1-3](\.[0-9])?|3\.9)$' <<< $score; then
score="${BGREEN}$score${NC}"
elif grep -qE '^(4(\.[0-9])?|5(\.[0-9])?|6(\.[0-8])?)$' <<< $score; then
score="${BYELLOW}$score${NC}"
elif grep -qE '^(7(\.0)?|8(\.0)?|9(\.0)?|10(\.0)?)$' <<< $score; then
score="${BRED}$score${NC}"
fi
fi
# print the data
echo_task "CVE [$i/$total]"
echo_task "$webpage"
echo "========================================"
echo_info "ID: $id"
echo_info "Score: $score"
# echo_info "Severity: $severity"
echo_info "CVSS: $cvss"
echo_info "Creation: $creation_date"
echo_info "Last Update: $last_update_date"
echo_info "Description: $description"
echo
((i++))
done
@ibitebyt3s
Copy link
Author

input as arguments:
image

Input from stdin:
image

Input from a file:
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment