This project started in 2016 and it has been lying dormant in my archive of unfinished code, i’m going to finish it in the near future since it’s a pain reading thru the log files and trying to fix false positives.
The first problem was that GeoIP is no longer working in the same way, without it you’d miss out on a lot of the cool features like longitude/latitude for use with Google Map API and also the little country flags on each row.
I’m working on the code when i have some time over so please be patient, the parsing class needs some more cleaning up before i release it to the world.
In the meanwhile, here is a very useful bash-script for parsing Apache OWASP logs, it even has a tail function to follow the logs in real-time.
#!/usr/bin/env bash
#
# @License GNU GENERAL PUBLIC LICENSE Version 3
# @Author Nimpen <nimpen@asbra.nu>
# @Copyright 2016 ASBRA AB
logfile="$2"
if ! command -v geoiplookup &> /dev/null
then echo "Please install the geoiplookup command!" ; exit 1
fi
country_code() {
[[ $(geoiplookup $1 | head -n 1) =~ :[[:space:]]([A-Z]+) ]] && echo ${BASH_REMATCH[1]}
}
filter() {
line=$*
[[ $line =~ ^\[([^\]]*)\] ]] && OWASP_DATE="${BASH_REMATCH[1]}"
[[ $line =~ \[id[[:space:]]\"([^\"]*)\"\] ]] && OWASP_ID="${BASH_REMATCH[1]}"
[[ $line =~ \[client[[:space:]]([^:]*)\] ]] && OWASP_CLIENT="${BASH_REMATCH[1]}"
[[ $line =~ \[msg[[:space:]]\"([^\"]*)\"\] ]] && OWASP_MSG="${BASH_REMATCH[1]}"
[[ $line =~ \[hostname[[:space:]]\"([^\"]*)\"\] ]] && OWASP_SITE="${BASH_REMATCH[1]}"
[[ $line =~ \[uri[[:space:]]\"([^\"]*)\"\] ]] && OWASP_URI="${BASH_REMATCH[1]}"
[[ $line =~ \[severity[[:space:]]\"([^\"]*)\"\] ]] && OWASP_SEVERITY="${BASH_REMATCH[1]}"
if [[ $showcolor == 'true' ]] ; then
[[ $OWASP_SEVERITY == 'CRITICAL' ]] && echo -n -e "\e[41m"
[[ $OWASP_SEVERITY == 'WARNING' ]] && echo -n -e "\e[33m"
[[ $OWASP_SEVERITY == 'NOTICE' ]] && echo -n -e "\e[34m"
fi
for var in "${OPTIONS[@]}" ; do
case ${var} in
'showdate') printf "%-32s" "$OWASP_DATE" ;;
'showcountry') printf "%-4s" "$(country_code $OWASP_CLIENT)" ;;
'showclient') printf "%-17s" "$OWASP_CLIENT" ;;
'showid') printf "%-10s" "$OWASP_ID" ;;
'showseverity') printf "%-10s" "$OWASP_SEVERITY" ;;
'showsite') printf "%-${colssite}s" "$OWASP_SITE" ;;
'showuri') printf "%-${colsuri}s" "$OWASP_URI" ;;
'showmsg') printf "%-${colsmsg}s" "$OWASP_MSG" ;;
esac
done
printf "%s" " "
echo -e "\e[0m"
}
syntax() {
cat<<EOF
AsbraFW - OWASP Log Parser v1.0
Copyright 2016 Asbra AB - GPLv3
Arguments:
-f Logfile
-t type [tail,parse]
-d Date (Apache)
-i Owasp ID
-g GeoIP Country Code
-l Severity level
-c Client IP-Address
-s [cols] Site name
-u [cols] URI
-m [cols] Message
-a Ansi colorized output based on severity
Example:
$0 -t parse -f "/var/log/apache2/*error.log" -d -i -g -l -c -s 20 -u 30 -m 30 -a | more
$0 -t tail -f "/var/log/apache2/*error.log" -d -i -g -l -c -s 20 -u 30 -m 30 -a
EOF
}
declare -a OPTIONS
counter=0
while getopts "t:f:dicm:s:u:lag" o; do
case "${o}" in
t) type=${OPTARG} ;
if [ -z "${OPTARG}" -o "${OPTARG:0:1}" = "-" ]
then echo "-f requires an argument"; syntax; exit 1
fi
;;
f) logfile=${OPTARG} ;
if [ -z "${OPTARG}" -o "${OPTARG:0:1}" = "-" ]
then echo "-f requires an argument"; syntax; exit 1
fi
;;
d) OPTIONS[$counter]='showdate' ; counter=$((counter+1)) ;;
i) OPTIONS[$counter]='showid' ; counter=$((counter+1)) ;;
c) OPTIONS[$counter]='showclient'; counter=$((counter+1)) ;;
m) OPTIONS[$counter]='showmsg' ; counter=$((counter+1)) ;
if [ -z "${OPTARG}" -o "${OPTARG:0:1}" = "-" ]
then echo "-m requires an argument"; syntax; exit 1
else colsmsg=${OPTARG}
fi
;;
s) OPTIONS[$counter]='showsite' ; counter=$((counter+1)) ;
if [ -z "${OPTARG}" -o "${OPTARG:0:1}" = "-" ]
then echo "-s requires an argument"; syntax; exit 1
else colssite=${OPTARG}
fi
;;
u) OPTIONS[$counter]='showuri' ; counter=$((counter+1)) ;
if [ -z "${OPTARG}" -o "${OPTARG:0:1}" = "-" ]
then echo "-u requires an argument"; syntax; exit 1
else colsuri=${OPTARG}
fi
;;
l) OPTIONS[$counter]='showseverity'; counter=$((counter+1)) ;;
g) OPTIONS[$counter]='showcountry' ; counter=$((counter+1)) ;;
a) showcolor='true' ;;
*) syntax; exit 1 ;;
esac
counter=$((counter+1))
done
[[ -z "$logfile" ]] && { syntax ; exit 1 ; }
[[ -z "$type" ]] && { syntax ; exit 1 ; }
case "$type" in
"parse")
IFS=$'\n';
for line in $(cat $logfile | grep -i OWASP)
do filter $line
done
;;
"tail")
while read -r line
do filter $line
done < <(tail --silent -n 10 -f $logfile | grep "ModSecurity")
;;
*)
syntax
exit 1
esac
exit 0
