#!/usr/bin/env bash
set -o pipefail
die(){
echo "$@" >&2
exit 1
}
#RED='\033[0;31m'
RED='\033[1;31m'
YELLOW='\033[1;33m'
GREEN='\033[1;32m'
LBLUE='\033[1;34m'
LCYAN='\033[1;36m'
ORANGE='\033[0;33m'
LGREY='\033[0;37m'
BOLDJ='\033[1;37m'
NC='\033[0m' # No Color
stripAnsi(){
sed -r "s/\x1B\[([0-9]{1,3}(;[0-9]{1,2})?)?[mGK]//g"
}
trimWhitespace(){
sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'
}
#wrapped echo
wecho(){
builtin echo -e "$@" | fold -s -w 80
}
drawInBox(){
innerWidth="45"
echo -en "${LBLUE}╭"
head -c $innerWidth /dev/zero | tr '\0' '-'
echo -e "╮${NC}"
while IFS= read -r line; do
# The ansi characters mess up the string length so we need to strip them to calculate the width
stripped="$(echo -n "$line" | stripAnsi)"
leftPad=$(( ( innerWidth - ${#stripped} ) / 2))
rightPad=$(( ( innerWidth - leftPad ) - ${#stripped} ))
echo -en "${LBLUE}|${NC}"
head -c $leftPad /dev/zero | tr '\0' ' '
echo -n "$line"
head -c $rightPad /dev/zero | tr '\0' ' '
echo -e "${LBLUE}|${NC}"
done
echo -en "${LBLUE}╰"
head -c $innerWidth /dev/zero | tr '\0' '-'
echo -e "╯${NC}"
}
# gets the colour that should be output
# 0 = green
# 1 = yellow
# 2 = red
getColour(){
case "$1" in
0) echo -en "$GREEN" ;;
1) echo -en "$YELLOW" ;;
2) echo -en "$RED" ;;
esac
}
printKey(){
echo -e "Not checked\
\t${GREEN}Fine${NC}\
\t${YELLOW}Mis-configured${NC}\
\t${RED}Missing${NC}"
}
generic_version_disclosure(){
local value
local header
value="$(echo "$1" | cut -d ':' -f 2- | trimWhitespace)"
header="$(echo "$1" | cut -d ':' -f 1 | trimWhitespace)"
echo "$header" | drawInBox
wecho -e "The server responds with ${ORANGE}$value${NC} in the \
$header header"
wecho -e "This is potentially un-necesary information disclosure\n\n"
[ -n "$value" ] && return 1 || return 0
}
test_server(){
local value
value="$(echo "$1" | cut -d ':' -f 2 | trimWhitespace)"
echo "Server" | drawInBox
wecho -e "The server responds with ${ORANGE}$value${NC} in the Server header"
wecho -e "This is potentially un-necesary information disclosure\n\n"
[ -n "$value" ] && return 1 || return 0
}
test_x-powered-by(){
local value
value="$(echo "$1" | cut -d ':' -f 2 | trimWhitespace)"
echo "X-Powered-By" | drawInBox
wecho -e "The server responds with ${ORANGE}$value${NC} in the X-Powered-By header"
wecho -e "This is potentially un-necesary information disclosure\n\n"
[ -n "$value" ] && return 1 || return 0
}
test_x-xss-protection(){
local value
value="$(echo "$1" | cut -d ':' -f 2 | grep -oE '[0-9]+' )"
if [ "$value" = "1" ]; then
return 0
else
echo "X-XSS-Protection" | drawInBox
wecho -e "The X-XSS-Protection header asks browsers to try and prevent \
reflected cross site scripting attacks. It has been replaced in modern browsers \
by the content-security-policy although should still be included for the sake \
of old browsers\n\n"
return 1
fi
}
test_x-frame-options(){
local value
value="$(echo "$1" | cut -d ':' -f 2 | trimWhitespace | tr '[:lower:]' '[:upper:]')"
case "$value" in
"SAMEORIGIN"|"DENY") return 0 ;;
"ALLOW-FROM"*)
echo "X-Frame-Opitons" | drawInBox
wecho -e "The ALLOW-FROM derivative is obsolete and no longer works \
in modern browsers.\n\n"
wecho -e "The Content-Security-Policy HTTP header has a \
frame-ancestors directive which you can use instead.\n\n"
return 1
;;
*)
echo "X-Frame-Opitons" | drawInBox
wecho "The X-Frame-Options HTTP response header can be used to \
indicate whether or not a browser should be allowed to render a page in a \
,