Mini Shell
#!/bin/bash
##############################################################################
##############################################################################
## This script is intended locate potential compromise scripts by anylizing
## the Apache domlogs.
##
## This is done by searching for POST requests which have no referrer but
## which do receive a success response. Certain other scripts are filtered
## out, as they may not indicate an actual compromise. Once a URL is
## found, the script attempts to look for a corresponding file which still
## exists and reports that file.
##
## Daniel K
##
usage() {
echo "Usage: $0 [ --help | [-i] [-a] DOMAIN [DOMAIN ...] ]"
echo ""
echo "Look for files which have had successful POSTs without a referrer in Apache domlogs."
echo "Excludes some common files, such as crons, xmlrpc, WordPress logins, etc."
echo ""
echo -e " DOMAIN\t\t\tDomain to check for POSTs. If none are given, check all domains."
echo -e " -a, --all\t\t\tCheck all domains."
echo -e " -i, --with-ips\t\tShow IP addresses which have connected to each script."
echo -e " -h, --help\t\t\tDisplay this message and exit."
echo ""
exit
}
# Parse options:
all_domains=''
with_ips=''
show_help=''
domain_array=()
for opt in "$@" ; do
case $opt in
-a | --all) all_domains=1; ;;
-i | --with-ips) with_ips=1; ;;
-h | --help) show_help=1 ; break ;;
[a-z0-9.-]*) domain_array+=("$opt"); ;;
esac
done
[[ -n "$show_help" ]] && usage
# Location of files containing VirtualHost entries
if [ -f /opt/dedrads/envinfo.py ]; then
VHOST_LOCATION="$(/opt/dedrads/envinfo.py --apache-conf)"
else
VHOST_LOCATION="$(/opt/sharedrads/envinfo.py --apache-conf)"
fi
# Location of Apache domlogs
if [ -f /etc/cpanel/ea4/is_ea4 ]; then
DOMLOG_DIR='/var/log/apache2/domlogs'
else
DOMLOG_DIR='/usr/local/apache/domlogs'
fi
# Number of lines to scan at the end of the log files
LOG_LINES=10000
if grep -q "release 7" /etc/redhat-release; then
LOCAL_IPS="$(ifconfig|awk 'match($0,/inet[ |6] *([a-f0-9.:]+)/,a){printf a[1]"|"}')LOCALIPS"
else
LOCAL_IPS="$(ifconfig|awk 'match($0,/addr: *([a-f0-9.:]+)/,a){printf a[1]"|"}')LOCALIPS"
fi
find_suspicious_posts() {
name="${1?Must include host and document root to check}"
document_root="${2?Missing either hostname or document root}"
domlog="${DOMLOG_DIR}/${name}"
[[ -f "$domlog" ]] || continue
tail -n "$LOG_LINES" "$domlog" |
awk -v local="$LOCAL_IPS" \
'$6~/POST/&&
$1!~local&&
$11~"\"-\""&&
$7!~/(cron|api)|((xmlrpc.php|wp-login.php|admin-ajax.php)$)/&&
$9~/^2/{gsub("\\?.*$","", $7); if (!x[$7]++)
{print $7}}' |
(
while read url; do
file="${document_root}${url}"
if [[ -f "$file" ]] ; then
echo "$file"
if [[ -n "$with_ips" ]] ; then
tail -n "$LOG_LINES" "$domlog" |
awk -v local="$LOCAL_IPS" \
-v url="$url" \
'$6~/POST/&&
$1!~local&&
$11~"\"-\""&&
$7~url&&
$9~/^2/{if (!x[$1]++)
{print "\t"$1}}'
fi
fi
done
)
}
search_one_domain() {
domain="${1}"
awk -v domain="$domain" \
'/ServerName/{name=$2}
/Server(Name|Alias)/&&$0~"\\y"domain"\\y"{v=1}
v&&$1~/DocumentRoot/{print name,$2;exit}' \
"$VHOST_LOCATION" |
(
read name document_root
[[ -z "$name" ]] && (>&2 echo "Cannot find domain '$domain'") && break
find_suspicious_posts "$name" "$document_root"
)
}
search_all_domains() {
awk '$1~/ServerName/{printf $2" "}$1~/DocumentRoot/{print $2}' "$VHOST_LOCATION" | (
while read name document_root; do
find_suspicious_posts "$name" "$document_root"
done
)
}
if [[ -n "$all_domains" ]] ; then
search_all_domains
exit
fi
for domain in "${domain_array[@]}" ; do
search_one_domain "$domain"
shift
done
Zerion Mini Shell 1.0