Skip to content

Instantly share code, notes, and snippets.

@jantytgat
Last active August 8, 2025 07:54
Show Gist options
  • Select an option

  • Save jantytgat/68419642be9c068b0d28324678b1387e to your computer and use it in GitHub Desktop.

Select an option

Save jantytgat/68419642be9c068b0d28324678b1387e to your computer and use it in GitHub Desktop.
NetScaler IOC Checker
#!/bin/sh
NAME=$1
UPDATE=$2
OUTLOG=/var/tmp/$NAME.log
echo "Sending output to $OUTLOG"
echo "RUNNING CHECKS FOR $NAME AGAINST DATE $UPDATE" | tee -a $OUTLOG
echo "##### 01 - Check for modified files in /var/nsinstall with extension .php #####" | tee -a $OUTLOG
T01=$(find /var/nsinstall/ -type f -iname '*.php' -exec ls -al {} \; 2>>$OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 02 - Check for modified files in /var/nsproflog with extension .php #####" | tee -a $OUTLOG
T02=$(find /var/nsproflog/ -type f -iname '*.php' -newermt $UPDATE -exec ls -al {} \; 2>>$OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 03 - Check for modified files in /var/netscaler/ns_gui/ with extension .php #####" | tee -a $OUTLOG
T03=$(find /var/netscaler/ns_gui/ -type f -iname '*.php' -newermt $UPDATE -not -path "/var/netscaler/ns_gui/admin_ui/*" -exec ls -al {} \; 2>>$OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 04 - Check for modified files in /var/netscaler/gui/ with extension .php #####" | tee -a $OUTLOG
T04=$(find /var/netscaler/gui/ -type f -iname '*.php' -newermt $UPDATE -not -path "/var/netscaler/gui/admin_ui/*" -exec ls -al {} \; 2>>$OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 05 - Check for modified files in /var/vpn/ #####" | tee -a $OUTLOG
T05=$(find /var/vpn/ -type f -newermt $UPDATE -exec ls -al {} \; 2>>$OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 06 - Check for modified files in /var/netscaler/logon/ #####" | tee -a $OUTLOG
T06=$(find /var/netscaler/logon/ -type f -newermt $UPDATE -not -path "/var/netscaler/logon/themes/*/resources/*.xml" -exec ls -al {} \; 2>>$OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 07 - Check for modified files in /var/netscaler/logon/ with extension .php #####" | tee -a $OUTLOG
T07=$(find /var/netscaler/logon/ -type f -iname '*.php' -newermt $UPDATE -exec ls -al {} \; 2>>$OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 08 - Check for modified files in /var/python/ #####" | tee -a $OUTLOG
T08=$(find /var/python/ -type f -newermt $UPDATE -exec ls -al {} \; 2>>$OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 09 - Check files in /netscaler/ns_gui/ with extension .php #####" | tee -a $OUTLOG
echo "WARNING ---> These files may change timestamps during system reboots — use this only as an indicator, not proof." >> $OUTLOG
T09=$(find /netscaler/ns_gui/ -type f -iname '*.php' -newermt $UPDATE -not -path "/netscaler/ns_gui/admin_ui/*" -exec ls -al {} \; 2>>$OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 10 - Check files in /netscaler/gui/ with extension .php #####" | tee -a $OUTLOG
T10=$(find /netscaler/gui/ -type f -iname '*.php' -newermt $UPDATE -not -path "/netscaler/gui/admin_ui/*" -exec ls -al {} \; 2>>$OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 11 - Check files in /netscaler/portal/ with extension .php #####" | tee -a $OUTLOG
T11=$(find /netscaler/portal/ -type f -iname '*.php' -newermt $UPDATE -exec ls -al {} \; 2>>$OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 12 - Check for 'Graceful' in /var/log/httperror.log #####" | tee -a $OUTLOG
T12=$(grep "Graceful" /var/log/httperror.log | grep -v ":00:" >> $OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 13 - Check for 'Graceful' in /var/log/httperror.log.* (compressed files) #####" | tee -a $OUTLOG
T13=$(gzcat /var/log/httperror.log.*.gz | grep Graceful | grep -v ":00:" >> $OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 14 - Check for suspicious pipes #####" | tee -a $OUTLOG
T14=$(pgrep -i nsppe | xargs -I% sh -c 'lsof -p % 2>>$OUTLOG| egrep -q "PIPE" && echo "%: suspicious pipe"')
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 15 - Check files in /var/vpn/ with extension .php #####" | tee -a $OUTLOG
T15=$(find /var/vpn -regex '/var/vpn/vpn.*' -type f -iname '*.php' -exec ls -al {} \; 2>>$OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 16 - Check files in /var/netscaler/logon/LogonPoint with extension .php #####" | tee -a $OUTLOG
T16=$(find /var/netscaler/logon/LogonPoint -depth 1 -type f -iname '*.php' -exec ls -al {} \; 2>>$OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 18 - Check for '.sh' in /var/log/httperror.log* #####" | tee -a $OUTLOG
T18=$(zgrep '.sh' /var/log/httperror.log* >> $OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 19 - Check for '.php' in /var/log/httperror.log* #####" | tee -a $OUTLOG
T19=$(zgrep '.php' /var/log/httperror.log* >> $OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 20 - Check for '.pl' in /var/log/httperror.log #####" | tee -a $OUTLOG
T20=$(zgrep '.pl' /var/log/httperror.log* >> $OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 21 - Check /var/log/sh.log #####" | tee -a $OUTLOG
T21=$(zgrep -E 'database.php|/flash/nsconfig/keys/updated|/flash/nsconfig/keys|/ns_gui/vpn|LDAPTLS_REQCERT|ldapsearch|openssl|/nsconfig/ns.conf|del /etc/auth.conf|cp /usr/bin/bash|.F1.key|.F2.key|nobody' /var/log/sh.log* >> $OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 22 - Check /var/log/bash.log #####" | tee -a $OUTLOG
T22=$(zgrep -E 'database.php|/flash/nsconfig/keys/updated|/flash/nsconfig/keys|/ns_gui/vpn|LDAPTLS_REQCERT|ldapsearch|openssl|/nsconfig/ns.conf|del /etc/auth.conf|cp /usr/bin/bash|.F1.key|.F2.key|nobody' /var/log/bash.log* >> $OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 23 - Check for httpd processes running as 'nobody' #####" | tee -a $OUTLOG
T23=$(ps aux | grep nobody | grep -v '/bin/httpd' >> $OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 24 - Check /etc/crontab #####" | tee -a $OUTLOG
T24=$(grep '' /etc/crontab >> $OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 25 - Check crontab for user 'nobody' #####" | tee -a $OUTLOG
T25=$(crontab -l -u nobody >> $OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 28 - Check files in /var/core/1 #####" | tee -a $OUTLOG
T28=$(ls -ll /var/core/1 >> $OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 29 - Check for running python processes #####" | tee -a $OUTLOG
T29=$(ps -aux | grep python >> $OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 30 - Check for running perl processes #####" | tee -a $OUTLOG
T30=$(ps -aux | grep perl >> $OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 31 - Top 10 running processes #####" | tee -a $OUTLOG
T31=$(top -n 10 >> $OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 32 - Check for illegal remote commands #####" | tee -a $OUTLOG
T32=$(grep -v '127.0.0' /var/log/*.log | grep 'nc -l|/etc/passwd|curl|python -c|.php' >> $OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 33 - Check file permissions in /var #####" | tee -a $OUTLOG
T33=$(find /var -perm -4000 -user root -not -path "/var/nslog/*" -newermt $UPDATE -exec ls -l {} \; 2>>$OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 34 - Check 'nsfsyncd' process #####" | tee -a $OUTLOG
T34=$(ps aux | grep nsfsyncd >> $OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 35 - Check /var/tmp for callhome_tmps #####" | tee -a $OUTLOG
T35=$(find /var/tmp -type f -iname 'callhome_tmps*' -exec ls -al {} \; 2>>$OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 36 - Find Root-owned SUID files #####" | tee -a $OUTLOG
T36=$(find /var \( -perm -4001 -or \( -perm -4010 -group nobody \) \) -user root -exec ls -al {} \; 2>>$OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 37 - Find backdoors in rc.netscaler #####" | tee -a $OUTLOG
T37=$(grep python /flash/nsconfig/rc.netscaler >> $OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 17 - Run python script to get newest timestamps #####" | tee -a $OUTLOG
T17=$(python -c "import os, glob, time; newest_timestamp = max(os.stat(f).st_mtime for f in glob.glob('/var/nsinstall/*')); print('\n'.join(os.path.join(dirpath, f) for dir in ['/var/netscaler/logon/', '/var/python/', '/var/vpn/'] for dirpath, _, files in os.walk(dir) for f in files if os.stat(os.path.join(dirpath, f)).st_mtime > newest_timestamp))" >> $OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 26 - Check /var/log/httpaccess-vpn.log* for status code 200 but not 'CitrixReceiver'#####" | tee -a $OUTLOG
T26=$(zgrep -E -v 'CitrixReceiver' /var/log/httpaccess-vpn.log* | grep ' 200 ' >> $OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "##### 27 - Check /var/log/httpaccess-vpn.log* for 'HeadlessChrome' #####" | tee -a $OUTLOG
T27=$(zgrep 'HeadlessChrome' /var/log/httpaccess-vpn.log* >> $OUTLOG)
echo "#############################################################" >> $OUTLOG
echo "" >> $OUTLOG
echo "" >> $OUTLOG
echo "Checking results..."
RESULT=
[ -z "$T01" ] || RESULT="$T01\n"
[ -z "$T02" ] || RESULT="$RESULT$T02\n"
[ -z "$T03" ] || RESULT="$RESULT$T03\n"
[ -z "$T04" ] || RESULT="$RESULT$T04\n"
[ -z "$T05" ] || RESULT="$RESULT$T05\n"
[ -z "$T06" ] || RESULT="$RESULT$T06\n"
[ -z "$T07" ] || RESULT="$RESULT$T07\n"
[ -z "$T08" ] || RESULT="$RESULT$T08\n"
[ -z "$T09" ] || RESULT="$RESULT$T09\n"
[ -z "$T10" ] || RESULT="$RESULT$T10\n"
[ -z "$T11" ] || RESULT="$RESULT$T11\n"
[ -z "$T12" ] || RESULT="$RESULT$T12\n"
[ -z "$T13" ] || RESULT="$RESULT$T13\n"
[ -z "$T14" ] || RESULT="$RESULT$T14\n"
[ -z "$T15" ] || RESULT="$RESULT$T15\n"
[ -z "$T16" ] || RESULT="$RESULT$T16\n"
[ -z "$T17" ] || RESULT="$RESULT$T17\n"
[ -z "$T18" ] || RESULT="$RESULT$T18\n"
[ -z "$T19" ] || RESULT="$RESULT$T19\n"
[ -z "$T20" ] || RESULT="$RESULT$T20\n"
[ -z "$T21" ] || RESULT="$RESULT$T21\n"
[ -z "$T22" ] || RESULT="$RESULT$T22\n"
[ -z "$T23" ] || RESULT="$RESULT$T23\n"
[ -z "$T24" ] || RESULT="$RESULT$T24\n"
[ -z "$T25" ] || RESULT="$RESULT$T25\n"
[ -z "$T26" ] || RESULT="$RESULT$T26\n"
[ -z "$T27" ] || RESULT="$RESULT$T27\n"
[ -z "$T28" ] || RESULT="$RESULT$T28\n"
[ -z "$T29" ] || RESULT="$RESULT$T29\n"
[ -z "$T30" ] || RESULT="$RESULT$T30\n"
[ -z "$T31" ] || RESULT="$RESULT$T31\n"
[ -z "$T32" ] || RESULT="$RESULT$T32\n"
[ -z "$T33" ] || RESULT="$RESULT$T33\n"
[ -z "$T34" ] || RESULT="$RESULT$T34\n"
[ -z "$T35" ] || RESULT="$RESULT$T35\n"
[ -z "$T36" ] || RESULT="$RESULT$T36\n"
[ -z "$T37" ] || RESULT="$RESULT$T37\n"
echo "Done."
echo ""
echo ""
echo "#############################################################"
# [ -z "$RESULT" ] || RESULT="$RESULT$(ps auxd)\n$(sysctl -a netscaler.version kern.boottime)"
[ -z "$RESULT" ] || echo -e "$RESULT\n!! Scan possibly identified one or more IOCs"
[ -n "$RESULT" ] || echo "Scan OK, don't forget to look through the log file"
echo "#############################################################"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment